テキスト生成モデルに新たな知識を埋め込んでChatモデルを作る方法の模索（自己流）

# 0. きっかけ
東京大学、松尾・岩澤研究室が主催している大規模言語モデル2024って講座を受けました。
ま、この顛末は別の投稿にも書いているのでググってもらうとして、この講義の最終課題がコンペだったのですが、テキスト生成モデル（notチャットモデル）に新たに知識を入れて、優秀なChatモデルを作るというのが課題でした。
その中で僕なりのテーマとして「持っていない情報を付け加えたままChatモデルを作りたい」というのがありました。だってその方が実用出来じゃない？RAGした方がいいかもしれないけれど、通信環境を持たない環境というのも会社にはあるのでこういう自己テーマを持って臨みました。
このテーマの出口が少し見えてきたとういうお話です。

あ、これの続きね。繰り返しになることも多いのでどんどん読み飛ばしてください。w

https://qiita.com/ikedachin/items/8c31b359ec7473e00595


<br><br>




# 1. 用いるベースモデルなど
https://llmc.nii.ac.jp/topics/post-707/

すでに学習されたモデルを使います。llm-jp-3-13bというモデル。前回は3.7bでテストしていましたが、今回はぐっと大きくして13bで攻めます。


<br><br>


https://llm-jp.nii.ac.jp/

これは2024年の9月に国立情報学研究所の大規模言語モデル研究開発センターが公開したモデルで、テキスト生成モデルです。このテキスト生成モデルはチャットモデルのように質問形式で問うのではなく、入力したテキストの続きが出力されるモデルです。
つまり、以下のようなモデルです。


- 入力例
> 2024年の自民党総裁選挙は


- 出力例
> 2024年の自民党総裁選挙は高市氏と石破氏との決選投票の末、・・・（省略）

チャットモデルだと「2024年の自民党総裁選挙の結果を教えて？」みたいな感じでモデルに入力します。違い、わかりますよね。

<br>
<br>


https://huggingface.co/llm-jp/llm-jp-3-13b#pre-training

学習データについては公開されいている内容を見ましたが、wikiなんかは2023のデータセットを使っていました。また、CommonClowlのデータはどれを使ったかわからなかったのですが、実際に出力させてみると2024年8月以降の情報は全くないと思ってます。（7月以前はチェックしていません。この辺の情報に間違いなどありましたらご指摘くださいませ。）

<br>



このllm-jp-3−13bに「2024年9月、10月のニュース情報」を教え込んで、さらにチャット形式で使えるモデルを作りたいと思います。

<br>
<br>


# 2. 全体の流れ
おさらいになりますが、今回使うllm-jp-3-13bは、すでに日本語能力を充分に持ち合わせたモデルです。ですので以下の手順で学習したいと思います。

1. 継続事前学習
新たな知識を覚えさせる
1. Supervised fine tuning
Chat形式で回答できるように出力調整する

<br><br>


# 3. 知っておくべきこと
### 3-1.Transformerの構造
これはね、YouTubeで解決しましょう。AsiaSolidさん一択！
もうね、わかりやすすぎて照れちゃう。

https://youtu.be/50XvMaWhiTY?si=yJ4fKRbFwb-zwiID

Transformerの一番のコアであるMulti-Head Attentionを理解するにはこれっすね！

https://youtu.be/50XvMaWhiTY?si=1XaQiBiNsxvwNd9S


### 3-2.知識はどこに蓄積される？
Transfromerの構造（特にデコーダー側）が理解できたら次です。このKan Hatakeyamaさんのすばらしい投稿を理解しておこう。僕もこのプリファードネットワークの論文を信じて取り組んでみました。

https://note.com/kan_hatakeyama/n/n04ef3afecba9

### 3-3.LoRAによる継続事前学習の有効性
そうです。LoRAを使って学習しようと思います。だって、Googleコラボしか使う手を持っていないのですから。ｗ
Unslothのブログ記事を見ておきましょう。

https://unsloth.ai/blog/contpretraining

このブログは「LoRAつかったら継続事前学習してもちょっとあかんねん」という論文に対して、「`embed_tokens`と`lm_head`も学習させることが大事やねん！」という解説ブログ。

ここまで理解できたら次に行きましょう。

<br>
<br>


# 4.dataset
### 4-1. 継続事前学習用データ
`kajuma/CC-news-2024-July-October-cleaned`を利用させてもらいました。
前処理として以下を行いました。
1. 2024/9/1以降の記事に絞りこみ
1. タイトルと思われるテキストの削除
1. 先頭に「2024年9月1日のニュース：大谷翔平選手がホームラン・・・」と記事の前にニュースの日付を入れる

<br>



### 4-2. SFT用データ
以下のデータセットを利用させてもらいました。
- `llm-jp/magpie-sft-v1.0`からランダムに5000データ
- `DeL-TaiseiOzaki/Tengentoppa-sft-mini-vol1.0`からランダムに15000データ

<br><br>


# 5. どうやったら（ある程度）うまくいったか

## 5-1. 継続事前学習
- *r=128*  # めっちゃ巨大にした
- target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj", *"embed_tokens", "lm_head"*,]  # unslothのブログ記事を参考にした
- *lora_alpha=256*  # めっちゃ巨大にした
- *learning_rate=0.0003*  # 少し大きめに
- *embedding_learning_rate = 0.00003*  # unslothのdocumentのおすすめのlearning_rateの1/10
- *epoch=3* # しっかり学習させるイメージで


