# 機械学習で「全体の正答率（Accuracy）」だけ見ると失敗する理由：混同行列・Balanced Accuracy・誤り内訳の読み方

> 音声認識やカメラ画像認識で「全体のAccuracyが上がったのに実機で特定の人が使うと全く当たらない」原因を整理。件数加重Accuracyの罠、グループ均等Balanced Accuracyの設計、および混同行列から誤りの構造を特定する手順を解説します。

- **Canonical URL**: https://nodus-lab.pages.dev/articles/ml-accuracy-trap-confusion-matrix-balanced-accuracy-guide.html
- **CSV Comparison Table**: https://nodus-lab.pages.dev/datasets/ml-accuracy-trap-confusion-matrix-balanced-accuracy-guide.csv
- **Category**: Architecture
- **Article type**: 選び方・公式資料から整理（実測なし）
- **Data Updated**: 2026-10-16

## 選び方の要点
- 全体の件数加重Accuracy（正答率）だけを主指標にすると、データ件数が多い人物・撮影条件や簡単なクラス（5母音のみ等）の成績に引っ張られ、未知ユーザーや難クラスでの大幅な劣化を見落とす。
- 実機向けのAI開発では、クラス別Recallを平均しさらに人物・条件間で均等平均した「グループ均等Balanced Accuracy」を主指標に置き、最も成績が低い人物・条件のスコア（最低値）を併記して監視する。
- 混同行列（Confusion Matrix）はそのまま眺めるのではなく、「母音一致・子音誤認」や「検出点数の増減（マイナスなら指による隠れ、プラスなら背景誤検出または格子ズレ）」のように物理的な誤り方向へ集約することで、次に直すべき箇所（前処理・モデル・後処理）が特定できる。


## 選択肢の比較表
| 評価アプローチ | 計算の仕組み | 見落とすリスク | 適した用途・改善アクションへの繋がり |
| --- | --- | --- | --- |
| 全体件数加重Accuracy | 全正解数 ÷ 全サンプル数 | 録音・撮影件数が多い特定人物や簡単な部分課題の成績に支配され、少数派や未知条件の崩壊に気づけない | データ分布が完全に均一な閉集合テストの参考値のみ（主指標には不適） |
| 全体まとめMacro-F1 | 全サンプルを合算してクラス別F1を単純平均 | クラス間の不均衡は補正できるが、サンプル数が多い人物・環境の支配は防げない | クラス別の見逃し・誤検出のバランス確認（人物間の均等性は別途必要） |
| グループ均等Balanced Accuracy | 人物ごとにクラス別Recall平均（BA）を出し、人物間で均等平均 | 課題範囲（例：100クラス話者と5クラス話者）が異なるグループを混ぜると難易度が揃わない | 同一課題を持つ未知人物・未知端末間での汎用性比較の主指標（課題別に分離して集計） |
| 構造化混同行列（エラー内訳分析） | 真値×予測値の行列を物理的・言語的特徴（子音/母音、点数の増減等）で集約 | 行列を生のまま眺めるだけでは100クラス超で傾向が読み取れない | 誤りの8割が「子音誤認」なら特徴プーリング改善、「点数減少」なら指の隠れ対策など直すべき層を特定 |

## 詳細解説・原因分析
### 全体の正答率（Accuracy）が上がったのに実機で悪化する仕組み
機械学習モデルの改善サイクルで最も頻繁に起きる失敗の一つが、「テストデータ全体のAccuracy（正答率）が数ポイント上がったから新モデルを採用したのに、実機で別の人が使うと以前より当たらなくなった」という現象です。これはモデルの能力ではなく、評価指標の集計方法に原因があります。

例えば計算例として、評価データに人物Aのサンプルが1,000件、人物Bのサンプルが100件含まれているとします。改善前のモデルが人物Aで85.0%（850件正解）、人物Bで60.0%（60件正解）だった場合、全体の件数加重Accuracyは 910 ÷ 1,100 ＝ 82.7% です。ここで新モデルが人物Aに特化して90.0%（900件正解）へ伸びる一方、人物Bで40.0%（40件正解）へ急落したとします。全体の件数加重Accuracyを計算すると 940 ÷ 1,100 ＝ 85.5% となり、見かけ上は「+2.8ポイントの改善」に見えてしまいます。

さらに、評価データの中に「全100クラスを発声・撮影した人物」と「簡単な5クラス（5母音や基本図形のみ）だけを発声・撮影した人物」が混在している場合、それらを1つの平均値に混ぜてしまうと、簡単な課題のスコアが全体の数字をかさ上げします。主指標を作る際は、まず「同じ課題範囲（共通のクラス集合C）を持つ人物集合S」を予測結果を見る前に固定し、各人物のBalanced Accuracy（クラス別Recallの平均）を算出したうえで、人物間でも等しい重みで平均する「グループ均等Balanced Accuracy」を基準にする必要があります。

主なチェックポイントは以下の通りです：全体の件数加重Accuracy：サンプル数が多い人物や環境の成績に支配されるため、主指標ではなく参考値として扱う / 課題の分離：100クラス課題と5クラス課題（基本母音のみ等）は難易度が異なるため、1つの主指標に混ぜず別スコアとして併記する / 最低グループ値の監視：平均値だけでなく「最も成績が低い人物・条件のスコア」を必ず併記し、特定層での回帰低下を見逃さない。
参照: [scikit-learn Documentation: confusion_matrix](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html)
参照: [scikit-learn Documentation: balanced_accuracy_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.balanced_accuracy_score.html)

