Uploaded model

  • Developed by: IWAIYuma
  • License: apache-2.0
  • Finetuned from model : llm-jp/llm-jp-3-13b

This llama model was trained 2x faster with Unsloth and Huggingface's TRL library.

サンプルコードで作成したモデルを強化学習する。

使用するデータセットは、『cyberagent/chatbot-arena-ja-calm2-7b-chat-experimental』のオープンソースを使用

https://huggingface.co./datasets/cyberagent/chatbot-arena-ja-calm2-7b-chat-experimental)

このソースは『このデータセットを用いてcalm2-7b-chatに対してDirect Preference Optimization (DPO)を行い、calm2-7b-chat-dpoを作成しました。 Instruction Tuningの評価用タスクであるELYZA-tasks-100とJapanese MT-Benchを用いてGPT-4による自動評価を行ったところ、どちらのデータセットでもcalm2-7b-chat-dpoの方がcalm2-7b-chatよりも高いスコアが得られました。』とあるため期待

◯ 参考にしたコード『自作FT済みモデルからDPOするためのサンプルコード(Unsloth最新版 2024.12.2)』にある、藤越様のコードを参考にし、RLHFをしてみました。

https://matsuolab-geniac.notion.site/FT-DPO-Unsloth-2024-12-2-bac63c15586840b9ad118f5f5b27420a

