Nishi0923 commited on
Commit
03171a5
1 Parent(s): 60d178f

Upload llm-jp-3-13b_train.py

Browse files
Files changed (1) hide show
  1. llm-jp-3-13b_train.py +168 -0
llm-jp-3-13b_train.py ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
2
+ from unsloth import FastLanguageModel
3
+ import torch
4
+ from datasets import load_dataset, concatenate_datasets
5
+
6
+ from trl import SFTTrainer
7
+ from transformers import TrainingArguments
8
+ from unsloth import is_bfloat16_supported
9
+
10
+ max_seq_length = 512 # unslothではRoPEをサポートしているのでコンテキスト長は自由に設定可能
11
+ dtype = None # Noneにしておけば自動で設定
12
+ load_in_4bit = True # 今回は8Bクラスのモデルを扱うためTrue
13
+
14
+ model_id = "llm-jp/llm-jp-3-13b"
15
+ new_model_id = "llm-jp-3-13b-it" #Fine-Tuningしたモデルにつけたい名前、it: Instruction Tuning
16
+ # FastLanguageModel インスタンスを作成
17
+ model, tokenizer = FastLanguageModel.from_pretrained(
18
+ model_name=model_id,
19
+ dtype=dtype,
20
+ load_in_4bit=load_in_4bit,
21
+ trust_remote_code=True,
22
+ )
23
+
24
+ # SFT用のモデルを用意
25
+ model = FastLanguageModel.get_peft_model(
26
+ model,
27
+ r = 32,
28
+ target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
29
+ "gate_proj", "up_proj", "down_proj",],
30
+ lora_alpha = 32,
31
+ lora_dropout = 0.05,
32
+ bias = "none",
33
+ use_gradient_checkpointing = "unsloth",
34
+ random_state = 3407,
35
+ use_rslora = False,
36
+ loftq_config = None,
37
+ max_seq_length = max_seq_length,
38
+ )
39
+
40
+
41
+ datasets_list = [
42
+ "/home/knishizawa/Matsuo_AI/LLM_Course2024/Distribution20241221_all/ichikara-instruction-003-001-1.json",
43
+ "/home/knishizawa/Matsuo_AI/LLM_Course2024/Distribution20241221_all/ichikara-instruction-003-001-2.1.json",
44
+ "/home/knishizawa/Matsuo_AI/LLM_Course2024/Distribution20241221_all/ichikara-instruction-003-001-2.2.json",
45
+ "/home/knishizawa/Matsuo_AI/LLM_Course2024/Distribution20241221_all/ichikara-instruction-003-001-5.1.json",
46
+ "/home/knishizawa/Matsuo_AI/LLM_Course2024/Distribution20241221_all/ichikara-instruction-003-001-5.2.json",
47
+ "/home/knishizawa/Matsuo_AI/LLM_Course2024/Distribution20241221_all/ichikara-instruction-003-002-1.json",
48
+ "/home/knishizawa/Matsuo_AI/LLM_Course2024/Distribution20241221_all/ichikara-instruction-003-003-1.json"
49
+ ]
50
+
51
+ valid_datasets = []
52
+
53
+ # 学習時のプロンプトフォーマットの定義
54
+ prompt = """### 指示
55
+ {}
56
+ ### 回答
57
+ {}"""
58
+ EOS_TOKEN = tokenizer.eos_token # トークナイザーのEOSトークン
59
+
60
+ # フォーマット関数
61
+ def formatting_prompts_func(examples):
62
+ input_text = examples["text"]
63
+ output_text = examples["output"]
64
+ text = prompt.format(input_text, output_text) + EOS_TOKEN
65
+ return { "formatted_text": text }
66
+
67
+ # データセットのロードとフォーマット
68
+ for file in datasets_list:
69
+ try:
70
+ dataset = load_dataset("json", data_files=file, split="train")
71
+ dataset = dataset.map(formatting_prompts_func, num_proc=4)
72
+ valid_datasets.append(dataset)
73
+ print(f"成功: {file} - {len(dataset)} 件ロード")
74
+ # データ確認
75
+ print(dataset[3]["formatted_text"])
76
+ except Exception as e:
77
+ print(f"エラー: {file} - {e}")
78
+
79
+ # マージと保存
80
+ if valid_datasets:
81
+ merged_dataset = concatenate_datasets(valid_datasets)
82
+ if len(merged_dataset) > 0:
83
+ save_dir = "/home/knishizawa/Matsuo_AI/LLM_Course2024/merged_dataset"
84
+ merged_dataset.save_to_disk(save_dir)
85
+ print(f"マージされたデータセットが {save_dir} に保存されました。")
86
+ else:
87
+ print("マージされたデータセットが空です。")
88
+ else:
89
+ print("有効なデータセットが見つかりませんでした。")
90
+
91
+
92
+ trainer = SFTTrainer(
93
+ model = model,
94
+ tokenizer = tokenizer,
95
+ train_dataset=merged_dataset,
96
+ max_seq_length = max_seq_length,
97
+ dataset_text_field="formatted_text",
98
+ packing = False,
99
+ args = TrainingArguments(
100
+ per_device_train_batch_size = 2,
101
+ gradient_accumulation_steps = 4,
102
+ num_train_epochs = 1,
103
+ logging_steps = 10,
104
+ warmup_steps = 10,
105
+ save_steps=100,
106
+ save_total_limit=2,
107
+ max_steps=-1,
108
+ learning_rate = 2e-4,
109
+ fp16 = not is_bfloat16_supported(),
110
+ bf16 = is_bfloat16_supported(),
111
+ group_by_length=True,
112
+ seed = 3407,
113
+ output_dir = "outputs",
114
+ report_to = "none",
115
+ ),
116
+ )
117
+
118
+ # 学習実行
119
+ trainer_stats = trainer.train()
120
+ # モデルの保存ディレクトリ
121
+ save_dir = "./saved_model"
122
+ # モデルの保存
123
+ model.save_pretrained(save_dir)
124
+ # トークナイザの保存 (必要に応じて)
125
+ tokenizer.save_pretrained(save_dir)
126
+ print(f"モデルが {save_dir} に保存されました。")
127
+
128
+
129
+
130
+ # ELYZA-tasks-100-TVの読み込み。事前にファイルをアップロードしてください
131
+ # データセットの読み込み。
132
+ # omnicampusの開発環境では、左にタスクのjsonlをドラッグアンドドロップしてから実行。
133
+ import json
134
+ datasets = []
135
+ with open("./elyza-tasks-100-TV_0.jsonl", "r") as f:
136
+ item = ""
137
+ for line in f:
138
+ line = line.strip()
139
+ item += line
140
+ if item.endswith("}"):
141
+ datasets.append(json.loads(item))
142
+ item = ""
143
+
144
+ # 学習したモデルを用いてタスクを実行
145
+ from tqdm import tqdm
146
+
147
+ # 推論するためにモデルのモードを変更
148
+ FastLanguageModel.for_inference(model)
149
+
150
+ results = []
151
+ for dt in tqdm(datasets):
152
+ input = dt["input"]
153
+
154
+ prompt = f"""### 指示\n{input}\n### 回答\n"""
155
+
156
+ inputs = tokenizer([prompt], return_tensors = "pt").to(model.device)
157
+
158
+ outputs = model.generate(**inputs, max_new_tokens = 512, use_cache = True, do_sample=False, repetition_penalty=1.2)
159
+ prediction = tokenizer.decode(outputs[0], skip_special_tokens=True).split('\n### 回答')[-1]
160
+
161
+ results.append({"task_id": dt["task_id"], "input": input, "output": prediction})
162
+
163
+ # jsonlで保存
164
+ with open(f"{new_model_id}_output.jsonl", 'w', encoding='utf-8') as f:
165
+ for result in results:
166
+ json.dump(result, f, ensure_ascii=False)
167
+ f.write('\n')
168
+