機械学習からディープラーニングまでをちゃんと理解して、FPGAに持ち込みたい

AI・機械学習

機械学習のモデルをFPGAへ持ち込むなら、正解率だけでなく、演算をどこに置き、データをどう流すかまで考える必要があります。モデルをPCで動かせても、そのまま回路にはなりません。

自分はFPGA側から入ったので、まず小さな問題で古典的な手法を試し、ニューラルネットの計算を追ってから、CNNの速度や量子化を見ることにしました。まだFPGAでの推論速度を測ったわけではありません。ここでは、PC上で確認できたことと、回路を作らないと分からないことを分けて整理します。

古典的な手法を基準にする

画像分類でも、最初からCNNが勝つとは限りません。FashionMNISTでHOG+Linear SVMとCNNを比較したところ、テスト1万枚の正解率はHOG+SVMが88.85%、3エポック学習したCNNが87.00%でした。一方、特徴量抽出とSVMの学習には約64.2秒、CNNのGPU学習には約3.59秒かかっています。精度と学習時間では選ぶものが変わります。

HOGは画素の明るさの変化から輪郭の向きを取り出します。Sobelのような差分計算や、局所領域を切り出す処理は、FPGAでもデータの流れを考えやすい部分です。ただし「回路にしやすそう」と「実際に速い」は別です。必要なラインバッファ、並列度、メモリ帯域は対象の画像サイズで見積もらなければなりません。

8×8のDigitsでロジスティック回帰とSVMを比べた実験でも、RBF-SVMは平均正解率98.06%で、ロジスティック回帰の97.04%を上回りました。ただし360枚の推論は約20倍長くかかりました。モデル名だけでなく、必要な精度と処理時間を先に決めておきたいところです。

勾配の計算を一度は追う

ニューラルネットはPyTorchで手早く動かせますが、重みがなぜ更新されるのかを見たいなら、NumPyだけで2層ネットワークを作った実験が役に立ちます。順伝播、損失、逆伝播を実装し、有限差分による勾配チェックで計算を確かめました。

その後、同じ構造をPyTorchへ移した実験では、手実装の勾配と自動微分の結果を照合しています。ここまで確認すると、loss.backward()が何を省略してくれているか分かります。4,810パラメータの小さな学習では、GPUよりCPUのほうが短時間でした。GPUが使えることと、GPUが速いことも別です。

CNNでは計算よりデータの流れが気になる

畳み込みは、画像の局所領域を取り出し、重みを掛けて足し合わせる処理です。FPGAなら画素をどの順番で受け取り、どの行をラインバッファへ残し、窓を何個並べるかを考えます。チャネルが増えると重みや中間特徴マップの置き場所も効いてきます。

たとえば28×28のモノクロ入力で3×3畳み込みを1画素ずつ流すなら、単純な見積もりでは直前の2行を保持します。入力を1画素1 byteに量子化した場合、28画素 × 2行 × 1 byte = 56 bytesです。これは最初の層の画素保持だけの概算。実際には窓のレジスタ、境界処理、並列読み出し、重み、後段の多チャネル特徴マップが加わります。56 bytesという数字だけでBRAM使用量を決めることはできません。

PC側でもデータ供給の影響は見えました。FashionMNISTのCNNをCPUとRTX 5070 Tiで学習すると、この約10万パラメータのモデルではGPUが優位でした。ただしDataLoaderのワーカー数を変えた実験では、画像にCPU側の変換を加えると、GPUが次のバッチを待つ時間が速度を左右しました。演算器だけ速くしても、入力が届かなければ遊んでしまいます。

量子化は容量・精度・速度を別々に見る

FPGAを意識するとINT8やINT4が気になりますが、bit数から性能を決めつけるのは危険です。FashionMNIST CNNの重みを丸めた実験では、INT8 per-channelは元の正解率86.50%を保ち、INT4 per-tensorは81.99%まで下がりました。INT4でもper-channelなら85.95%です。同じ4 bitでも縮尺の持ち方で結果が変わりました。

この実験は重みを整数へ丸めてからFP32へ戻す模擬量子化です。整数演算の推論速度を測ったものではありません。PyTorchからONNXへ変換したときの出力と速度も別に確認しましたが、ONNXにしただけでFPGA上の性能が分かるわけではありません。

FPGAへ移す前に残るもの

PCだけで確認できるのは、モデルの正解率、誤分類、演算の形、量子化による予測の変化、入力待ちや推論時間などです。FPGA上のレイテンシ、DSP・BRAMの使用量、外部メモリの帯域、タイミングが閉じるかどうかは、実装して測らなければ分かりません。

PC上の実験では、入力待ちや特徴量の準備に時間を使う場面がありました。回路へ移す際も、掛け算の数だけでなく、その前後にどれだけデータを運ぶかを見積もっておきたいところです。