コーパス学習 (learn-corpus)
このページでは、akaza-data learn-corpus によるモデルの学習処理を説明する。
概要
Wikipedia・青空文庫等から生成した統計ベースの言語モデル(データフロー参照)には偏りがある。learn-corpus は手作業で作成した教師コーパスを使い、言語モデルのカウント値を直接調整することで変換精度を補正する。
アルゴリズムは誤り駆動のカウント調整であり、構造化パーセプトロンなどの識別学習は実装されていない。構造化パーセプトロンの検討メモは設計メモを参照。
アルゴリズム
学習ループ
for each コーパスファイル (may → should → must):
for each エポック (1..最大エポック数):
for each 教師文:
1. 教師文の「よみ」をビタビで変換
2. 変換結果が正解と一致 → スキップ
3. 不一致 → 正解パス上のカウントを調整
全問正解なら早期終了
カウント調整
変換結果が不正解のとき、正解パス上の単語・バイグラム・スキップバイグラムの出現カウントを delta だけ減算する:
#![allow(unused)]
fn main() {
// ユニグラム: 正解パスの各単語
new_count = old_count - delta
// バイグラム: 正解パスの隣接ペア (BOS→先頭, 末尾→EOS を含む)
new_count = old_count - delta
// スキップバイグラム: 正解パスの1語飛ばしペア
new_count = old_count - delta
}
カウントは u32 型で保持されている。delta がカウントを超える場合は符号なし整数のアンダーフローにより非常に大きな値になり、結果としてコスト(-log₁₀(count / total))が極端に低くなる。これにより、コーパスに登場頻度が低い正解単語が強制的にコスト最小化される。
運用パラメータ
実際の運用(akaza-default-model)では以下のパラメータが使用されている:
| パラメータ | 値 | 意味 |
|---|---|---|
delta | 2000 | 1回の不正解あたりの減算量 |
may_epochs | 10 | may.txt の最大エポック数 |
should_epochs | 100 | should.txt の最大エポック数 |
must_epochs | 10000 | must.txt の最大エポック数 |
教師コーパス
形式
Kytea のフルアノテーション形式を採用。各行が1つの教師文で、表層/よみ のペアをスペース区切りで記述する:
東京都/とうきょうと 特許/とっきょ 許可/きょか 局/きょく
私/わたし は/は 学校/がっこう に/に 行く/いく
品詞は扱わず、「どの位置で変換候補が区切られていたら自然か」という観点で区切る。
三段階の優先度
教師コーパスは重要度に応じて3ファイルに分かれ、弱い順に学習される:
| ファイル | エポック数 | 用途 |
|---|---|---|
may.txt | 10 | できれば変換できてほしい表現 |
should.txt | 100 | 変換できてほしい表現 |
must.txt | 10,000 | 必ず変換できなければならない表現 |
弱いコーパスを先に学習し、その後に強いコーパスを学習することで、重要度の高い表現が確実に反映される。各コーパスは全問正解になった時点で早期終了する。
学習の流れ(全体)
akaza-corpus-stats の統計データ (wordcnt trie)
↓
learn-corpus (may → should → must の順にカウント調整)
↓
unigram.model / bigram.model / skip_bigram.model (MARISA Trie)
- wordcnt trie をオンメモリの HashMap にロード
- 教師コーパスに含まれるがモデルに未登録の単語を追加(初期カウント 1)
- may → should → must の順に学習ループを実行
- 調整後のカウントから MARISA Trie 形式のモデルファイルを生成
実装: akaza-data/src/subcmd/learn_corpus.rs