'''python

Google Colab の場合は上記の環境構築手順を行なわず、単にこのセルから実行していってください。

!pip uninstall unsloth -y !pip install --upgrade --no-cache-dir "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"

Google Colab のデフォルトで入っているパッケージをアップグレード(Moriyasu さんありがとうございます)

!pip install --upgrade torch !pip install --upgrade xformers

notebookでインタラクティブな表示を可能とする(ただし、うまく動かない場合あり)

!pip install ipywidgets --upgrade

Install Flash Attention 2 for softcapping support

import torch if torch.cuda.get_device_capability()[0] >= 8: !pip install --no-deps packaging ninja einops "flash-attn>=2.6.3" from google.colab import output output.enable_custom_widget_manager()

Hugging Face Token を指定

from huggingface_hub import login from google.colab import userdata

hf_token = userdata.get('HF_TOKEN') if hf_token: login(token=hf_token) print("Hugging Face token found and logged in.") else: print("Hugging Face token not found. Please set it using userdata.set('HF_TOKEN', '')") print(dataset['train'][0])

学習時のプロンプトフォーマットの定義

prompt = """### 指示 {}

回答

{}"""

""" formatting_prompts_func: 各データをプロンプトに合わせた形式に合わせる """ EOS_TOKEN = tokenizer.eos_token # トークナイザーのEOSトークン(文末トークン) def formatting_prompts_func(examples): input = examples["text"] # 入力データ output = examples["output"] # 出力データ text = prompt.format(input, output) + EOS_TOKEN # プロンプトの作成 return { "formatted_text" : text, } # 新しいフィールド "formatted_text" を返す pass

# 各データにフォーマットを適用

dataset = dataset.map( formatting_prompts_func, num_proc= 4, # 並列処理数を指定 )

dataset """ training_arguments: 学習の設定

  • output_dir: -トレーニング後のモデルを保存するディレクトリ

  • per_device_train_batch_size:

    • デバイスごとのトレーニングバッチサイズ
  • per_device_eval_batch_size:

    • デバイスごとの評価バッチサイズ
  • gradient_accumulation_steps:

    • 勾配を更新する前にステップを積み重ねる回数
  • optim:

    • オプティマイザの設定
  • num_train_epochs:

    • エポック数
  • eval_strategy:

    • 評価の戦略 ("no"/"steps"/"epoch")
  • eval_steps:

    • eval_strategyが"steps"のとき、評価を行うstep間隔
  • logging_strategy:

    • ログ記録の戦略
  • logging_steps:

    • ログを出力するステップ間隔
  • warmup_steps:

    • 学習率のウォームアップステップ数
  • save_steps:

    • モデルを保存するステップ間隔
  • save_total_limit:

    • 保存しておくcheckpointの数
  • max_steps:

    • トレーニングの最大ステップ数
  • learning_rate:

    • 学習率
  • fp16:

    • 16bit浮動小数点の使用設定(第8回演習を参考にすると良いです)
  • bf16:

    • BFloat16の使用設定
  • group_by_length:

    • 入力シーケンスの長さによりバッチをグループ化 (トレーニングの効率化)
  • report_to:

    • ログの送信先 ("wandb"/"tensorboard"など) """ from trl import SFTTrainer from transformers import TrainingArguments from unsloth import is_bfloat16_supported

trainer = SFTTrainer( model = model, tokenizer = tokenizer, train_dataset=dataset["train"], max_seq_length = max_seq_length, dataset_text_field="formatted_text", packing = False, args = TrainingArguments( per_device_train_batch_size = 2, gradient_accumulation_steps = 4, num_train_epochs = 1, logging_steps = 10, warmup_steps = 10, save_steps=100, save_total_limit=2, max_steps=-1, learning_rate = 2e-4, fp16 = not is_bfloat16_supported(), bf16 = is_bfloat16_supported(), group_by_length=True, seed = 3407, output_dir = "outputs", report_to = "none", ), ) #@title 学習実行 trainer_stats = trainer.train() edataset = load_dataset("elyza/ELYZA-tasks-100") edataset = edataset.remove_columns('eval_aspect') edataset = edataset.rename_columns({'input':'text'}) print(edataset['test'][0])

学習時のプロンプトフォーマットの定義

prompt = """### 指示 {}

回答

{}"""

""" formatting_prompts_func: 各データをプロンプトに合わせた形式に合わせる """ EOS_TOKEN = tokenizer.eos_token # トークナイザーのEOSトークン(文末トークン) def formatting_prompts_func(examples): input = examples["text"] # 入力データ output = examples["output"] # 出力データ text = prompt.format(input, output) + EOS_TOKEN # プロンプトの作成 return { "formatted_text" : text, } # 新しいフィールド "formatted_text" を返す pass

# 各データにフォーマットを適用

edataset = edataset.map( formatting_prompts_func, num_proc= 4, # 並列処理数を指定 )

edataset

データを確認

print(edataset["test"]["formatted_text"][3]) etrainer = SFTTrainer( model = model, tokenizer = tokenizer, train_dataset=edataset["test"], max_seq_length = max_seq_length, dataset_text_field="formatted_text", packing = False, args = TrainingArguments( per_device_train_batch_size = 2, gradient_accumulation_steps = 4, num_train_epochs = 1, logging_steps = 10, warmup_steps = 10, save_steps=100, save_total_limit=2, max_steps=-1, learning_rate = 2e-4, fp16 = not is_bfloat16_supported(), bf16 = is_bfloat16_supported(), group_by_length=True, seed = 3407, output_dir = "outputs", report_to = "none", ), ) #@title 学習実行 trainer_stats = etrainer.train()

強化学習

%%capture !pip install unsloth

Also get the latest nightly Unsloth!

!pip uninstall unsloth -y && pip install --upgrade --no-cache-dir --no-deps git+https://github.com/unslothai/unsloth.git from huggingface_hub import login from google.colab import userdata

hugging faseにlog in

hf_token = userdata.get('HF_TOKEN') if hf_token: login(token=hf_token) print("Hugging Face token found. Logged in to Hugging Face.") else: print("Hugging Face token not found. Please set it using userdata.set('HF_TOKEN', '')") from unsloth import PatchDPOTrainer PatchDPOTrainer() from unsloth import FastLanguageModel import torch max_seq_length = 2048 # Choose any! We auto support RoPE Scaling internally! dtype = None # None for auto detection. Float16 for Tesla T4, V100, Bfloat16 for Ampere+ load_in_4bit = True # Use 4bit quantization to reduce memory usage. Can be False. model, tokenizer = FastLanguageModel.from_pretrained( model_name = "IWAIYuma/llm-jp-3-13b-it_v3", # 自分がUnslothを使ってFTして、loraだけアップロードしているモデル max_seq_length = max_seq_length, dtype = dtype, load_in_4bit = load_in_4bit, token = hf_token, )

cyberagent/chatbot-arena-ja-calm2-7b-chat-experimentalデータセットの読み込み

import json import codecs from pprint import pprint from datasets import load_dataset

データセットをロード

ds = load_dataset("cyberagent/chatbot-arena-ja-calm2-7b-chat-experimental")

フィルタリング関数を定義

def filter_short_examples(example): return ( len(example['prompt']) <= 2000 and len(example['chosen']) <= 2000 and len(example['rejected']) <= 2000 )

トレーニングデータをフィルタリング

filtered_train = ds['train'].filter(filter_short_examples)

データセットをトレーニング用と評価用に分割 (80%をトレーニング用、20%を評価用)

train_size = int(0.8 * len(filtered_train)) # トレーニングデータのサイズ eval_size = len(filtered_train) - train_size # 評価データのサイズ

インデックスを順序通りに生成 (ランダム性なし)

train_indices = list(range(train_size)) # トレーニング用インデックス eval_indices = list(range(train_size, len(filtered_train))) # 評価用インデックス

トレーニングデータと評価データを選択

train_dataset = filtered_train.select(train_indices) eval_dataset = filtered_train.select(eval_indices)

データセットのサイズを出力

print(f"トレーニングデータセットのサイズ: {len(train_dataset)}") print(f"評価データセットのサイズ: {len(eval_dataset)}") pprint(train_dataset[0]) print("\n") pprint(eval_dataset[0])

一旦100までを学習

結果が良かったので修正

use_dataset = train_dataset.select(range(100))

use_dataset = train_dataset use_dataset

One must patch the DPO Trainer first!

from unsloth import PatchDPOTrainer PatchDPOTrainer()

from transformers import TrainingArguments from trl import DPOTrainer, DPOConfig from unsloth import is_bfloat16_supported

dpo_trainer = DPOTrainer( model = model, ref_model = None, args = DPOConfig( per_device_train_batch_size = 2, gradient_accumulation_steps = 4, warmup_ratio = 0.1, num_train_epochs = 1, learning_rate = 5e-6, fp16 = not is_bfloat16_supported(), bf16 = is_bfloat16_supported(), logging_steps = 1, optim = "adamw_8bit", weight_decay = 0.0, lr_scheduler_type = "linear", seed = 42, output_dir = "outputs", report_to = "none", # Use this for WandB etc ), beta = 0.1, train_dataset = use_dataset, #raw_datasets["train"], # eval_dataset = raw_datasets["test"], tokenizer = tokenizer, max_length = 2048, max_prompt_length = 1024, )

学習の開始

dpo_trainer.train()

ELYZA-tasks-100-TV データセットの読み込み。

import json datasets = [] with open("/content/elyza-tasks-100-TV_0.jsonl", "r") as f: item = "" for line in f: line = line.strip() item += line if item.endswith("}"): datasets.append(json.loads(item)) item = ""

学習したモデルを用いてタスクを実行

from tqdm import tqdm

推論するためにモデルのモードを変更

FastLanguageModel.for_inference(model)

results = [] for dt in tqdm(datasets): input = dt["input"]

prompt = f"""### 指示\n{input} 簡潔に回答してください \n### 回答\n"""

inputs = tokenizer([prompt], return_tensors = "pt").to(model.device)

outputs = model.generate(**inputs, max_new_tokens = 2048, use_cache = True, do_sample=False, repetition_penalty=1.2) prediction = tokenizer.decode(outputs[0], skip_special_tokens=True).split('\n### 回答')[-1]

results.append({"task_id": dt["task_id"], "input": input, "output": prediction})

jsonlで保存

new_model_id = "llm-jp-3-13b-it" with open(f"{new_model_id}_output.jsonl", 'w', encoding='utf-8') as f: for result in results: json.dump(result, f, ensure_ascii=False) f.write('\n')

#書き込みにログイン whf_token = userdata.get('WHF_TOKEN') if whf_token: login(token=whf_token) print("Hugging Face token found and logged in.") else: print("Hugging Face token not found. Please set it using userdata.set('HF_TOKEN', '')")

モデルとトークナイザーをHugging Faceにアップロード

new_model_id = "llm-jp-3-13b-it" new_model_id = f"{new_model_id}_RLHFv3" model.push_to_hub(new_model_id, token=whf_token, private=True) tokenizer.push_to_hub(new_model_id, token=whf_token, private=True) '''

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference API
Unable to determine this model’s pipeline type. Check the docs .

Model tree for IWAIYuma/llm-jp-3-13b-it_RLHFv3

Finetuned
(1129)
this model