はじめに
当サイトでは、応答時間がミリ秒以下になるような、高リアルタイム性のコンピューターシステムを検討対象としており、AI(というか機械学習)もその対象範囲です。
このようなリアルタイム性の条件下でAIを考える場合、通常の AI のように単に高精度な結果を出せる学習モデルを設計するだけではだめで、時間経過の中で今出力できる最善の解に更新を繰り返していくモデルを設計し、 実世界のダイナミクスに追従する適応性 を持たせることが必要になります。
ですので今日はあまり一般的な話ではなく、この分野に閉じて、少し考察をしてみようと思います。
メモリ階層とモデルの矛盾
一般的な計算機のメモリは階層的になっており、CPUなどでも1次キャッシュから3次キャッシュ、外部SDRAMなどの階層で、容量が小さく高速なものから順に、大容量で低速なものになっていきます。
FPGAなど、自由に計算機アーキテクチャを設計できるデバイスにおいてもこれは同様で、利用できる演算資源としては、階層的になっており、例えば以前に下記のような絵を描いたことがあります。

一方で、リアルタイムコンピューティングでは、新しい入力から出力更新までの制約時間の中で読み出せる量のデータしか使えません。 例えば サンプリングレート 1kHz (1000fps) で1ms (1ミリ秒は 1000分の1秒) で応答する処理を行う場合、メモリがどんなに大容量であっても 1ms で読み出せる量のデータやパラメータしか演算に投入することができません。
そうすると、大容量メモリほど少しのデータとパラメータしか使えない という一見矛盾したことが起こり始めます。

