File size: 13,608 Bytes
ec7ede9
2d5421f
 
 
 
 
 
 
 
 
 
 
 
ec7ede9
2d5421f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
 
 
 
 
 
ec7ede9
2d5421f
 
 
 
 
 
 
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
 
 
 
 
 
 
ec7ede9
2d5421f
ec7ede9
2d5421f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
 
ec7ede9
2d5421f
 
 
 
 
 
 
 
ec7ede9
2d5421f
ec7ede9
2d5421f
 
ec7ede9
2d5421f
ec7ede9
2d5421f
ec7ede9
2d5421f
 
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
 
 
 
ec7ede9
2d5421f
 
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
 
 
 
ec7ede9
 
2d5421f
 
 
 
 
 
 
 
 
 
ec7ede9
2d5421f
 
 
 
 
ec7ede9
2d5421f
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
 
 
 
 
 
 
 
 
 
 
 
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
ec7ede9
2d5421f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ec7ede9
2d5421f
 
 
 
 
 
 
 
ec7ede9
2d5421f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41caa56
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
---
base_model: llm-jp/llm-jp-3-13b
tags:
  - text-generation-inference
  - transformers
  - llama
  - trl
license: apache-2.0
language:
  - en
  - ja
model_creator: YukikoMatsuda
finetuned_from: llm-jp/llm-jp-3-13b

---
# Sample Use

以下は、elyza-tasks-100-TV_0.jsonl の回答用コードです