### 混同行列（Confusion Matrix）を「誤りの物理的・構造的な内訳」へ変換する
AccuracyやMacro-F1は「どれくらい当たったか」は教えてくれますが、「なぜ外れたか」「次にコードのどこを直せばよいか」は教えてくれません。10クラス〜100クラス以上の分類問題では、scikit-learnの `confusion_matrix` 等で真値と予測値のペアを出力し、さらにそれをドメイン固有の「誤り構造」へ集約することが不可欠です。

例えば日本語の単音節音声認識（約100クラス）で誤分類の内訳を混同行列から集計すると、「母音も子音も外れている誤り」は全体の1割強に過ぎず、誤認全体の80%以上が「母音は合っているが子音だけ取り違えている（ち↔し、つ↔す、k↔g、n↔mなど）」に集中しているといった構造が浮かび上がります。この事実が分かれば、「データを闇雲に増やす」のではなく、「音声区間検出（VAD）の切り出し境界ジッターで先頭の短い子音フレームが欠けているのではないか」「時間方向の平均プーリングで短い子音の特徴が長い母音に埋もれているのではないか（フレーム単位のLogit最大値プーリングや子音・母音マルチタスクヘッドが必要ではないか）」という具体的なアーキテクチャ改善へ直結します。

同様に、カメラ画像から点字やドットパターンを認識するタスクでも、文字単位の混同行列に「検出された点数の増減（予測された点数 − 本来の点数）」という軸を加えるだけで原因が明確に分かれます。点数の増減が「マイナス（点が減って別の文字に化けた）」なら原因は指や影によるオクルージョン（隠れ）や検出閾値の高さであり、「プラス（点が増えて化けた）」なら背景ノイズの誤検出または隣接列の割り当てズレであると即座に切り分けられます。

主なチェックポイントは以下の通りです：音声認識の混同行列集約例：「母音一致・子音誤認」「子音一致・母音誤認」「両方誤認」「同音異表記（ぢ↔じ、づ↔ず、を↔お）」に分類してボトルネックを特定する / 画像・ドット認識の混同行列集約例：「置換（文字化け）」「余分（背景からの湧き出し）」「欠落（見逃し）」「重複（同一対象の2回読み）」と点数の増減方向を分離する / 同音・同義ラベルの扱い：生の予測結果は上書きせず保存したうえで、評価目的に応じて「厳密ラベル一致率」と「同音統合後のスコア」の両方を記録する。
参照: [scikit-learn Documentation: confusion_matrix](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html)
参照: [scikit-learn Documentation: balanced_accuracy_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.balanced_accuracy_score.html)
参照: [scikit-learn Documentation: f1_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html)

### 実機開発で導入すべき評価レポートの定型チェックリスト
モデルや前処理を変更するたびに手作業で集計スクリプトを書き換えていると、都合の良い指標だけを見て採用判断を下す「チェリーピッキング」が起きやすくなります。評価パイプラインの出力フォーマットは以下の順序で固定しておくのが安全です。

まず「1. データ分割と評価対象の検証範囲（人物数・件数・クラス範囲・欠落クラスの有無）」を出し、次に「2. 主指標（同一課題上のグループ均等Balanced Accuracy）」、続いて「3. 人物別・性別別・端末条件別のスコアと最低値」、「4. 基本課題（5母音等）の回帰確認」、「5. 対象外ノイズ（other）の誤受理率と発話の誤拒否率」、最後に「6. 混同行列の上位ペアとエラー種別内訳」を出力します。

平均スコアが0.5ポイント上がっていても、特定の重要グループ（未知の女性話者や実機スピーカーフォン条件など）で数ポイントの悪化が起きている場合は自動採用せず、混同行列の差分を確認する運用ルールを徹底することで、実機での手戻りを劇的に減らすことができます。

主なチェックポイントは以下の通りです：欠落クラスのゼロ埋め禁止：特定の評価話者に一部のクラスの正解データが存在しない場合、そのクラスを0点として平均に混ぜず、事前に固定した共通クラス集合上で比較する / 後付けの除外禁止：予測結果を見た後に「このクラスは難しいから評価から外そう」と集計範囲を変更しない / ValとTestの役割分離：閾値調整やエラー分析によるサンプラー調整はすべてVal（検証セット）で行い、Test（最終評価セット）の混同行列を見て学習設定を作り直さない。
参照: [scikit-learn Documentation: confusion_matrix](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html)
参照: [scikit-learn Documentation: balanced_accuracy_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.balanced_accuracy_score.html)
参照: [scikit-learn Documentation: f1_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html)

## 記事の範囲
2026年10月16日にscikit-learn公式ドキュメント（confusion_matrix、balanced_accuracy_score、f1_score）を確認し、多クラス分類および複数人物・複数環境データセットにおける集計バイアスと混同行列の分析手法を整理した記事です。文中のスコアや件数は指標の性質を比較するための計算例です。


## 参考資料
- [scikit-learn Documentation: confusion_matrix](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html)
- [scikit-learn Documentation: balanced_accuracy_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.balanced_accuracy_score.html)
- [scikit-learn Documentation: f1_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html)

## 次に考えたいこと
- [機械学習のベンチマークが正しく測れない原因：話者・撮影条件リークと学習パイプライン内の再分割バグ](https://nodus-lab.pages.dev/articles/ml-benchmark-data-leakage-group-split-pipeline-guide.html)
- [学習データにノイズ・対象外（other）クラスを入れないと実機で何が起きるか：誤受理率と誤拒否率の設計](https://nodus-lab.pages.dev/articles/ml-noise-other-class-false-acceptance-evaluation-guide.html)
- [オフライン正答率は高いのに実機で使えない理由：ストリーミングAIにおける「内容一致率」と「発火タイミング一致率」の乖離](https://nodus-lab.pages.dev/articles/streaming-ai-offline-accuracy-vs-realtime-timing-guide.html)