しかしこれはとても重要なことで、同じくリアルタイム処理であるグラフィックスレンダリングの処理などでは、例えば 60fps でゲーム画像をレンダリングしたい場合、16.6ms で読み出せるデータ(テクスチャやポリゴン頂点など)しか描画に使えません。 そうなると容量よりもデータ帯域が重要となり、GPUには GDDRメモリなど容量は少ないが高速なメモリが採用されてきた歴史があります。
高リアルタイムシステムほど、これのもっと極端なことが起こっていきます。
ではそのような制約下でどのようにAIモデルを考えていくかと言うのが本記事の考察です。
階層メモリのリアルタイムでの活用方法
それではパターン別に大容量メモリをうまく使う方法を考えていきます。大きくはデータの履歴(状態変数も含む)の保持に使うパターンと、学習パラメータを置いておくのに使うパターンとがあると思います。
データ履歴の活用の工夫
最初に過去のデータを利用する観点で考察します。今入力されたデータだけでなく、過去に入力されたデータを使う事で、空間的な広がりや、時間的な変化を認識できるようになります。
データの古さで置き分ける
もっともオーソドックスな使い方がこれでしょうか。例えば画像処理においては
のようにすると、空間と時間の3次元方向の周辺情報を使ってそのピクセルを処理することができます。 画像のようのものは1フレーム自体が巨大ですし、場合によっては何フレームも過去の情報を使いたい場合は容量の多い外部メモリを活用できます。 内蔵メモリにフレーム全部が収まらないにもかかわらず、カメラデータ入力の数倍程度のメモリ帯域があれば、演算対象のピクセル周辺のデータは常にオンメモリに持ってこれる構成が作れます。
状態空間モデルで、各ピクセル位置に状態を持たせる場合でも、状態変数をフレームと一緒に外部SDRAMに記憶して、次にそのフレーム位置が来た時に状態を復元して、次の時刻の計算を行うのも合理的な使い方と言えるでしょう。
特に周期性を持った時系列処理においてこの考え方は非常に重要で、例えばお店の売り上げのような時系列データでも、曜日や季節に影響を受けるため、昨日の同じ時間、先週の同じ曜日、先月の同じ日、昨年の同じ日、などとはしばし比較評価を行います。 大容量メモリが大量の容量を持っていることを利用して、ピンポイントで古い情報を利用するのに利用するわけです。
お店の売り上げの例だとあまりにも長いですが、我々の身の回りや、産業応用などでは、エンジンの回転周期ぐらいの周期性を持った時系列は沢山あります。特に人間には感知できないぐらい高い周波数でも計算機なら感知できるというのは重要なことだと思います。
選択的に履歴を選ぶ
履歴はそのままフラットに記録しておき、どこを読み出すかを選択的に選ぶことで読み出しデータ帯域を抑えることもできます。
以前に、ハイフレームレートでは動き補償の計算が激減できるという話をしたことがありますが、該当するピクセルに写っていた物体が、過去のフレームのどこにあるか追跡しながらそこだけピンポイントで取り出してくることもできます。
例えばバイクに乗って手を振っている移動している人から、「手を振っている」という時間変化成分を加えてた認識が、限られたメモリ帯域の中でできる可能性など出てくるわけです。
動き補償は極めて強力な武器で、60fps で 16ピクセル移動する物体でも、1000fps なら1ピクセルしか移動せず、CNN の3x3の畳み込みフィルタに収まってくれます。
また ViT などの応用で、画像の中の注目すべきポジションを計算して、次のフレームでそのあたりを重点的に読み出すのも手です。
これもリアルタイムシステムであれば、1ミリ秒の間に最大で何ピクセル移動するかは、物理的に制約できる事が多いですので、対象のダイナミクスにあわせてマージンを設定すればよく、効果的に過去のデータを限られた帯域の中で活用できます。
過去の情報を要約(圧縮)して使う
これには時間方向の要約と空間方向の要約の2つの軸があると思いますが、読み出し時ではなく書き込む際にデータ量を圧縮してしまう方法です。
いずれも要らなくなった情報から順に削除したり圧縮したりしていきます。 例えば古いものを 1/2 に出来れば、 1/2 + 1/4 + 1/8 + ・・・ = 1 ですので、決まったメモリ帯域の中で履歴にアクセスし続けられる計算になります。
例えば以前に単純に画像を縮小していくというMIPMAP方式を提案したことがあります。 Attention 的に有用なものだけ残す手もありますし、また、認識まで行ってもっとメタ情報として圧縮する方法もあるでしょう。
縮小を行うと1つのピクセルの処理において、より広い範囲を俯瞰して判断することが可能になり認識精度が上がります。
画像処理では認識したい画像特徴に対してスケール普遍性がある場合が多く、画像ピラミッドを作って認識することは多いです。 CNNなどでも特徴量の世界でもこれは同じであり同じ認識器をマルチ解像度に適用していくのは合理性があります。
また動き補償と縮小とを組み合わせると、把握できる範囲が 6x6、12x12、24x24 ・・・ と倍々で広がりますので、多少の移動速度であれば簡単にスコープに捕らえます。過去の動きは大雑把に追跡して、最新位置を最新の最大解像度の画像で正確に認識し、さらにその情報を次のフレームに状態として引き継げるわけです。
パラメータ利用の工夫
昨今のAIでは 入力データよりもパラメータの方がはるかに巨大 ということがしばしあります。
すべてのパラメータがFPGA内などにオンメモリにもてれば何の苦労もないわけですが、残念ながら外部SDRAMなどにパラメータを置いておいて動的に入れ替えなければ、極めて小パラメータのモデルしか使えないことになってしまします。
パラメータを動的に変更する
例えば、高速に応答したい物体Xの認識パラメータセットと、その他の認識対象セットがA、B、C、D・・・ と何セットかあった場合
X → A → X → B → X → C → X → D → X →
のようにタイムスロット(画像なら1フレーム毎とか)ごとにパラメータセットを入れ替える手が考えられます。
1つのタイムスロットで読み込めるパラメータ数は決まっていますので、時間ごとに切り替えることで、見逃せない X を頻繁に調べつつ、他のものも探索するようなことは十分にあり得ます。
100クラス認識できるものを 10 回入れ替えて 1000クラス分類に近づけていくようなアプローチでしょうか。
選択的にパラメータ使う(MoEなど)
MoE(Mixture of Experts) も最近よく耳にする技術になってきました。これはもちろんリアルタイムAIでも重要な要素だと思います。
画像認識も、街中や森の中、夜間や霧、顕微鏡画像やMRI画像など、環境の違いもあれば、認識したいものが人間だっり、自動車だったり、交通標識だったり、部品のひび割れだったり、病気の腫瘍だったり様々です。
これらをパラメータセットを沢山持っておいて、適応的に切り替えながらあらゆるシーンで活用することを考えるのも、限られたメモリ帯域を有効に使う上でとても重要です。
例えば、人間が前を向いた時、横を向いたとき、後ろを向いたとき、などそれぞれを学習させた認識器を使って、今どういう運動をしているかを認識しておけば、次のフレームでロードすべき認識パラメータはおのずと決まってきますし、変化や状況を見て適応的に次にロードするパラメータを選ぶことで、一度に使うパラメータ数を抑えながら幅広い認識を応答性良く行える可能性が出てきます。
ハイブリッドに使う
ここまで挙げたようなテクニックをハイブリッドに組み合わせることももちろんありだと思います。
特に、センサーの値を特徴量として汎用的にとらえる部位と、特徴量から目的に合わせた認識を行う部位はしばし分けて考えられます。
特徴量を作る部分では、例えば昼用と夜用などシーン変化に応じてパラメータを切り替えて常に高品質な特徴量を得られるようにして、後半は認識対象に応じてパラメータを切り替えるような手もあります。
100クラスのうち50クラスだけは常に同じものを認識するようにして、残りの50だけを変えたパラメータを入れ替えるなどもありでしょう。
用途にに応じた組み合わせこそが重要だと思います。
おわりに
アルゴリズム開発をしている多くの人にとって、0.1 秒で以下で終わるものと言うのは、どれも大差ないように思えるかもしれません。
一方で我々の生活するリアルな空間では、その 1/100 である 1ミリ秒(0.001秒)であっても、案外大きな変化をします。 人間は 100mを10秒 (1m を 0.1 秒)で走ってしまう生き物で、時速何百キロのボールを投げることもできます。 一般人がその半分の速度で動いても 1ミリ秒に何cm も移動するのです。
また、人間は応答に 0.1秒以上かかると言われています。ですので人間をアシストする計算機まで 0.1秒遅れてしまうと遅延が倍になります。計算機がアラートを出してから人間が回避行動をとるシステムにしたら 2倍鈍感な動作しか出来なくなった では悲しいわけです。
近年では フィジカルAI とか エンボディドAI と言われている領域の中には、これらが課題になる分野が間違いなくあります。
そしてこれらの分野にむけて学習モデルを作る場合、単に総演算量だけ考えればいいものではなくなります。
アルゴリズムを1ミリ秒などのタイムスロットで細切れにして、どこにどのようにデータを置いて、タイムスロット間では何を渡して、システム全体としてどう振舞うようにするか、を考える必要が出てきます。
考える事が一気に増えて複雑なパズルを解くことになりますが、これは好きな人にはとても楽しい話ですし、新規性のある独自の工夫や、他の方式との差別化がとてもやりやすい領域になります。
昨今の FPGA は、学生が研究用に研究室で買ってもらえるぐらいの価格帯のFPGAで、 ResNet18 を 60fps で動かせる程度の演算リソースは内蔵するようになってきました。これを 60fps の 16.6ms で計算するのではなく、 1/16 の演算量の計算を 16回に分けて行うことで、定常的には従来相当の認識率を保ちつつ、変化に対して 1 ms などの応答性を持たせることが出来れば大変興味深い研究になってきます。 最初の認識に 16ms (16フレーム)かかっても、それは従来と同じですので、そこから先に 1ms の応答性が手に入るなら大きな進歩を手に入れたことになります。
もしこういった分野に興味のある方、是非、いろいろ考えてみて頂けると面白いのではないかと思います。







![【改訂2版】FPGAボードで学ぶ 組込みシステム開発入門[Intel FPGA編] 【改訂2版】FPGAボードで学ぶ 組込みシステム開発入門[Intel FPGA編]](https://m.media-amazon.com/images/I/61swEqAWYhL._SL500_.jpg)































