リランキング evaluate/check 修正 & 評価レポート
背景
リランキング実装 (#432) で重みパラメータを変えても evaluate / check の結果が変わらないバグがあった。
原因
2箇所で convert_k_best(リランキング適用済み)を経由していなかった。
1. check.rs
k-best モードで engine.graph_resolver.resolve_k_best(&lattice, k) を直接呼んでおり、リランキングが適用されていなかった。
#![allow(unused)]
fn main() {
// Before
let paths = engine.graph_resolver.resolve_k_best(&lattice, k)?;
// After
let paths = engine.convert_k_best(yomi, None, k)?;
}
2. evaluate.rs
1-best 判定に engine.convert() を使っていたため、リランキングで順位が変わっても Good/Bad に反映されなかった。
#![allow(unused)]
fn main() {
// Before: convert で 1-best、不一致時に別途 convert_k_best
let result = engine.convert(yomi, Some(&force_ranges))?;
// After: convert_k_best 1回で両方判定
let k_results = engine.convert_k_best(yomi, Some(&force_ranges), k_best)?;
let got = k_results.first().map(|p| /* 先頭パスから surface を取得 */);
}
修正内容
- PR: #433
check.rs: k-best ブランチでconvert_k_bestを使用するように変更evaluate.rs:convert→convert_k_bestの先頭パスで 1-best 判定するように変更
評価結果
条件
- コーパス: anthy-corpus (corpus.0〜5.txt, 全 11,233 件)
- 辞書: SKK-JISYO.L
- モデル: akaza-default-model
- k-best: 5 (デフォルト)
結果
| unknown-bigram-weight | Good | Top-5 | Bad | 再現率 |
|---|---|---|---|---|
| 1.0 (default) | 6,427 | 467 | 4,339 | 92.51% |
| 0.3 | 5,931 | 963 | 4,339 | 91.46% |
| 0.1 | 5,780 | 1,114 | 4,339 | 91.23% |
分析
- 重みパラメータの変更が evaluate に正しく反映されていることを確認した
- Bad は全パターン同じ (4,339) — Top-5 にも入らないものは重みを変えても変わらない
- Good + Top-5 の合計も同じ (6,894) — リランキングで Top-5 内の順位が入れ替わっている
- unknown-bigram-weight を下げると Good が減り Top-5 が増える
- 未知 bigram のコストを軽くすると、未知語を含む分割が選ばれやすくなり精度が低下
- デフォルト (1.0) が現時点では最良
corpus.2.txt のみでの結果 (参考)
| unknown-bigram-weight | Good | Top-5 | Bad | 再現率 |
|---|---|---|---|---|
| 1.0 (default) | 13 | 4 | 61 | 71.85% |
| 0.3 | 13 | 4 | 61 | 70.76% |
| 0.1 | 12 | 5 | 61 | 70.41% |
length-weight 評価
粗探索 (0〜10.0)
| length-weight | Good | Top-5 | Bad | 再現率 | Good差分 |
|---|---|---|---|---|---|
| 0 (baseline) | 6,427 | 467 | 4,339 | 92.51% | - |
| 0.1 | 6,428 | 466 | 4,339 | 92.51% | +1 |
| 0.5 | 6,438 | 456 | 4,339 | 92.56% | +11 |
| 1.0 | 6,462 | 432 | 4,339 | 92.61% | +35 |
| 2.0 | 6,472 | 422 | 4,339 | 92.64% | +45 |
| 3.0 | 6,473 | 421 | 4,339 | 92.62% | +46 |
| 5.0 | 6,438 | 456 | 4,339 | 92.51% | +11 |
| 10.0 | 6,350 | 544 | 4,339 | 92.33% | -77 |
- length-weight を上げるほど Good が増加し、2.0〜3.0 でピーク
- 5.0 以上では逆に悪化し、10.0 では baseline を下回る
詳細探索 (2.0〜3.0, 0.1刻み)
| length-weight | Good | Top-5 | Bad | 再現率 | Good差分 |
|---|---|---|---|---|---|
| 2.0 | 6,472 | 422 | 4,339 | 92.64% | +45 |
| 2.1 | 6,473 | 421 | 4,339 | 92.63% | +46 |
| 2.2 | 6,473 | 421 | 4,339 | 92.64% | +46 |
| 2.3 | 6,474 | 420 | 4,339 | 92.63% | +47 |
| 2.4 | 6,470 | 424 | 4,339 | 92.62% | +43 |
| 2.5 | 6,472 | 422 | 4,339 | 92.62% | +45 |
| 2.6 | 6,471 | 423 | 4,339 | 92.62% | +44 |
| 2.7 | 6,472 | 422 | 4,339 | 92.63% | +45 |
| 2.8 | 6,473 | 421 | 4,339 | 92.63% | +46 |
| 2.9 | 6,468 | 426 | 4,339 | 92.61% | +41 |
| 3.0 | 6,473 | 421 | 4,339 | 92.62% | +46 |
- ピークは length-weight=2.3 (Good=6,474, +47)
- ただし 2.0〜3.0 の範囲で Good は 6,468〜6,474 (差6件) とほぼ横ばい
- この範囲ではパラメータに対して敏感ではなく、2.0〜3.0 のどこでもほぼ同等の改善
length-weight=2.0 の詳細分析 (baseline との差分)
baseline (length-weight=0) と length-weight=2.0 で変換結果が変わったケースを個別に分析した。
変化の概要
| 変化 | 件数 | 内容 |
|---|---|---|
| 改善: BAD/TOP-5 → Good | 109件 | TOP-5 内で 1 位に昇格 |
| 悪化: Good → TOP-5 | 67件 | 1 位から脱落(TOP-5 には残っている) |
| 悪化: Good → BAD | 0件 | 完全に見つからなくなるケースはなし |
| BAD↔TOP-5 ステータス変化 | 0件 | - |
| 出力変化 (同ステータス) | 220件 | BAD/TOP-5 のまま出力だけ変わった |
ネット改善: +109 - 67 = +42件
改善例 (TOP-5 → Good, 109件から抜粋)
正しい分節まとめが効いているケース:
| よみ | corpus (正解) | baseline | length-weight=2.0 |
|---|---|---|---|
| とうきょうととっきょきょかきょく | 東京都特許許可局 | 東京と特許許可局 | 東京都特許許可局 |
| あるぷすのしょうじょはいじ | アルプスの少女ハイジ | アルプスの少女は維持 | アルプスの少女ハイジ |
| きょうとはぼんちです | 京都は盆地です | 今日とは盆地です | 京都は盆地です |
| あしばがためをしてから | 足場固めをしてから | 足場がためをしてから | 足場固めをしてから |
| せいこういのってます | 成功祈ってます | 性行為のってます | 成功祈ってます |
| いやがおうでも | 否が応でも | いやが王でも | 否が応でも |
| としむけにはつばいした | 都市向けに発売した | 年向けに発売した | 都市向けに発売した |
| ふなばしてん | 船橋店 | 船場支店 | 船橋店 |
| にかいきゅうとくしん | 二階級特進 | に階級特進 | 二階級特進 |
悪化例 (Good → TOP-5, 67件から抜粋)
漢字→ひらがな/カタカナの退行や過剰な結合:
| よみ | corpus (正解) | baseline | length-weight=2.0 |
|---|---|---|---|
| だいじなことは | 大事なことは | 大事なことは | だいじなことは |
| なぜかじゅうでんできずに | なぜか充電できずに | なぜか充電できずに | 何故か充電できずに |
| いくのをやめました。 | 行くのをやめました。 | 行くのをやめました。 | 生野をやめました。 |
| こうじえんちょうしんせいのしょるいをかいた | 工事延長申請の書類を書いた | 工事延長申請の書類を書いた | 広辞苑超新星の書類を書いた |
| ぜんはんせい | 全半生 | 全半生 | 前半生 |
| ぜんじんみとうのち | 前人未到の地 | 前人未到の地 | 前人未到後 |
| かくめいをおこしましたしね | 革命を起こしましたしね | 革命を起こしましたしね | 革命を起こしました死ね |
悪化パターンの傾向
悪化 67件の全てが Good → TOP-5 であり、Good → BAD は 0件。つまり:
- length-weight=2.0 で正解候補が Top-5 から完全に消えることはない
- 長い単位を優先しすぎて「生野」(いくの) のような過剰結合や、「広辞苑超新星」のような誤った長単語マッチが起きる
- ひらがな表記が正解のケースで漢字変換を優先してしまう傾向がある (「だいじ」→「大事」は Good だが逆は悪化)
- 「7日」(なのか) のような数詞を含む結合エラーも散見される
考察
unknown-bigram-weight
- 単体での改善は難しい
- 1.0 未満にすると悪化する
- 1.0 を超えると元のモデルが学習したコストバランスを歪めることになる
length-weight
- length-weight=2.0〜2.3 が最適値 (baseline比 Good+45〜47, 再現率 92.51%→92.63%)
- トークン数の少ない(= 長い単位でまとめた)分割を優先することで精度向上
- 2.0〜3.0 の範囲で安定しており、ロバストなパラメータと言える
- 5.0 以上では過度にトークン数を減らそうとして逆効果
- 悪化ケースは全て Good→TOP-5 であり、Good→BAD は発生しない(安全性が高い)
- ただし「生野」「広辞苑超新星」のような過剰結合による悪化には注意が必要
今後の方向
- length-weight のデフォルト値を 2.0 程度に設定することを検討
- 複数の重みパラメータの組み合わせ探索
- コーパスを使った重みの自動チューニング
- 「なのか」→「7日」のような特定パターンの悪化への対処