zxell.ai
開発記録 / review20
この記録は、プロジェクトの作業報告(報告 → アーキテクトの回答)を公開用に編集したものです。サーバ運用・セキュリティに関わる部分を省略しています(編集方針)。

review20: 「val/test が 100% 日本語」問題のかみ砕き説明と分割方針の提案 / ja 連結の重複除去を実装(ja 文字数 −12%)/ tokenizer_report.md 再生成

作成日: 2026-09-27 対象: review19 確認事項 1(val/test 分割)へのご質問と、9/20 に持ち越した 2 件(ja 連結の重複対策、 tokenizer_report.md の再出力)への対応。

省略: 同時期のネットワーク障害への言及
省略: 下書き段階の要旨(下の「要旨」と重複)

要旨

  1. 「val/test が日本語だけ」が困る理由をかみ砕くと: 英・独・仏の記事が 1 件残らず教科書(train)側に入ってしまい、「初見の文章でどれだけ当てられるか」を測る問題用紙が日本語しか無い、ということです(2 章)
  2. 原因を掘ると新事実: en/de/fr の収集は 2023-05-28 に同日で止まり、ja だけ 2024-02 まで続いていた。単一の日付で末尾を切れば、日本語しか残らないのは必然でした(3 章)
  3. 分割方針は A'(言語別・記事数ベースで末尾を切る)を推奨します。review19 の A(言語別・3 か月)は en の test が 26.6 万記事(6.7%)と過大になるため修正しました(4 章)
  4. ja 連結の重複除去を実装・コミット済み。ja の全記事で文字数 −12.06%(4.57 億字 → 4.02 億字)。 title の重複は記事の 87.5% で発生していました(5 章)
  5. トークナイザの比較レポートを再生成しました(6 章)
  6. ついでに HTML 残骸の規模を調べたところ 無視できる量(タグ付き本文 0.005%)でした(7 章)

確認事項 1〜3(10 章)にご回答いただければ、再エンコード(約 2 時間)を 1 回で済ませます。


1. 前提: train / val / test の役割

分割役割たとえ
trainモデルが学習する(何周も読む)教科書
val学習の途中で「ちゃんと伸びているか」「過学習していないか」を測る模擬試験
test学習が終わってから、最終成績を 1 回だけ測る本番の試験

val/test は「モデルが一度も見ていない文章」でなければ意味がありません。 教科書と同じ問題を出せば、丸暗記で満点が取れてしまい、本当の実力(初見の文章への強さ)が分からないからです。

2. 「言語別パープレキシティ / en·de·fr の要約評価が測れない」をかみ砕く

2-1. パープレキシティとは

言語モデルは「次の単語(トークン)は何か」を確率で予想します。 パープレキシティ(PPL)は「次のトークンを当てるとき、平均して何択で迷っているか」を表す数字です。 PPL 20 なら「毎回 20 択くらいの迷い」、PPL 5 なら「5 択まで絞れている」。小さいほど賢い。

これを 言語別に測りたいのが成功基準 1.2 の「検証パープレキシティ(言語別)」です。英語は PPL 15 だが日本語は 40、のように、言語ごとの得意・不得意を数字で見るためです(日本語はデータがトークンベースで 3.7% しかないので、そこが弱点になると予想しており、それを定量的に確認したい)。

2-2. 何が起きているか

現在のシャード:

train: 123 シャード … en / de / fr / ja が全部入っている
val  :   1 シャード … ja 100%(2,667 記事)
test :   1 シャード … ja 100%(8,734 記事)

つまり 英・独・仏の記事は 1 件残らず train(教科書)側にあります。すると:

一言でいえば 「4 言語のモデルを作ったのに、成績表に載せられる科目が日本語だけ」という状態です。成功基準 1.2 の「単一マシン学習比で劣化 10% 以内」を言語別に示すには、4 言語すべてに初見の問題用紙が要ります。

2-3. 副次的な問題

3. 原因を掘ったら分かったこと: en/de/fr は 2023-05-28 に一斉停止していた

言語別に pub_date の終端を実測しました(全 797 万件走査):

言語記事数最終 pub_date終盤の月間記事数
en3,978,4592023-05-28約 62,000〜73,000 件/月(健全なまま終了)
de2,028,0352023-05-28約 33,000〜41,000 件/月
fr1,115,9242023-05-28約 15,000〜19,000 件/月
ja846,8182024-02-12約 2,600〜3,400 件/月

en/de/fr は同じ日に、勢いを保ったまま突然終わっています。 先細りではなく、 2023-05-28 に(欧文フィード側の収集だけが)止まったと読めます。ja は 2024-02 まで 9 か月弱、単独で続いた。

review19 の「末尾 3 か月 + 1 か月」という全言語共通の日付で切ると、その期間(2023-10 以降)に記事があるのは ja だけなので、val/test が 100% 日本語になるのは必然でした。設計ミスというより、「収集停止のタイミングが言語で違う」というデータの事実に、単一境界の設計が合っていなかった、ということです。

