Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

変換精度改善の方針

現状の仕組み

モデルのパイプライン

  1. ベースモデル: akaza-corpus-stats の大規模コーパス統計から unigram/bigram の出現頻度を取得
  2. コーパス学習: learn-corpus が training-corpus の正解データを使ってスコアを補正
  3. 辞書: SKK-JISYO.L + SKK-JISYO.akaza で語彙をカバー

学習アルゴリズム(learn-corpus)

パーセプトロン的な手法を採用している:

  • 正解と変換結果が異なる場合、正解側の unigram/bigram 出現頻度を delta(=2000)ずつ加算
  • 正解と一致するまで、または最大エポック数に達するまで繰り返す
  • 不正解側のスコアを下げる処理はない(正解を引き上げるのみ)

コーパスの3階層

ファイルエポック数用途
must.txt10,000絶対に正しく変換すべきもの
should.txt100正しく変換してほしいもの
may.txt10できれば正しく変換したいもの

過学習のリスク

コーパスにエントリを追加していくと以下のリスクがある:

  • スコアの偏り: delta=2000 × 最大10,000エポックで、個別エントリのスコアがベース統計を圧倒しうる
  • 副作用: 特定の文脈でスコアを歪めると、同じ読みを含む別の文脈で誤変換が発生する
  • 片方向学習: 正解のスコアを上げるだけで不正解を下げないため、多数のエントリが積み重なるとスコア分布が不自然になる

改善アプローチ

1. エラー分類を先に行う

make evaluate の k-best スコアリング(--k-best 5)で誤変換を2種類に分類する:

  • BAD(top-k にも正解なし): 語彙やセグメンテーションの問題。コーパス学習では直らない可能性が高い
  • TOP-k(top-1 は外れだが候補にはある): スコアリングの問題。コーパス学習で改善の見込みがある

対処の優先度は BAD > TOP-k。BAD はユーザーが候補を探しても見つからないため体験が最悪。

2. 辞書で直せるものは辞書で直す

dict/SKK-JISYO.akaza への追加は語彙を増やすだけで、unigram/bigram のスコアバランスを崩さない。 BAD のうち「そもそも候補に出ない」ものはまず辞書で対処するのが安全。

3. コーパスは「パターン」で入れる

1つの誤変換を直すために1行追加するのではなく、同じ種類の誤変換パターンをまとめて入れる。

例: 「暑い/熱い/厚い」の使い分け → 典型的な共起パターンを複数入れて bigram で自然に学習させる

夏/なつ は/は 暑い/あつい
お湯/おゆ が/が 熱い/あつい
板/いた が/が 厚い/あつい

個別の文をピンポイントで追加するより、パターンとして入れた方が汎化しやすく過学習しにくい。

4. 定量的にモニタリングする

コーパスを追加するたびに make evaluate の結果を確認し、退行がないか検証する。

Good=XXXX, Top-5=XXXX, Bad=XXXX, 再現率=XX.XX

Good が増えずに Top-k から BAD に移動するような退行が起きていないか注意する。

現状の評価結果(2026-02-08)

Good=5870 (53.1%), Top-5=493 (4.5%), Bad=4702 (42.5%), 再現率=91.47%

全11,065文中、半数強が top-1 で正解。再現率(文字レベルの LCS ベース)は91.5%。

エラーパターン分析

BAD(4,702件)の内訳

カテゴリ件数割合説明
1箇所だけ誤り3,60076.6%文中の1箇所だけが間違っている
2箇所誤り93719.9%文中の2箇所が間違っている
3箇所以上1653.5%広範な誤り

文字数の差(セグメンテーション品質の指標):

件数割合
同一長2,92062.1%
差2以下4,66099.1%
差3以上420.9%

BAD のうち99%はセグメンテーション自体はほぼ正しく、漢字の選択ミス(同音異義語の取り違え) が主因。

主な誤パターン:

  • 同音異義語の誤選択(~1,585件, 33.7%): 「使用/仕様」「行/言」「日本/二本」「買/書」等。セグメンテーションは正しいが漢字選択が間違い
  • 漢字にすべきところがひらがな(~913件, 19.4%): 「明後日→あさって」「物→もの」「事→こと」等
  • ひらがなにすべきところが漢字(~538件, 11.4%): 「ください→下さい」(63件)、「ない→無い」(136件)等
  • 表記スタイルの不一致(588件, 12.5%): 「すでに」vs「既に」、「たくさん」vs「沢山」等
  • カタカナ/ひらがな不一致(~175件, 3.8%): 「ダメ→だめ」「ごみ→ゴミ」等
  • 全角/半角の違い(41件, 0.9%): 「?→?」「0→0」等。評価時の正規化で対処可能
  • 文末表現の誤解析(~80件): 「かね→鐘」「よね→米」「ますね→マスネ」「ないん→ナイン」

TOP-5(493件)の内訳

TOP-5 の 94.7% は1箇所だけの誤りで、スコア調整で修正可能。

