# オフライン正答率は高いのに実機で使えない理由：ストリーミングAIにおける「内容一致率」と「発火タイミング一致率」の乖離

> カメラ映像や音声のリアルタイム認識で「出力された文字列の一致率は70〜80%あるのに、実機で動かすとタイミングがズレて全く使えない（タイミング込み一致率0%）」現象の構造を解説。認識部と確定層（Readout）のペア評価、早すぎ・遅すぎの計測設計をまとめます。

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

## 選び方の要点
- カメラ映像や音声ストリームのリアルタイム処理は「認識部（フレーム単位の検出・分類）」と「確定層（いつ音を鳴らすか決めるReadout層）」の2段で構成され、文字列の『内容だけの一致率』で選ぶと実機で破綻する。
- 視野の右端に文字が見えた瞬間にまとめて鳴らす確定層は、内容一致率では70〜80%台で上位に見えるが、96%以上の発話が「まだ指が触れる前（通過前）」に鳴るため、タイミング込み一致率では0%になる。
- 認識部と確定層は必ずペアの名前で登録してA/B比較し、通し番号（ID振り直し）への依存を排して「直前確定列の左端退出」や「フレーム間の点群移動量による位相ロック」でタイミングを制御する。


## 選択肢の比較表
| 認識器＋確定層の構成パターン | 内容だけの一致率（例） | 早すぎ率（通過前発火） | タイミング込み一致率 | 実機での挙動と採否判断 |
| --- | --- | --- | --- | --- |
| 構成A：視野内の全確定文字を即座にまとめて鳴らす確定層 | 73.8% 〜 82.2% | 95.8% 〜 96.8% | 0.0% 〜 1.2% | 不採用。カメラの右端に文字が見えた瞬間に先回りしてまとめて鳴るため、指の動きと音が全く合わない |
| 構成B：通し番号（トラッキングID）の5フレーム連続一致で鳴らす確定層 | 68.8% | 77.7% | 17.5% | 不採用。地図の作り直しで通し番号が振り直されるたびに確定がリセットされ、タイミングも先走りやすい |
| 構成C：直前確定列の左端文字を、新文字列確定時かつ逆行ガード付きで鳴らす確定層 | 77.8% 〜 79.9% | 1.6% 〜 3.8% | 78.6% 〜 79.8% | 採用候補。通し番号に依存せず、ちょうど指が離れて画面左端から抜けた文字と音が揃う |
| 構成D：紙面上の移動量と格子位相ロックで通過を数える確定層 | 86.7% 〜 91.2% | 低水準（通過判定後） | 85.8% 〜 88.4% | 実機採用。フレーム間の点群移動量で格子の横ズレを半減させ、行飛びによる誤発火も防止 |

## 詳細解説・原因分析
### 「内容だけの一致率」で1位のアルゴリズムが実機で0点になる理由
カメラで紙面上の文字や点字をなぞりながらリアルタイムに読み上げる装置や、ストリーミング音声認識システムを開発する際、最も陥りやすい罠が「録画や録音に対する最終出力テキストの一致率（内容だけの一致率）」だけでアルゴリズムの優劣を決めてしまうことです。

連続認識システムは、各フレームから文字や候補を取り出す『認識部』と、複数フレームの推移を見て「今この文字を確定して音を鳴らす」と決める『確定層（Readout）』の2段で成り立っています。もし確定層が「画面内で文字の読みが落ち着いた瞬間に、新しく見えた文字をまとめて鳴らす」という実装になっていると、カメラの視野の右端に先の文字が写った時点で（ユーザーの指がまだそこに触れるよりもずっと前に）次々と先回りして読み上げてしまいます。

この状態で出力された文字列だけを正解テキストと照合すると、一致率は73%〜82%といった高い数字が出ます。しかし、「鳴った瞬間にその文字がちょうど通過位置（左端）を経て画面から抜けたか」という『タイミング込み一致率』で測り直すと、発話の96%以上が「早すぎ（まだ画面内に残っている文字の先読み）」と判定され、実機でのタイミング込み一致率は0.0%〜1.2%まで暴落します。認識部と確定層は必ず1つの名前（ペア）に紐づけて登録し、既存の認識器を直接上書きせずA/B比較できる状態でタイミング込みの数字を測る必要があります。