4. 分割方針の提案

4-1. review19 の案 A(言語別・末尾 3 か月)をそのまま適用すると

言語test 期間test 記事数(概算)train からの流出
en2023-02-26〜05-28約 266,0006.7%
de同約 146,0007.2%
fr同約 68,0006.1%
ja2023-11-13〜2024-02-12約 9,9001.2%

評価に 26 万記事は要りません(数千記事・数 M トークンで十分に安定します)し、 en/de/fr の学習データを 7% 捨てるのはもったいない。よって修正します。

4-2. 推奨: 案 A'「言語別に、時系列の末尾から記事数で切る」

案val/test の多言語性時系列の意図train の流出再エンコード
A'(推奨) 言語別・記事数◎ 4 言語同サイズ○ 各言語の最新記事極小(0.3〜1.3%)必要(約 2 時間)
A 言語別・3 か月◎○大(en 6.7%)必要
B 記事単位ランダム◎× 捨てる任意必要
C 現状維持× ja のみ○極小不要

実装は小さいです: boundaries.json を言語別の {lang: {val_start, test_start}} にし(記事数から日付を逆算するスクリプトを追加)、tokenize_full.py の分割判定を言語別に参照するだけ。 再エンコードは 5 章の ja 重複除去(と 7 章の HTML 除去を採るならそれも)と同時に 1 回で済ませます。

5. 「2.」ja 連結の重複除去 — 実装・実測済み

5-1. 実装(コミット 04c46b5、push 済み)

5-2. 効果の実測(ja 全 846,818 記事)

項目値
旧連結の総文字数456,795,403
新連結の総文字数401,686,737
削減率−12.06%
title を省いた記事741,184(87.5%)
description を省いた記事244,812(28.9%)
両方省いた記事244,220(28.8%)

ja 記事の 87.5% で「本文が title から始まっている」、約 29% で「description が本文冒頭の写し」でした。削減分 5,500 万字はまるごと重複だったので、再エンコード後の ja トークン数は 0.23B → 約 0.20B になり、 日本語の学習トークンの中身が 12% 濃くなることになります(同じ文を 2 回読ませても学習効率は上がらないため)。

補足: 短い title(10 字未満)は対象外にしているため、そこだけは重複が残ります。実データの ja title で 10 字未満は少数なので実害はありません。

6. tokenizer_report.md の再生成

トークナイザの比較レポートを再生成しました。(省略: 原版が失われた経緯(サーバ障害)) 9/5 の再学習結果は 8/13 と小数第 3 位まで一致しているので内容は等価です。原版より増えた項目: 語彙 48,000 ピースの文字種構成(ラテン 61% / 日本語系 37%)、4 言語の分割実例、既知の注意点(5・7 章の件を反映)。

7. ついでに見つけた HTML 残骸 — 規模は無視できる

compose_ja の動作確認で覗いた ja の最初の記事(省略: 媒体名)の本文に <p><img src=…> が生で入っていたため、先頭 100 万行で規模を調べました:

言語タグ入り本文HTML エンティティ(&amp; 等)入り
en25 件(0.00%)0.28%
de5 件0.01%
fr19 件(0.04%)0.03%
ja3 件0.00%

合計 52 件 / 100 万件 = 0.005%。 特定の数チャンネル(省略: チャンネル番号)に偏っています。学習への実害はほぼありませんが、対処コストもほぼゼロ(clean() にタグ除去とエンティティ復号を 2 行足すだけ)なので、再エンコードに同乗させることを提案します(確認事項 2)。

8. その他

省略: 9. 9/21〜26 のネットワーク全断インシデント(サーバ運用)

10. 確認事項

  1. val/test の分割方針: 案 A'(言語別・末尾から test 8,000 記事 + val 3,000 記事)で進めてよいですか? 記事数を変えたい場合はご指定ください(評価の安定性の観点では test 5,000 以上を推奨)。
アーキテクト回答案 A'で OK
  1. HTML 残骸の除去(タグ除去 + エンティティ復号)を再エンコードに同乗させますか?(推奨: はい)
アーキテクト回答はい
  1. 再エンコードの実行許可(約 2 時間 = encode 70 分 + シャード化 50 分)。現行の 125 シャードは shards_v1/ にリネームして保管し、新シャードを shards/ に出す想定です(ディスクの空きは十分なので両方置けます。不要になったら v1 を消します)。
アーキテクト回答OK
省略: 確認事項 4(サーバの外形監視)とその回答

11. 次の作業予定

  1. 確認事項 1〜3 の回答 → 言語別 boundaries の算出スクリプト + tokenize_full.py の分割判定改修 → 再エンコード
  2. 新シャードの検証(言語構成が 4 言語揃った val/test になっていること、sha256 抜き打ち)→ 短報
  3. S(30M)モデルの実装(モデル定義・学習ループ・チェックポイント・評価ハーネスの PPL 部分)
  4. RTX 3060 機のクライアント環境(PyTorch CUDA)→ S ベースライン学習開始
← review19目次review21 →