Views
No views yet
llm-jp/llm-jp-3-13b などの事前学習済みモデル1!pip uninstall unsloth -y
2!pip install --upgrade --no-cache-dir "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
3!pip install --upgrade torch
4!pip install --upgrade xformers
5# notebookでインタラクティブ表示を可能にする(うまく動かない場合があります)
6!pip install ipywidgets --upgrade
7
8# Install Flash Attention 2 for softcapping support
9import torch
10if torch.cuda.get_device_capability()[0] >= 8:
11 !pip install --no-deps packaging ninja einops "flash-attn>=2.6.3"
121# llm-jp/llm-jp-3-13b を4bit量子化(qLoRA)でロード
2from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
3from unsloth import FastLanguageModel
4import torch
5
6max_seq_length = 512 # unslothではRoPEをサポートしているので自由に設定可能
7dtype = None # Noneにしておけば自動設定
8load_in_4bit = True # 今回は8Bクラスのモデルを扱うためTrue
9
10model_id = "llm-jp/llm-jp-3-13b"
11new_model_id = "llm-jp-3-13b-it" # Fine-tuning後のモデル名
12
13# FastLanguageModel インスタンスを作成
14model, tokenizer = FastLanguageModel.from_pretrained(
15 model_name=model_id,
16 dtype=dtype,
17 load_in_4bit=load_in_4bit,
18 trust_remote_code=True,
19)
20
21# LoRA SFT用のモデルを用意
22model = FastLanguageModel.get_peft_model(
23 model,
24 r=32,
25 target_modules=[
26 "q_proj", "k_proj", "v_proj", "o_proj",
27 "gate_proj", "up_proj", "down_proj"
28 ],
29 lora_alpha=32,
30 lora_dropout=0.05,
31 bias="none",
32 use_gradient_checkpointing="unsloth",
33 random_state=3407,
34 use_rslora=False,
35 loftq_config=None,
36 max_seq_length=max_seq_length,
37)# Hugging Face Token を指定
# 下記 URL で発行したトークンを HF_TOKEN に入れてください
# https://huggingface.co/settings/tokens
HF_TOKEN = "YOUR_KEY"from datasets import load_dataset
# データファイルを指定
dataset = load_dataset("json", data_files="任意のjsonファイル.json")prompt = """### 指示
{}
### 回答
{}"""
EOS_TOKEN = tokenizer.eos_token
def formatting_prompts_func(examples):
input_text = examples["text"]
output_text = examples["output"]
text = prompt.format(input_text, output_text) + EOS_TOKEN
return {"formatted_text": text}
# データをフォーマットして新しいフィールドに格納
dataset = dataset.map(
formatting_prompts_func,
num_proc=4, # 並列処理数
)
datasetfrom 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",
),
)trainer_stats = trainer.train()
---
追加学習の例(ELYZAデータセット)
下記は、別途 ELYZA データセットを用いて追加学習を行う例です。
---
from datasets import load_dataset
from transformers import TrainingArguments, Trainer
# 1. データセットのロード
elyza_dataset = load_dataset("elyza/ELYZA-tasks-100")
# 2. トークナイズと前処理
def preprocess_function(examples):
inputs = examples["input"]
outputs = examples["output"]
# 入力データをトークナイズ
model_inputs = tokenizer(inputs, padding="max_length", truncation=True, max_length=512)
# 出力データ(ラベル)をトークナイズ
labels = tokenizer(outputs, padding="max_length", truncation=True, max_length=512)["input_ids"]
model_inputs["labels"] = labels
return model_inputs
tokenized_elyza_dataset = elyza_dataset.map(preprocess_function, batched=True)
# 3. トレーニング設定
additional_training_args = TrainingArguments(
output_dir="./elyza_additional_training",
evaluation_strategy="steps",
eval_steps=50,
learning_rate=5e-5,
per_device_train_batch_size=4,
per_device_eval_batch_size=4,
num_train_epochs=3,
weight_decay=0.01,
save_total_limit=2,
save_steps=50,
resume_from_checkpoint=True,
logging_dir="./logs",
logging_steps=10,
)
# 4. トレーナーの作成
additional_trainer = Trainer(
model=trainer.model, # 既存のモデルを再利用
args=additional_training_args,
train_dataset=tokenized_elyza_dataset["test"], # ELYZAのデータはtest分割のみ
eval_dataset=tokenized_elyza_dataset["test"],
)
# 5. 追加学習の実行
trainer_stats = additional_trainer.train()
# 6. 学習済みモデルの保存
additional_trainer.save_model("./fine_tuned_model_elyza")
tokenizer.save_pretrained("./fine_tuned_model_elyza")import json
datasets = []
with open("./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_text = dt["input"]
prompt = f"""### 指示\n{input_text}\n### 回答\n"""
inputs = tokenizer([prompt], return_tensors="pt").to(model.device)
outputs = model.generate(
**inputs,
max_new_tokens=512,
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_text, "output": prediction})import re
renamed_model_name = re.sub(r'[^/]+/', '', new_model_id) # パス要素を取り除く
with open(f"{renamed_model_name}_output.jsonl", 'w', encoding='utf-8') as f:
for result in results:
json.dump(result, f, ensure_ascii=False)
f.write('\n')
---
モデルとアダプタの保存
学習後、LoRAアダプタを Hugging Face Hub にアップロードします。
---
new_model_id = "midcentury/llm-jp-3-13b-it" # アップロード先
model.push_to_hub_merged(
new_model_id,
tokenizer=tokenizer,
save_method="lora",
token=HF_TOKEN,
private=True #publicの際はFalseに変更
)• モデル公開時: 公開前に、ライセンス要件や他者の権利をすべて満たしているか確認してください。
• ライセンス: データセットやベースモデルのライセンスに従い、適切にご利用ください。• Developed by: midcentury
• License: Apache License 2.0
• Finetuned from: llm-jp/llm-jp-3-13b