主な改善可能パターン:

パターン件数
文末「かね」→「鐘」17「ありますかね」→「あります鐘」
文末「よね」→「米」10「ないですよね」→「ないです米」
「ないん」→「ナイン」7「ないんですよ」→「ナインですよ」
「ますね」→「マスネ」4「使えますね」→「仕えマスネ」
「きき」→「気気」4「危機に瀕する」→「気気に瀕する」
1文字漢字違い148様々な同音異義語
その他1箇所278-

スコアリングロジックの改善ポイント

重大度: 高

1. bigram バックオフが定数フォールバック

bigram が見つからない場合、default_edge_cost(= calc_cost(0, total_bigrams, unique_bigrams) ≈ 10-12)という単一の定数にフォールバックする。unigram 確率との補間(Jelinek-Mercer 補間や Stupid Backoff)がない。

影響: 「私は」のようなありふれた語の組み合わせでも、bigram モデルに含まれていなければ「鑢蛸」のような稀な組み合わせと同じペナルティを受ける。

改善案: lambda * P_bigram + (1-lambda) * P_unigram のような線形補間を導入する。

2. パスに長さ正規化がない

Viterbi のコストは sum(node_costs) + sum(edge_costs) の単純加算。セグメント数が増えるほど edge_cost が加算されるため、少ない分節数(長い単語)が体系的に有利

影響: 「きょういくのはなし」→「教育の話」(3分節)より「今日行くの話」(4分節のように見えるが実際は「教育」vs「今日行く」のセグメンテーション競合)が不利になる構造的バイアス。

3. コスト関数の smoothing が非標準

#![allow(unused)]
fn main() {
cost = -log10((count + 0.00001) / (total_words + 0.00001 + unique_words))
}

ALPHA=0.00001 が極端に小さく、count=0(未知語)と count=1 の間に約5.0のコスト断崖がある。標準的な加算スムージングでは分母は total + alpha * V だが、現在は total + alpha + V で、未知語への確率配分がほぼゼロ。

重大度: 中

4. OOV の二重ペナルティ

未知語はノードコスト(高い unigram ペナルティ)とエッジコスト(全ての接続が default_edge_cost)の両方で罰せられる。固有名詞などの正当な未知語が候補に上がりにくい。

5. OOV 判定のバイト長ヒューリスティック

surface.len() < yomi.len() で漢字変換かどうかを判定しているが、1文字漢字(「気/き」等、バイト長が同一)はフル OOV ペナルティを受ける。

6. 文末表現の体系的な誤変換

「かね」「よね」「ますね」「ないん」が漢字/カタカナに変換される問題は、文末の助詞・終助詞が直前の動詞と分離されてセグメント化され、独立した語として漢字変換される ことが原因。bigram で「ます→ね」の接続コストが「ます→マスネ」より高くなっている。

頻出誤変換パターンと対処の優先度

優先度: 高(アルゴリズム改善で多数のケースに効く)

パターン影響件数対処方法
文末助詞「かね/よね/ますね/ないん」→ 漢字・カタカナ~80件 (BAD+TOP-5)bigram「ます+かね」「です+よね」等の強化
「使用/仕様」(しよう)~35件bigram「使用+する/した/して」の強化
「行/言」(いって等)~33件bigram で移動先「に+行って」等を強化
「金/鐘」(かね)~40件unigram で「金」の重み引き上げ
「日本/二本」(にほん)~18件bigram「日本+語/人/で/の」等の強化
「ここ/個々」~25件unigram「ここ」の重み引き上げ
「買/書/勝/飼」(かう等)~60件目的語名詞との bigram 強化
「危機」→「気気」~5件辞書エントリの確認・追加

優先度: 中(表記規約の問題、方針を決めて対処)

パターン影響件数備考
「ください/下さい」~63件補助動詞としてはひらがなが現代標準
「ない/無い」~136件anthy コーパスは「無い」を好む
「もの/物」「こと/事」「ところ/所」~129件形式名詞としてはひらがなが標準
「ダメ/だめ/駄目」等カタカナ・ひらがな揺れ~175件文脈依存、統一困難

優先度: 低(評価方法の改善で対処可能)

パターン影響件数備考
全角半角「?/?」「0/0」~41件評価時に正規化すれば解消

スコアリングロジック改善の優先順位

上記のエラー分析とコードの構造分析を総合すると、以下の順で取り組むのが効果的:

  1. bigram バックオフの改善 — 最多のエラー原因。定数フォールバックから unigram 補間への変更で、同音異義語の文脈判定が大幅に改善する見込み
  2. 文末助詞の bigram 強化 — コーパス追加で対処可能で即効性がある。「ます+かね」「です+よね」等のパターンを training-corpus に入れる
  3. コスト関数の smoothing 改善 — ALPHA の調整と標準的な加算スムージング式への変更で、OOV 周辺の挙動が安定する
  4. パス長の正規化 — 長い単語への構造的バイアスを緩和