主なチェックポイントは以下の通りです：既存認識器の上書き禁止：大きな変更を既存の認識器名へ直接上書きすると劣化した際に切り戻せずA/B比較もできなくなるため、必ず別名で登録して比較後に既定を切り替える / 早すぎ（残留読み）の監視：まだ視野の先に残っている対象を鳴らしていないか、精度レポートに『残ったまま読んだ件数』の列を設けて監視する / インターフェース不整合の検出：認識部自体は1本あたり400文字以上検出できているのに、確定層が期待する属性（center_cells等）を渡していないために1文字も鳴らない『配線ミスによる0%』と『認識精度による0%』をログで区別する。
参照: [ONNX Runtime Documentation: Performance and Model Optimizations](https://onnxruntime.ai/docs/performance/model-optimizations/quantization.html)
参照: [scikit-learn User Guide: Metrics and scoring](https://scikit-learn.org/stable/modules/model_evaluation.html)

### 通し番号（トラッキングID）への依存を捨て、物理移動量で制御する
確定層を設計するとき、「各対象に通し番号（トラッキングID）を振り、同じIDで同じ文字が5フレーム連続したら確定して、画面から消えた瞬間に鳴らす」という方式は一見合理的に思えます。しかし実機の映像では、手の影やブレでメモリ上の格子マップが作り直されるたびに通し番号が振り直されるため、「同じ通し番号が5フレーム以上維持される確率」自体が17%程度しかない、といった事態が起きます。確定が追いつかないまま発火契機だけを後ろへ遅らせると、今度は保留文字が積み上がって実機で2文字以上の遅延が発生します。

これに対して強いのが、(1) 通し番号を一切使わず「新しく確定した文字列の並びが直前と矛盾しなければ、前回確定していた文字列の左端（いま抜けた文字）を鳴らす」方式や、(2) フレーム間の検出点群の重ね合わせから「紙面の物理的な移動量（ピクセル/フレーム）」を直接測り、一度確定した格子の位相をその移動量分だけスライドさせて固定する方式です。これにより、点が少ないフレームで格子が1列ズレる誤りを半減させることができます。

また、誤検出の点が数フレームだけ現れて消えた場合や、ユーザーが指を別の行へ移して3文字以上が一度に画面から消えた場合に、文字列の変化だけで判断すると「読み違いが混ざった通常のなぞり」まで捨ててしまいます。ここでも『紙面の移動量で見て本当に指の境界線を越えたのか、それとも指を浮かせて別の場所へ飛んだのか』を物理量で切り分けることで、余分な暴発を半分以下に抑えられます。

主なチェックポイントは以下の通りです：1フレーム1行のJSONLトレース出力：毎回重いモデル推論（YOLO等）や動画デコードを回し直すのではなく、まずフレームごとの検出・確定状態をJSONLに書き出し、そこから高速にHTML精度レポートを生成する / 置換・余分・欠落・重複の4分類：同じ一致率80%でも、誤りが「余分な発話」に寄っているか「読み落とし（欠落）」に寄っているかで調整すべき閾値が正反対になる / ベンチマーク判定器自体のバグ検証：評価文の中に同じ文字（例：『かがわ』の『か』）が複数回登場するとき、素朴に『画面内に同じ文字が見えるか』で早すぎ判定を行うと、2個目の『か』が見えているせいで1個目の正しい発話まで不合格にする判定バグが起きるため、残りの同一文字数を考慮して判定する。
参照: [ONNX Runtime Documentation: Performance and Model Optimizations](https://onnxruntime.ai/docs/performance/model-optimizations/quantization.html)
参照: [scikit-learn User Guide: Metrics and scoring](https://scikit-learn.org/stable/modules/model_evaluation.html)

## 記事の範囲
2026年10月16日にONNX Runtimeおよびscikit-learnの評価ドキュメントを確認し、リアルタイム連続認識システムにおける認識部と確定層（Readout）の分離評価・トレース分析手法を整理した記事です。


## 参考資料
- [ONNX Runtime Documentation: Performance and Model Optimizations](https://onnxruntime.ai/docs/performance/model-optimizations/quantization.html)
- [scikit-learn User Guide: Metrics and scoring](https://scikit-learn.org/stable/modules/model_evaluation.html)

## 次に考えたいこと
- [機械学習で「全体の正答率（Accuracy）」だけ見ると失敗する理由：混同行列・Balanced Accuracy・誤り内訳の読み方](https://nodus-lab.pages.dev/articles/ml-accuracy-trap-confusion-matrix-balanced-accuracy-guide.html)
- [カメラ距離やマイク（スピーカーフォン）を変えたらAI認識精度が急落する理由：前処理ハイパーパラメータの前提崩壊と再校正](https://nodus-lab.pages.dev/articles/hardware-change-camera-microphone-hyperparameter-regression-guide.html)
- [PyTorchで学習したモデルをONNX INT8量子化して実機へ載せるときに精度が落ちる原因：前処理不一致と段階的検証](https://nodus-lab.pages.dev/articles/edge-ai-pytorch-fp32-to-onnx-int8-preprocess-mismatch-guide.html)