```python

# python 3.10.12
!pip install -U pip
!pip install -U transformers
!pip install -U bitsandbytes
!pip install -U accelerate
!pip install -U datasets
!pip install -U peft
!pip install -U trl
!pip install -U wandb
!pip install ipywidgets --upgrade

from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    BitsAndBytesConfig,
    TrainingArguments,
    logging,
)
from peft import (
    LoraConfig,
    PeftModel,
    get_peft_model,
)
import os, torch, gc
from datasets import load_dataset
import bitsandbytes as bnb
from trl import SFTTrainer

# Hugging Face Token
HF_TOKEN = "your_hf_token" # 任意のトークンに変更

# モデルを読み込み。
# llm-jp-3 1.8B, 3.7B, 13Bのsnapshotをダウンロード済みでmodelsディレクトリに格納してあります。
# base_model_idの値はomnicampusの環境におけるモデルのパスを表しており、それ以外の環境で実行する場合は変更の必要があります。
# その他のモデルは取得に承諾が必要なため、各自でダウンロードお願いします。
# base_model_id = "models/models--llm-jp--llm-jp-3-13b/snapshots/cd3823f4c1fcbb0ad2e2af46036ab1b0ca13192a" #Fine-Tuningするベースモデル
# omnicampus以外の環境をご利用の方は以下をご利用ください。
base_model_id = "llm-jp/llm-jp-3-13b"
new_model_id = "llm-jp-3-13b-finetune" #Fine-Tuningしたモデルにつけたい名前

"""
bnb_config: 量子化の設定

  - load_in_4bit:
      - 4bit量子化形式でモデルをロード

  - bnb_4bit_quant_type:
      - 量子化の形式を指定

  - bnb_4bit_compute_dtype:
      - 量子化された重みを用いて計算する際のデータ型

"""

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4", # nf4は通常のINT4より精度が高く、ニューラルネットワークの分布に最適です
    bnb_4bit_compute_dtype=torch.bfloat16,
)

"""
model: モデル

  - base_model:
      - 読み込むベースモデル (事前に定義したもの)

  - quantization_config:
      - bnb_configで設定した量子化設定

  - device_map:
      - モデルを割り当てるデバイス (CPU/GPU) "auto"で自動に割り当てられます。

tokenizer: トークナイザー

  - base_model:
      - 読み込むベースモデル (事前に定義したもの)

  - trust_remote_code:
      - リモートコードの実行を許可 (カスタムモデルなど)
"""
model = AutoModelForCausalLM.from_pretrained(
    base_model_id,
    quantization_config=bnb_config,
    device_map="auto"
)

tokenizer = AutoTokenizer.from_pretrained(base_model_id, trust_remote_code=True)

"""
find_all_linear_names: モデル内の4bit量子化線形層を探します。
"""

def find_all_linear_names(model):
    cls = bnb.nn.Linear4bit # 4bit量子化線形層クラスを指定
    lora_module_names = set() # ここに取得した線形層を保持します。

    # モデル内の全てのモジュールを探索します
    for name, module in model.named_modules():
        if isinstance(module, cls): # モジュールが4bit量子化線形層の場合
            names = name.split('.') # モジュールの名前を分割 (ネストされてる際などに対処)
            lora_module_names.add(names[0] if len(names) == 1 else names[-1]) # 最下層の名前をlora_module_namesに追加

    # 'lm_head' は16ビット演算の際に除外する必要があるため、lora_module_namesから削除
    if 'lm_head' in lora_module_names:
        lora_module_names.remove('lm_head')

    return list(lora_module_names) # lora_module_namesをリストに変換して返します。

modules = find_all_linear_names(model)

"""
peft_config: PEFTの構成設定

  - r
      - LoRA のランク (4, 8, 16 ,32...)
      - 増やすほど学習が捗るが, 過学習のリスクも高まるので注意

  - lora_alpha
      - LoRAのスケーリング係数

  - lora_dropout
      - ドロップアウト率(過学習を防ぐための割合)

  - bias
      - バイアス項の扱い ("none"の場合、LoRAはバイアスを学習しない)

  - task_type
      - タスクタイプ

  - target_modules
      - LoRAを適用するターゲットモジュール (前のコードで特定した層)
"""

peft_config = LoraConfig(
    r=16,
    lora_alpha=32,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=modules,
)

model = get_peft_model(model, peft_config)

from google.colab import drive
drive.mount('/content/drive')

import json

file_path = '/ICHIKARA|Distribution20241221_all/ichikara-instruction-003-001-1.json'

# JSON ファイルを開く
with open(file_path, 'r', encoding='utf-8') as f:
    data = json.load(f)

# データの確認
print(data)

"""
学習に用いるデータセットの指定
今回はLLM-jp の公開している Ichikara Instruction を使います。データにアクセスするためには申請が必要ですので、使いたい方のみ申請をしてください。
Ichikara Instruciton を Hugging Face Hub にて公開することはお控えください。
また、CC-BY-NC-SAですのでモデルはライセンスを継承する前提でお使いください。

下記のリンクから申請を終えた先に Google Drive があり、Distribution20241221_all というフォルダごとダウンロードしてください。
今回は「ichikara-instruction-003-001-1.json」を使います。必要であれば展開(!unzip など)し、データセットのパスを適切に指定してください。
omnicampusの開発環境では取得したデータを左側にドラッグアンドドロップしてお使いください。

https://liat-aip.sakura.ne.jp/wp/llmのための日本語インストラクションデータ作成/llmのための日本語インストラクションデータ-公開/
関根聡, 安藤まや, 後藤美知子, 鈴木久美, 河原大輔, 井之上直也, 乾健太郎. ichikara-instruction: LLMのための日本語インストラクションデータの構築. 言語処理学会第30回年次大会(2024)

"""
ichikara_file_pass = "/ICHIKARA|Distribution20241221_all/ichikara-instruction-003-001-1.json"

dataset = load_dataset("json", data_files=ichikara_file_pass)
dataset

# 学習時のプロンプトフォーマットの定義
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

# データを確認
print(dataset["train"]["formatted_text"][3])

# データをtrainデータとtestデータに分割 (test_sizeの比率に)
# dataset = dataset["train"].train_test_split(test_size=0.1)
# dataset

"""
training_arguments: 学習の設定

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

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

  - per_device_
  _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"など)
"""

training_arguments = TrainingArguments(
    output_dir=new_model_id,
    per_device_train_batch_size=1,
    gradient_accumulation_steps=2,
    optim="paged_adamw_32bit",
    num_train_epochs=1,
    logging_strategy="steps",
    logging_steps=10,
    warmup_steps=10,
    save_steps=100,
    save_total_limit = 2,
    max_steps = -1,
    learning_rate=5e-5,
    fp16=False,
    bf16=False,
    seed = 3407,
    group_by_length=True,
    report_to="none"
)

"""
SFTTrainer: Supervised Fine-Tuningに関する設定

  - model:
      - 読み込んだベースのモデル

  - train_dataset:
      - トレーニングに使用するデータセット

  - eval_dataset:
      - 評価に使用するデータセット

  - peft_config:
      - PEFT(Parameter-Efficient Fine-Tuning)の設定(LoRAを利用する場合に指定)

  - max_seq_length:
      - モデルに入力されるシーケンスの最大トークン長

  - dataset_text_field:
      - データセット内の学習に使うテキストを含むフィールド名

  - tokenizer:
      - モデルに対応するトークナイザー

  - args:
      - トレーニングに使用するハイパーパラメータ(TrainingArgumentsの設定を指定)

  - packing:
      - 入力シーケンスのパッキングを行うかどうかの設定 (False に設定することで、各入力を独立して扱う)
"""
trainer = SFTTrainer(
    model=model,
    train_dataset=dataset["train"],
    peft_config=peft_config,
    max_seq_length= 512,
    dataset_text_field="formatted_text",
    tokenizer=tokenizer,
    args=training_arguments,
    packing= False,
)

model.config.use_cache = False # キャッシュ機能を無効化
trainer.train() # トレーニングを実行

# タスクとなるデータの読み込み。
# omnicampusの開発環境では、左にタスクのjsonlをドラッグアンドドロップしてから実行。
import json

elyza_file_pass = "/elyza-tasks-100-TV_0.jsonl"

datasets = []
with open(elyza_file_pass, "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

results = []
for data in tqdm(datasets):

  input = data["input"]

  prompt = f"""### 指示
  {input}
  ### 回答
  """

  tokenized_input = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt").to(model.device)
  attention_mask = torch.ones_like(tokenized_input)

  with torch.no_grad():
      outputs = model.generate(
          tokenized_input,
          attention_mask=attention_mask,
          max_new_tokens=100,
          do_sample=False,
          repetition_penalty=1.2,
          pad_token_id=tokenizer.eos_token_id
      )[0]
  output = tokenizer.decode(outputs[tokenized_input.size(1):], skip_special_tokens=True)

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

# こちらで生成されたjsolを提出してください。
# 本コードではinputとeval_aspectも含んでいますが、なくても問題ありません。
# 必須なのはtask_idとoutputとなります。
import re
jsonl_id = re.sub(".*/", "", new_model_id)
with open(f"./{jsonl_id}-outputs.jsonl", 'w', encoding='utf-8') as f:
    for result in results:
        json.dump(result, f, ensure_ascii=False)  # ensure_ascii=False for handling non-ASCII characters
        f.write('\n')

from google.colab import files
files.download(f"./{jsonl_id}-outputs.jsonl")

# モデルとトークナイザーをHugging Faceにアップロード
model.push_to_hub(new_model_id, token=HF_TOKEN, private=True) # Online saving
tokenizer.push_to_hub(new_model_id, token=HF_TOKEN, private=True) # Online saving

"""https://liat-aip.sakura.ne.jp/wp/llmのための日本語インストラクションデータ作成/llmのための日本語インストラクションデータ-公開/

関根聡, 安藤まや, 後藤美知子, 鈴木久美, 河原大輔, 井之上直也, 乾健太郎. ichikara-instruction: LLMのための日本語インストラクションデータの構築. 言語処理学会第30回年次大会(2024)
"""

```

# データセット名: Ichikara Instruction
ライセンス: CC-BY-NC-SA <br>
データセット申請: https://liat-aip.sakura.ne.jp/wp/llmのための日本語インストラクションデータ作成/llmのための日本語インストラクションデータ-公開/