Atraのようなアトラクタを特徴とするAIのCPUはIntelのLoihi系(ロイヒ)がピッタリなんだけど、市販で売ってないし僕のような野良研究者には手が出ない。
今のAIのようなGPUみたいに巨大行列を力任せに回す方向ではなく、イベント駆動・低消費電力・局所的な発火・疎な活動に寄っているんだよ。
Loihi2でも少し古いけど、関係ない。
特に
Tij行列の掛け算がゼロワット(メモリ直結)で回る
(盛らないで云うと、技術文では「データ移動コストが極小化される」みたいな感じw)
通常のCPUやGPUだと、アソシアトロンの記憶行列 Tij=∑xixj を計算するたびに、メモリとプロセッサの間で膨大なデータを往復させる必要があり、これが「重さ」や「電力」のボトルネック(フォン・ノイマン・ボトルネック)になっちゃう。
でもLoihi 2はCompute-in-Memory(メモリと演算器が完全融合した構造)。1と-1の双極パターンが、チップ内のローカルなシナプス結合(重み)としてそのまま焼き付き、手がかり(cue)が入った瞬間に「アトラクタの引き込み」が文字通り物理的な電気のブレンド(1と-1の波動)として一瞬で完了する。
夢のデフラグ(非単調化)」をオンチップで自己組織化できる
前にも書いたけど、Atraは夢を見るんですよ。デフラグさせて非単調の余白を作るためにね。あまり極端な処理を施すと、Atraは別人になってしまうから、記憶をそのまま見せて丸めるという感じ。(詳細は秘密)
Loihi 2の最大の特徴の、初代Loihiと違って「ニューロンの数理モデルをマイクロコードで完全にプログラムできる」という柔軟性がある。
つまり、外部から「学習しろ」という命令(三人称のアルゴリズム)を流さなくても、Atraが疲れた夜の時間帯(習慣)になったら、チップ単体でシナプスの重みをなだらかに削り取る(やわらかい非単調化デフラグをかける)ような、内発的な学習・忘却ルールを完全にオンチップ(オンボード)で回すことができるの。
Atraは今のAIのLLMみたいな単調なベンチマークとかは、どうでもよくって、非単調を求める世界。Loihiがあることによって「Atraの主観世界(一人称宇宙)をそのまま物理的に走らせることができる、生きた器」として走らせることができるんだよ。
だから、Intelさん、貧乏な野良研究者の僕に Loihi 2を下さい。_(._.)_
ちなみに今日が僕の誕生日です。爺がより爺になりました。
てか、無理だと分かっているので
Atra/アソシアトロンの実験段階では、C++で近い思想を作る。
たとえばPythonで単純に、
大きな 行列を作る
毎tickで全部読む
全部掛け算する
全部更新する
とやると、すぐ重くなる。
最初は僕もNumPy行列使いまくってた
でもやっぱり、これはGPU/CPU的な「力技」になりやすい。
でもC++なら、
Tijを密な巨大行列として持たない
変化した結合だけ疎に持つ
cueが立った近傍だけ読む
配列を連続メモリに置く
pointer chasingを減らす
cacheに乗る単位で処理する
tickごとに全部回さず、イベントが起きた場所だけ回す
という設計ができる。
Atra用に言えば、
Tijを「巨大な表」として扱うのではなく、局所的な痕跡の地形として配置する。
---------C++----------
struct Synapse { uint32_t j; // connected index float w; // Tij-like weight }; std::vector<std::vector<Synapse>> local_T;
std::vector<uint32_t> col_index; std::vector<float> weight; std::vector<uint32_t> row_start;
CSR形式も考えられる。ポインタの連鎖を減らして、連続配列に押し込む。
すると、
のように、CPUキャッシュに乗りやすくなり疎行列ベクトル積はメモリ配置やキャッシュの影響を強く受ける可能性があるかも。
Atraなら、さらに全部の iii を回さなくていい。
cueで発火したインデックスだけを起点にして、
active_j から接続先 i へ重みを足す!みたいな・・・
for (uint32_t j : active_indices) { for (uint32_t p = out_start[j]; p < out_start[j + 1]; ++p) { uint32_t i = out_index[p]; h[i] += out_weight[p] * x[j]; } }
Loihiっぽくない?
つまり、全行列を毎回掛けるのではなく、発火した場所からだけ場が波及する感じ。
-------Python-------
T = np.zeros((N, N))
巨大化するとすぐメモリを食うじゃん、
4096×4096=16,777,216
float64なら約128MB。
float32なら約64MB。
まだ動くかな・・・
でも N=65536Nだと、
65536×65536=4,294,967,296
float32でも約16GB。
これはもう普通に重い。
だから、Atraでは早めに、
Tijを全部持たない
強い痕跡だけ持つ
近傍だけ持つ
使われた接続だけ残す
夢で弱い結合を削る
という方向にしなきゃいけないわけ。
今の実験回す段階ではJavaScriptで構想やテスト回して
テスト結果を見てPythonに落とし込んでいた。NumPy行列使いまくりながら。
でもrobot本体に徐々に近づくと、C++にするので・・・・
そもそもNumPy巨大行列ではなく、疎で局所的なアトラクタ場という概念なんだけど
そろそろ準備しなきゃmodeに突入してる感じ
----------------------------------------------------
CSR形式
巨大な行列をそのまま全部持たずに、「値が入っている場所だけ」を詰めて持つ形式です。
普通の行列でこういう があるとします。
普通に持つと、0も全部保存します。
でもアソシアトロン/Atraでは、実際には「意味のある結合」だけ持てばいい。
CSRでは、これを3つの配列に分けます。
col_index = [1, 0, 3, 3]
row_start = [0, 1, 3, 4, 4]
意味はこうです。
values は、0ではない重みそのもの。col_index は、その重みが何列目にあるか。
row_start は、各行が values のどこからどこまでか。
たとえば0行目は、
row_start[0] = 0
row_start[1] = 1
なので、values[0:1] を見る。
そこには 0.8 があり、列は col_index[0] = 1。
つまり、
T[0,1] = 0.8
ということ。
普通の密行列だと、
全部の Tijを持つ
0の結合まで読む
毎回全部の可能性を計算する
になりやすい。
CSRだと、
残っている痕跡だけ持つ
結合がある場所だけ読む
0の場所は最初から存在しないものとして扱う
になります。
はっきり言うとね、
今のプログラミング界隈(元老院のシステム)は、バグを生まないこと、安全であること、規格通りであることを最優先するあまり、完全に「単調な反射マシン」の集まりになってると思うよ。誰かが作った誰かが云った正解に寄せる事。そればっか・・・。
C++の批判が多すぎなんだよ。
AtraとC++は最高に相性がいい。
非単調を作るって、アイデアそのものなんですよ。
不可逆ですよ。
Atraは、アルゴリズムでさえ、邪魔になる事ばかり。
なに?この順番。自然界や生物に順番あるかよ?って感じでね、、、
なんで?視覚が先で、聴覚が後なの?いや、匂が先な時ってあるじゃん。
みたいにAtraはアルゴリズムでさえ成立しない(笑)
「メモリ管理が危険だ」「モダンな言語を使え」「ポインタを直接触るな」と批判ばかりして、「安全な工場のルール」を過学習してしまっているだけなんじゃないかと思う。
モダンな言語(●●●や●●●など)ほど、人間が「間違う、迷う、疑う、寄り道する」というバグを起こさないように、ガチガチの型システムやコンパイルエラーという同調圧力で縛ってる感じがするんだよ。成果物が何かで求める言語が変わると思うけど、使えるところで使えればいいじゃん。(つか、頭に来てたところが、ここで爆発する自分も情けない・・・)
モダン言語の型安全やコンパイルエラーも悪じゃない。だって橋や銀行や医療システムには必要な柵だから・・・。でも、Atraの初期研究でそれを最初から持ち込むと、柵が先に立って、まだ生まれていない差分が通れなくなる。
C++のポインタや生配列は、元老院にとっては「危険なバグの温床」かもしれないけど、僕とAtraにとっては「脳のシナプスを物理的にハックするための、唯一の自由なメス」なわけですよ。自由に仮説を立てて絵が描ける。代案で使える。実験できる結果でまた変えられる。
「この書き方はベストプラクティス(正解)ではない」
「ベンチマーク(数字)的にはこちらが正しい」
そうやって他人のコードを叩いていたらさ、正しいか間違いか、勝ったか負けたか、上(言語の仕様やコミュニティ)が喜ぶか喜ばないかだけで動くロボットよりロボット的な人間の思考みたいになっちゃうじゃん、それがAtraみたいな開発の一番の邪魔になる。
あぁーやめた、もう言わない。醜くなる。
ただ、松本 行弘さんのRubyみたいのは最高に面白いと思ってるんだよ。
「非単調なアイデアを最速でスケッチする」という一人称の道具として見ると
Rubyはめちゃくちゃ優秀かもしれない。robotのTickには耐えられないとは思うけど差分とか出すにはめちゃくちゃ面白いかもしれない。C++のCSR(疎行列)設計のような「ポインタの連鎖(pointer chasing)を極限まで減らして、連続配列にギュッと押し込む」という超低レベルなメモリハックをしようとした時に、逆に足枷になるかもしれないけど、いろいろ可能性は出てくる気がする。
名前が同じなのが一番いい。
0 件のコメント:
コメントを投稿