7.8. テンサーI/O¶
エンジンは入力側で単一のテンサーを受け付け、出力側で1つ以上を生成します。テンサーは、numpyの章で紹介された形状、dtype、ディスクリプタの語彙を持つ ndarray オブジェクトです。それらの形状とdtypeはモデルファイルに由来し、input_shape / output_shape および input_dtype / output_dtype を通じて報告されます。
7.8.1. 量子化¶
カメラが実行するほとんどのネットワークは、カメラのRAMと計算予算に収まるように、量子化された整数テンサー -- int8 または uint8 -- を扱います。量子化されたテンサーは、テンサーごとのスケールとゼロ点を通じて実数値を表す整数値を運びます:
スケールとゼロ点はモデルの学習時のキャリブレーションに由来し、モデルファイルに保存されます。それらは input_scale、input_zero_point、output_scale、output_zero_point として公開されます -- それぞれ入力または出力テンサーごとに1エントリを持つリストです。
ml.utils.quantize() と ml.utils.dequantize() は、指定された出力インデックスに対して数式を適用します:
import ml.utils
real_tensor = ml.utils.dequantize(model, q_tensor, index=0)
q_tensor = ml.utils.quantize(model, real_tensor, index=0)
どちらの関数も、指定されたインデックスの出力dtypeが既にfloatの場合は値を変更せずに返すため、モデルの量子化状態に関係なく呼び出しは安全です。
7.8.2. 出力側でスクリプトが見るもの¶
predict() が返すものは、ポストプロセッサが登録されているかどうかに依存します。
ポストプロセッサがない場合、エンジンの生の整数出力は自動的に逆量子化されてfloatになり、float ndarray オブジェクトのリストとして返されます。スクリプトは読み取り可能な実数値を受け取ります。これは分類ネットワークに適したパスです。分類ネットワークの単一の出力テンサーは、アプリケーションが反復処理するクラスごとの信頼度スコアのリストであり -- デコードステップは不要です。また、未知のモデルを素早く動かすため、あるいはREPLからのその場での調査のための簡単なパスでもあります。
ポストプロセッサが登録されている場合(コンストラクタの postprocess= またはpredict呼び出しの callback= を通じて)、生の量子化されたテンサーがポストプロセッサの呼び出し可能オブジェクトに直接渡されます。ポストプロセッサは生の量子化されたテンサーを受け取り、必要な逆量子化を行う責任を負います。
この分岐はパフォーマンスの選択です。自動逆量子化は各出力に対して新しいfloatテンサーを割り当て、すべての要素を走査します。各テンサーから少数の値だけを必要とするポストプロセッサ -- 信頼度スコアをしきい値処理し、生き残ったものについてボックスをデコードする -- は、残りを逆量子化するコストをスキップします。ml.postprocessing 下に同梱されているボックスデコーダはすべてこのルートを取り、ml.utils.threshold() はまさにこのケースのために作られています。これは量子化されたスコアテンサーを受け取り、テンサー全体を逆量子化することなく、逆量子化された値が実数値のしきい値を通過するインデックスを返します。