Ryuz's tech blog

FPGAなどの技術ブログ

リアルタイムコンピューティング的CNN再考

はじめに

当方はFPGAを使ったリアルタイムコンピューティングをメインに活動しております。

流行りの深層学習は私の中では One of them でしかないつもりなのですが、それでも昨今どうしても無視はできないので、リアルタイムコンピューティング観点でCNNを眺めなおしたらどうなるのかというのを再考察してみたいと思います。

まずリアルタイムコンピューティング的には

  • 入力をなるべく低遅延で出力に反映させる
  • 情報は古くなると価値が下がるという前提で、価値が最大化するようアルゴリズムと計算機アーキテクチャをセットで考える

の2点を大事にしています。

世の中は計算している間にどんどん変化していきます。壁にぶつかってからブレーキを踏んでも遅いし、ロボットが流れてくる不良品の隣の良品を廃棄しても困るわけです。

CNNを考えてみる

当方は画像信号処理を扱うことが多いので、無難にCNNの話をします。よくあるこんなやつです。

よくあるCNNのアーキテクチャ

フルサイズで入力された画像を順番に各レイヤーで処理して、途中でプーリング処理を挟んで小さくしながら、でも特徴量を表すチャネルの深さは深くなりながら(次元数を増やしながら)次々と処理していきます。

特にこのプーリング処理で縮小されていくのは重要で、前段では細部を、後段では全体を認識することができます。

画像処理でもよく画像ピラミッドを作りますが、縮小された画像で全体を把握しつつ、オリジナルの解像度に近いところで細かい計測をします。

さて、この段階で、入力から出力までのレイテンシが長そうだというのがなんとなく想像がつくわけです。

リアルタイムコンピューティング的に考えてみる

リアルタイムコンピューティング的には入力をなるべく低遅延で出力に反映させるという事がしたいわけです。

ここで唐突にセマンティックセグメンテーションを考えてみます。

カメラからは左上のピクセルから順に画素が読み出されてきて計算機に入力されるわけですが、1画素新しい情報を得たら、なるべく早くその画素がどういうクラスなのか情報を出力したいわけです。

となると、まあ、下図のようなアーキテクチャに考えが至るわけです。

リアルタイムコンピューティング的CNN(妄想)

まず、何はなくとも、入力されたらなるべくすぐに、赤い線のようにまっすぐと入力画素に対応する部分の出力結果をアップデートしたいわけです。

そうはいってもこれだと、例えば 3x3 の畳み込み層だと遅延は2ライン貯める時間で済んでも、高々周辺の9画素の情報だけで推論しろという無茶な話になります。

ここで、本サイトお得意の1000fpsの高速度カメラなどの話になります。世の中の変化より十分早くオーバーサンプリングしておけば、少し大雑把な周辺情報は1フレーム前の情報でもある程度あてにできるよね? という、撮影対象のダイナミクスよりもサンプリングレートを上げる話に持っていきます。

要するに例えばCNNでありがちな犬猫認識をしつつ動きを追う場合、「猫パンチの手の位置は素早く動くが、1/1000秒後にそこにいた猫が犬に入れ替わったりはすまい」という前提で、「手の動きは最新フレームで追いかけるが、その手が猫のものか犬のものかは少し古い画像も使って認識してもいいよね」というアルゴリズムにするわけです。

で、これを以前やりかけたまま放置してるのが、以前書いた

ミップマップを使ったIIRフィルタライクなRNNを考える - Ryuz's tech blog

です。

まあ、学習させるのがしんどくてそのうち高価なGPU買う機会があったらやろうと放置したまま幾星霜。

しかしまあそういう思想なわけです。

Layer1 で最短経路で出力を更新しつつ、Layer2 以下で Pooling して縮小した画像を処理してさらに下の層へ。一方で、下の層の認識結果も同様にアップコンバートしながら上に戻していくわけです。

各レイヤーでそれぞれのサイズ感での認識ができればな、というのと、過去のデータの更新という意味で RNN 的な要素も取り込めればと思ってしまうわけです。

計算効率をどう上げるか

最近Xのこのへんで書いた話なのですが、画像ピラミッドの縮小に目を付けた話です。

畳み込み層といっても中は IM2COL した後は普通の全結合層が入っているわけですが、全結合層を考えると入力100chで出力100chの時、10000接続あるわけでch数の二乗で演算量とパラメータ数が増えていくわけです。なので画像サイズが1/4になってもチャネルが2倍になると計算量は元と変わらなくなります。

一方、私のやってる LUT-Net の場合、物理制約で 6入力LUTのカスケード数で例えば3段の場合 63=216固定であり、ch数が倍になっても接続は倍にしかなりません。どういうトリックかというと、全結合層の場合、1つのチャネルは全部の出力にもれなく重複して繋がってるところ、LUT-Net ではどんどん重複が減って疎結合になっていく代わりに計算量がリニアな伸びに制限できます。

でまあ、LUT-Net の場合はパラメータ入れ替えできないからこういうことはできないのだけど、仮にDSPとか普通のネットに同じようなポリシーで疎結合化をできたとしたら、単に演算量の話だけすると、1, 1/2, 1/4, 1/8 ・・・ と減っていくよねと。 でほんとにそんなことが出来たら 1 + 1/2 + 1/4 + 1/8 +・・・ = 2 なので、2レイヤー分の演算ユニット入れておけば全部うまいこと回せないかと。低遅延&演算器稼働率100%が目指すところではあるわけです。

演算ユニット2つで無限の深さをやれないか?(妄想)

猫が猫かどうか認識する機能なんて、猫のサイズを同じサイズまでリサイズすれば同じ認識器でいけるはずだし、単純に探索範囲=画像サイズで縮小するほど処理量減っていくはずだし、なんか、なんとかなりそうな気がしなくもないところです。

まあ、実際問題、どうやって学習させるんだとか、精度出るのかとか、いろいろ未知数というかほとんど妄想なのですが、晩酌しながら考えて呟いてしまったわけです。

おわりに

上記のような考えが、まあ半分以上妄想として、じゃあ全部妄想かというとおそらくそんなことは無くて、リアルタイム計算にもっと適したネットワークモデルというのは少なからず、今のCNNより改善できる形はあるであろうし、それを学習させる方法なんかもまだまだ未探索な世界なんじゃないかと思います。

また上記はあくまで「空間認識」において、広い範囲を見るために縮小という概念を時間方向に展開して効率化を試みたわけですが、RNN構造はそもそも「変化に含まれる情報の識別」という意味合いも持っておりますので、学習データ次第ではこの構造で例えばジェスチャー認識のようなもっと動きパターンに起因するものを認識できる可能性なども出てくるかもしれません。

こういったシステムを実際に作ってみて、試してみるというようなことができるのが、FPGAの良いところであり、計算機科学に興味を持つメリットが生まれてくるところです。

どこかの誰かの新しいアイデアに繋がれば幸いです。