TT Lab
はじめる
学ぶ 学習パス コース

AIダイエット失敗事件

小さくしたAIが数字を読めなくなった

TT Labで続きを見る

一言でいうと

変換の成功、整数カーネルの実行、分類品質を、それぞれ別の検査で確認します。

なぜ必要なのか

数字読み取り器のファイルサイズを減らしたところ、正解率が大きく下がりました。変換コマンドは成功し、ファイルの拡張子もonnxです。何を根拠にデプロイを拒否すればよいのでしょうか。ファイルが小さいという事実、整数の重みがあるという事実、実際に整数カーネルが実行されたという事実、数字を正しく読めているという事実は、それぞれ別の証拠です。

どう動くのか

量子化は、実数を狭い整数表現で近似する変換です。scaleとzero pointを使って整数と実数を対応させるため、情報の損失が生じることがあります。静的量子化では、あらかじめキャリブレーション入力を実行して活性化値の範囲を決めます。QDQグラフには、QuantizeLinearとDequantizeLinearが入ります。この過程では、活性化値と重みをsigned INT8に変換し、重みにはチャネルごとの範囲を使います。詳しいAPIはONNX Runtimeの公式ガイドを参照してください。

このコースのフィクスチャにあるFP32モデルは、3つの線形層を持つ小さなMLPです。キャリブレーション用の360枚の画像を読むCalibrationDataReaderを作り、各サンプルをpixelsという名前の1×64のfloat32入力として渡します。変換器は、入力ONNXの隣にシェイプ推論用の一時ファイルを作ることがあります。そのため、保護された/opt/lab/quantization/fp32.onnxを直接変換せず、自分の作業フォルダーにsource.onnxとしてコピーして使います。元ファイルを書き込み可能にする必要はありません。

提供されるbad-calibration.onnxは、すべてのピクセルが0のキャリブレーション入力で作った、失敗の比較群です。正常にキャリブレーションした候補と同じ評価データで実行したあと、差を見てください。どの数字をどの数字と取り違えたかは、混同行列に現れます。この教材では、行が実際のクラス、列が予測クラスです。実際の1を2と読んだなら、confusion[1][2]を増やします。軸を入れ替えても対角和と全体の精度は同じなので、精度だけを検証していると誤りを見逃します。

最後の出力にもQDQが適用されたモデルは、丸めのために確率の合計がちょうど1にならないことがあります。提供された正常な変換で観察した合計の最小値は、約0.992でした。チェッカーは、この変換の1/255の間隔と10クラス分の丸め誤差を許容しますが、負の値・有限でない値・大きくずれた合計は拒否します。許容誤差があるということは、どんな出力でも通すという意味ではありません。

現場での姿

分類器のデプロイレビューに参加したと仮定してみてください。同僚が「24KBのファイルを作りました」と言っても、すぐに差し戻す必要はありません。代わりに、どんな入力でどんな性能で動作したのかを尋ねればよいのです。ファイルサイズは保存容量の証拠です。重みのデータ型は、表現方式の証拠です。プロファイルは、実行経路の証拠です。評価データから得た指標は、限られた範囲での品質の証拠です。この4つの問いを1つの項目にまとめないことが、今回の課題の核心です。

混同行列は、精度の数字を説明できるようにしてくれます。実際の正解が[1, 2, 1, 0, 9]で、予測が[2, 2, 1, 0, 8]なら、当たったサンプルは3つです。精度は3/5で、間違えた2つのサンプルは1→2と9→8です。コードが2→1と8→9と記録していたら、比率は合っていてもレポートの説明は逆になります。summarize関数を全体のモデルから切り離して、短いリストでテストする理由がここにあります。

精度の差を確認するときは、比較の基準も固定する必要があります。基準のFP32自体が誤った入力を受け取ると、候補と両方が低い精度になって、差だけが小さくなることがあります。「損失が小さい」という基準だけを置くと、両方とも読めないモデルが通ってしまいます。チェッカーは、まず提供されたFP32が評価セットで0.95以上かどうかを確認してから、候補との差を見ます。前処理単体のテスト、基準モデルの確認、候補の比較は、それぞれ別の種類の誤りを担当します。

不良キャリブレーションのモデルも実際に実行してみる理由を考えてみてください。レポートのreject_badを常にtrueと書くプログラムは、拒否するふりをしているだけです。3つのモデルのcount・correct・accuracy・混同行列を再計算して照合してこそ、不良候補をどんな根拠で拒否したのかがわかります。比較群のモデルサイズは正常な候補と近いことがあるため、バイト数を品質指標の代わりに使ってはいけません。ファイルが小さいことは、この事件の犯人ではなく、別の観察です。

CPUの種類が変わると、同じバイト列のINT8モデルでも、境界に近いサンプルの予測が変わることがあります。開発時にあるマシンの正解リストを覚えておいて、すべての実行環境に当てはめることはしません。同じ実行環境で基準と候補を一緒に評価し、差を検査します。ただし、差が生じたという事実を無条件に許容するわけでもありません。設定した損失の上限を超えたら失敗です。直後のクイズで誤りの方向を読み、最後のモジュールの統合ラボでレポートを自分で作ります。

次のラボですること

ステップ4–6で、candidate.onnxを自分で作り、3つのモデルの推論を実行します。metrics.pyのsummarize(predictions, labels)は、count・correct・accuracy・10×10のconfusionを返します。精度は0–1の比率です。FP32に対する損失の上限1%pは比率0.01であり、相対的に1%減少したという意味とは異なります。FP32が0.96なら、候補の0.95が境界です。regression.jsonに、実際の結果と不良モデルを拒否した判断を残します。