大きな言語モデルは「何でも知っている」ように見えますが、日常会話そのものに必要な言葉は、実はそれほど多くありません。語彙を日常語の5,000語に絞り、モデルも小さくしたら、どこまで会話らしくなるのか。それを確かめるために、小型のGPTをゼロから作りました。
結論から書くと、あいさつ、道案内、体調、予定のような定番の受け答えは自然な英語で返せました。一方で、自由な会話は数ターンで話題がずれます。この記事は、その過程と数字の記録です。
設定
| 項目 | 内容 |
|---|---|
| 言語 | 英語 |
| 語彙 | 日常語5,000語(Oxford 5000 相当をもとにした許可リスト。機能語と活用形を含み、会話用に約50語を追加) |
| モデル | GPT型、8層・埋め込み384・6ヘッド、約1,614万パラメータ |
| 事前学習 | コーパス 約465万文(約5,210万トークン)、5エポック |
| 追加学習 | 会話 約7.1万件(のち、約11.8万件に拡張) |
| 学習環境 | Google Colab(T4、無料枠) |
| データ生成 | DeepSeek Flash(API)、合計約16.5ドル |
手順
1. 事前学習用の文を作る
人手で数百万文を集めるのは現実的ではないので、「テンプレートを作り、スロットの語を差し替えて増やす」方法を取りました。
- DeepSeek に、許可リストの語だけを使った文型(テンプレート)を大量に書いてもらう。
- 各テンプレートの名詞や形容詞のスロットに、語彙リストの語を入れて文を増やす。
- すべての文について、許可リスト外の語が含まれていないかを機械的に検査し、外れたものを捨てる。
結果は、元のテンプレートが約8.7万種、文が4,647,510文(約5,210万トークン)で、費用は5.86ドルでした。
2. トークナイザーと事前学習
トークナイザーは、このコーパスで語彙5,000のBPEを学習しました。「5,000語」と「5,000トークン」は別のものです。頻出語は1トークンに収まりますが、珍しい語は2〜3個に分かれます。
モデルのサイズは、最初は約2,790万パラメータで設計していました。コーパスが5,210万トークンと分かった時点で、データ量に対して大きすぎると判断し、約1,614万パラメータに縮めています。
Colab(T4)で5エポック、7,950ステップを回し、検証データの val_loss は 1.566 でした。生成させると、たとえば次のような文が出ます。
She keeps the egg for a few minutes and then eats it.
文法は崩れていません。ただし、この検証データは学習データと同じテンプレートから作った文を含むので、val_loss は未知の文に対する実力より良く出ている可能性が高いです。
3. 会話データを作る
事前学習の時点では、単文しか見ていません。このままでは、質問に答えるのではなく、「文の続きを書く」だけです。そこで会話データを作りました。
- DeepSeek に、日常の30場面で4〜8往復の会話を書いてもらい、語彙フィルタを通す。
- 費用の上限を10ドルにして生成し、70,971会話が残った。
- 1会話は平均で約104トークン、最長でも232トークン。コンテキスト長は256にした。
最初の試作では、書かれた会話のうち語彙フィルタを通ったのは約半数で、残りは語彙外の語を含んでいました。落ちた語を集計すると、okay、sorry、phone、milk などの日常語が、手元の許可リストに入っていないことが分かりました。「5,000語で日常会話には足りる」という前提そのものは変えていませんが、リストの中身は点検が必要だったということです。承認のうえで約50語を会話用に追加しましたが、その後の本番でも、書式が正しい会話の約3割(29,182件)が語彙外で落ちています。
4. 公開データは使わなかった
DailyDialog という公開の会話データも試しました。13,118会話のうち、語彙フィルタを通ったのは1,543会話(約12%)で、人名や国名を許しても約2,700会話でした。ライセンスが非商用であることも踏まえて、採用は見送りました。
5. 会話の追加学習(SFT)
書式は、<user> 発言 <bot> 返事 <eos> の繰り返しです。特殊トークンを3つ足しました(将来の記憶枠用の <memory> を含む)。損失は、botの返事と直後の終了記号だけに掛けます。ユーザーの発言は学習しません。
位置埋め込みは、事前学習の128から256に広げました。129以降の位置は新しく初期化しています。
Colabで3エポック学習し、val_loss(botの返事のみ)は 7.05 から 1.289 まで下がりました。
6. スロット置換で会話を増やす
追加のAPI生成は費用がかかります。そこで、既存の会話の曜日・色・ペットの名前などを差し替えて増やしました。同じ会話の中では、同じ語を同じ語に置き換えます。意味が崩れやすい会話(「weekend」を含む会話や、食べ物に色が付く会話など)は除外しました。検証用の1,000会話は元のまま分け、変種は学習側だけに入れています。
結果は117,899会話です。同じ条件で学習し直すと val_loss は 1.3125 でした。検証用の会話が前回と別のセットなので、1.289 との単純な比較はできません。チャットの出力を見ても、はっきりした差は確認できませんでした。
結果
うまくいった例
You: Hi! How are you today?
Bot: I'm good, thanks. How about you?
You: I am a little tired. I did not sleep well.
Bot: That's too bad. You should rest a bit.
You: Excuse me, where is the station?
Bot: Go straight and turn left at the bank. It is near.
You: How long does it take to walk there?
Bot: About five minutes. You can see the river.
崩れる例
(入力のスペルミスや記号は、実際に入力したままです)
You: Do you like reading books
Bot: Yes, I read every night.
You: What kind of books you like?
Bot: I like stories about people and stories.
You: I see,I like some Science fiction.
Bot: That is interesting. Do you ever read?
You: Yes I read some stories about some alien in Mars.
Bot: I should try that. I want to learn more about the environment.
You: Environment?Great!
Bot: Maybe we can do it.
読書の話題は数ターン続きます。ただ、すでに答えた話題を聞き直したり、直前の発言とつながらない返事をしたりします。夕食の相談に対する「Maybe soup and bread. It helps me a day.」のように、文としておかしい返事も混ざります。
分かったこと
1. 定番の受け答えには、小さなモデルでも十分だった。 あいさつ、道案内、体調のような、型のある会話は自然に返せます。
2. 品質を決めるのは、データ量より会話の型の種類らしい。 チンチラの目安(パラメータ1個あたり約20トークン)で見ると、事前学習の量はほぼ足りていました。一方で、会話の冒頭の発言は約4万種にとどまり、発言数が8の会話が95%を占めています。スロット置換は語の種類を増やしますが、会話の型は増やしません。拡張データでの追加学習では、val_lossが途中から横ばいになり、train_lossだけが下がり続けました。型の少なさと関係している可能性があると見ています。これは観察からの推測で、追加の会話データで確かめてはいません。
3. 語彙リストの点検は、機械的にやる。 「okay」や「sorry」が許可リストに入っていないことは、落ちた語の集計を取って初めて分かりました。
4. 生成の確認は、学習済みの重みで行う。 途中で、チャットの出力が単語の羅列になったことがありました。学習前の重みで生成していた可能性が高いと見ています(その時点の状態は確認できていません)。生成の前に、保存した重みのステップ数とval_lossを表示するようにしてからは、同じ症状は出ていません。
限界
- 自由会話で話題がずれ、既出の質問を繰り返す。
- スペルミス、語彙外の語、全角の記号に弱い。
- 評価は少数の会話の目視と、val_lossだけで、定量的なチャット評価は行っていない。
- 検証データに近い文が学習データにも入っているため、val_lossは楽観的である。
費用と環境
| 項目 | 費用 |
|---|---|
| 事前学習用の文の生成(DeepSeek) | 5.86ドル |
| 会話データの生成(DeepSeek) | 約10ドル |
| 試作 | 約0.6ドル |
| 学習(Colab T4) | 無料枠 |
学習時間は、会話の追加学習が約25分(元データ)と約43分(拡張データ)でした(Colab T4)。事前学習の所要時間は計っていません。
今後
もう一度やるなら、会話の型を増やすのが先だと考えています。冒頭の発言が重複しないよう指示し、10発言以上の会話を混ぜて生成します。次に、モデルを大きくするか、過去の会話を外部から差し込む仕組み(RAG)を試します。
作ったプログラム(トークナイザー学習、会話生成、スロット置換、Colab用ノートブック)とデータは、再現手順とあわせて手元に整理してあります。