## 5-2. Supervised fine-tuning
- *r=16*  # 継続事前学習の1/8
- target_modules=["q_proj", "k_proj", "v_proj"]  # トークン同士の繋がりだけをチューニングするイメージ
- *lora_alpha=32*  # 継続事前学習の1/8
- *learning_rate=0.00003*  # 継続事前学習の1/10
- *epoch=1*


## 5-3. なんでこの設定にしたか
分厚い石板がパラメータだとしよう。この石板を掘り込んでいくのが学習過程とイメージして説明してみる。

### 5-3-1. 継続事前学習
知識を学習させたいので、石板表面にアウトラインをしっかり掘っていくイメージ。大胆に、全体をしっかり学習させることが目的。
なので、パラメータを学習させるためにLoRAの`r`を大きく（128）、ものとパラメータへの影響度を示す`lora_alpha`も大きくした。そして学習するパラメータもunslothのドキュメントおすすめの通り、`embed_tokens`と`lm_head`を追加。そして、`learning rate`も少し大きめ、epoch数も3とした。

　<br>
 
![W&B Chart 2025_1_31 23_26_22 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3655320/06b93476-b3e3-5c17-3faf-e1d2030f984c.png)
`r`を大きく設定にしたら、2epoch目に入ると大きくlossが減り、3epoch目もさらに大きくlossが下がる現象を確認。意味はわかっていないが、僕にとっては新しい挙動だった。

<br>

![W&B Chart 2025_1_31 23_26_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3655320/aff6521c-0f17-5ffa-19f1-7c2c8896f92c.png)
これは3.8bモデルで試行錯誤していた時のもので、2epochしか実行していないが、`r`を大きく取った上で、lora?alphaを大きくするとこの現象が発生した。（N数がないので断言できないけど）
これでしっかり知識を埋め込む。

<br>

### 5-3-2. Supervised fine tuningで出力調整
出力調整なので、継続事前学習で掘り込んだアウトラインを崩さぬよう、石板に施されたアウトラインを壊さないように微細な装飾を施していくイメージ。繊細に、出力だけが変化するように学習させ、出力調整することが目的。`r`もそこそこ、`lora_alpha`もそこそこ。学習するパラメータはトークン同士の関連性だけを学習させ、入出力のプロンプトを覚え込ませ、eosを出力させるイメージ。
あまり大きな工夫はしていない。強いて言うなら、あまり学習させすぎない。w

なんか、偉そうに言っているけど、先に読んだ記事や、ブログ、論文からインスパイヤしただけだ。何もわかってない。www

<br><br>

# 6. 現時点での結論
本当はいろんなパターンで学習させてもう少し探りたいのだけれど、Google Colabを小遣いの範囲で使っているので限界がある。😭

今の仮説はこうだ。
- Unslothのブログは大事だった
（継続事前学習の設定）
- LoRAの`r`、`lora_alpha`、`学習率`はめっちゃ大事だった
（継続事前学習と、Supervised finetuningのバランス）

言うなれば、継続事前学習後に局所解にあえて持っていくイメージか？？？

<br><br>

# 7. 結果
わかりやすいネタで出力させてみた。前記事で書いていた評価用データセットはボツにした。もう少し、しっかり考えたい。

### 7-1. Q: 2024年9月の自民党総裁選の決選投票の結果についてくわしく教えてください。
> 2024年9月27日に行われた自民党総裁選挙では、石破茂氏が新たな総裁として選出されました。この決定は、1回目の投票で上位2名（高市早苗氏と石破茂氏）による決選投票によって行われました。
> 
> 決選投票は以下のように進められました。
> - 一回目の投票：高市早苗氏が1位、石破茂氏が2位。
> - 決選投票：高市早苗氏が184票を獲得し、石破茂氏が194票を得て勝利しました。

決選投票の票数は間違ったみたい。
正しくは、石破氏が215票、高市氏が194票。数字的に、194は合ってるけど、高市さんでしたね。

<br>


### 7-2. Q: 2024年のワールドシリーズにおいて、大谷翔平はどこを怪我をしましたか？
> 2024年10月26日に行われた第2戦で、大谷翔平は左肩の亜脱臼により負傷しました。

詳しい回答ではないものの、正解！
もう怪我しないでよ！大谷さん！

<br>


### 7-3. Q: 2024年の衆議院選挙の結果、自公与党の結果を教えてください。
> 2024年10月27日に行われた第50回衆議院議員総選挙では、自民・公明両党が大敗し、自公連立政権は崩壊しました。この選挙で、自民と公明は、合わせて215議席（定数465）しか獲得できず、過半数割れとなりました。一方、野党側では躍進がみられ、特に日本維新の会は38議席から44議席へと大幅な増票となり、国民民主党も7議席から28議席へ大きく伸ばしました。また、共産党やれいわ新選組なども議席数を増加させましたが、社民党などは減少しています。

日本維新の会の議席数は44ではなく38議席、共産党は10→8、れいわは3→9、社民は1→1なので、いくつかの間違いがありますが、大勢は合っていそうです。テキトーでごめん


<br><br>

# 8. 今後
今回は官能評価でしたので、再度評価用データセットを作り直して検証したい。
それにしても自由に使えるGPUが欲しい。💰💰💰

<br><br>

# 9. とはいえ・・・
まだまだよくわかってねぇ。天才の頭、どっかに売ってないかな。

<br><br>