7.1. ニューラルネットワークとは¶
ニューラルネットワークとは、その振る舞いが手作業でコーディングされるのではなく、例から学習されるアルゴリズムです。同じネットワークアーキテクチャでも、100万枚の顔画像を与えれば顔を検出することを学習します。同じアーキテクチャに100万枚の手の画像を与えれば手を検出することを学習します。同じアーキテクチャに多数の物体カテゴリを網羅したラベル付きセットを与えれば、それらすべてを一度に検出することを学習します。ターゲット間で変わるのは重みだけであり、その重みはオフボードの訓練プロセスによって生成されます。このプロセスはラベル付きの例に対するネットワークの予測を監視し、両者が一致するまで重みを調整します。
7.1.1. 仕組み¶
ニューラルネットワークは層を積み重ねたものです。各層は前の層の出力に重みの行列を掛け、バイアスベクトルを加え、その結果に非線形関数を適用します。ある層の出力は次の層の入力になります。取り込んだ画像はスタックの最上部から入り、数十から数百の層を通って下へと流れ、最下部で画像に何が写っていたかを記述する要素を持つテンソルとして出てきます。
各層の重みが何を行うかは、ネットワークが何で訓練されたかに依存します。ビジョンネットワークの初期層の重み行列は、短い水平エッジに反応するかもしれません。少し深い層では角に反応するかもしれません。さらに深い層では円形の目の形に反応するかもしれません。最も深い層では顔全体の配置に反応するかもしれません。これらはどれも手作業で書かれたものではありません。訓練プロセスが数百万のラベル付きの例を反復処理し、損失関数に沿って重みを下方へ少しずつ調整した結果、エッジ・角・目・顔という階層構造がデータから自然に現れたのです。
層のスタックとしての小さな分類ネットワーク。入力テンソルは取り込んだ画像の形状で最上部から入り、各層がテンソルの次元を変換しながら下方へと流れます。最下部の出力テンソルはクラスごとに1つの要素を持ちます。検出ネットワークやキーポイントネットワークも同じ層スタック形式を共有しており、変わるのは出力テンソルの解釈だけです。¶
ネットワークのアーキテクチャ――層がどのように配置され、どの演算が層をつなぐか――は、ネットワークが何をできるかを表します。重みはネットワークが何を学習したかを表します。このうちカメラが担う部分は、訓練によって生成された重みファイルを読み込み、トレーナーが実行したのと同じ計算を、ただし訓練セットの代わりに取り込んだフレームに対して実行することです。
7.1.2. 何が入力され、何が出力されるか¶
ネットワークの両端はどちらもテンソル――数値の多次元配列であり、numpyの章で紹介したのと同じ種類のオブジェクトです。ビジョンネットワークの入力テンソルは、取り込んだ画像をネットワークが期待するレイアウトに並べ替えたものです。典型的には (B, H, W, C) という4要素タプルの形状で、B はバッチ次元(カメラ上では一度に1フレームを処理するため常に1)、H と W はネットワークが期待するピクセル単位の高さと幅、C はチャンネル数(RGBネットワークでは3、グレースケールでは1)です。
出力テンソルはネットワークの用途に依存します。
分類ネットワークは、クラスごとに1つの信頼度スコアを持つ1次元テンソルを生成します。最大のスコアのインデックスが予測されたクラスです。ほとんどのカメラに搭載されているMobileNet由来の人物検出器はこの形式で、「人物」用と「人物でない」用の2つのスコアを持ちます。
検出ネットワークは、バウンディングボックスのリストとクラス確率を記述する要素を持つ2次元テンソルを生成します。YOLOv8 はこの形式です。
(84, N)テンソルで、84行のうち4行がボックス回帰値、残りの80行がクラスごとの確率であり、これがN個のアンカー位置にわたって繰り返されます。キーポイントネットワークは、名前付きランドマークのピクセル位置を要素とするテンソルを生成します。MediaPipe の顔ランドマークモデルはこの形式で、検出された顔ごとに468個のキーポイントを持ちます。
セグメンテーションネットワークは、ピクセルごとのクラスラベルを要素とする2次元テンソル――入力と同じ次元で、すべての位置にカテゴリインデックスを持つもの――を生成します。
回帰ネットワークは、単一の数値または短い数値ベクトル――深度推定値、角度、温度など――を生成します。
各形式には、生の出力テンソルを、アプリケーションの残りの部分が使用する結果形式――バウンディングボックス、キーポイントのリスト、クラスラベル、数値推定値――に変換する独自のポストプロセッサがカメラ上にあります。ポストプロセッサはネットワークの出力レイアウトを把握しているアプリケーション側のコードです。ネットワーク自体はテンソルを生成する計算にすぎません。
7.1.3. なぜこれがカメラ上で動作するのか¶
2つの計算上の工夫が、これをマイクロコントローラクラスの部品で実用的なものにしています。1つ目は量子化です。訓練は32ビット浮動小数点演算で行われますが、推論はほとんどのネットワークでほぼ精度損失なく8ビット整数演算で実行できます。8ビットの重みはストレージを4分の1しか使わず、32ビット浮動小数点数より数倍高速に動作します。カメラに搭載されるすべてのモデルは、すでにオフボードで量子化されています。
2つ目はハードウェアアクセラレーションです。マイクロコントローラのCPUが一度に1命令ずつ処理していく同じ計算を、ニューラルネットワークアクセラレータは一度に数百の演算で実行します。新しいカメラ(AE3 と N6)には専用のニューラルプロセッシングユニット(NPU)――SoC上のテンソルアクセラレータ――が搭載されており、CPUでの実行に1秒かかっていたモデルを数十ミリ秒で実行できるようにします。推論エンジンの章では、このうちカメラが担う部分がどのようなものかを扱います。
7.1.4. この章で扱う内容¶
訓練はカメラの仕事ではありません。訓練済みモデルは .tflite ファイルとしてカメラに届きます。カメラはそれを読み込み、取り込んだ各フレームをそれに通し、得られたテンソルをアプリケーションが行動を起こせる結果へとデコードします。以降の内容は、これらの各ステップに関するものです。
モデルの読み込みと検査、
モデルファイルが格納されるフラッシュパーティション、
推論呼び出しの4つの段階、
実際に計算を行うエンジン、
そして出力テンソルをボックス、キーポイント、クラスのリストへと戻すポストプロセッサ。
imageの章の検出器は、それぞれ特定のターゲットに合わせて作られていました。この章の残りで扱う検出器は、代わりにデータから訓練されており、スクリプトが読み込むモデルが何であれ同じエンジンが実行します。これらに伴うワークフローの変化――ターゲット固有のアルゴリズムが、ターゲット固有の重みファイルに置き換わったこと――が、次に掘り下げるべきことです。