
8,727 文字

みなさん、ようこそ。今日は「より良いディープラーニングに向けて」というテーマでお話しさせていただきます。
みなさんご存知の通り、私は大学におりますし、AMIにも所属しています。そして、Keen Technologiesっていう、いわゆるAGIのスタートアップでメインの仕事をしています。
それに、以前はオープンマインド研究所を設立しましたが、そっちもええ感じで進んでいて、もうすぐ最初のフェローを発表できるんちゃいますかね。
今日のお話は、副題を「理論的根拠とビジョン」としてます。つまり、どないしたらディープラーニングをより良くできるかっていう見方を示すつもりです。完全なアルゴリズムを提示するわけやないんですけどね。
既存の巨大なディープラーニング分野を改善するっていうのは、かなり野心的な目標やし、批判したり限界を指摘したりするのは、ほんまにせやなって思うかもしれません。でも、今日はそれをやっていきます。
この研究は新しいもので、まだ完成してへんねんけど、同時に他の多くの研究の上に成り立っています。既に発表されたものもあれば、誰かの論文に載ってるものもあります。
例えば、カーム・ジャヴェド、アルサロン・シャルフ・ナサブ、シャバン・フェルナンド、パラシュ・キング・ファン、ルパム(ルパムの学生)、ムハンマド・エラド、そして私の良き同僚のジョセフ・モダイルらの研究ですね。
最初のスライドで要点をまとめておきます。先ほど言うたように、これは理論的根拠とビジョンです。理論的根拠は青字で、ビジョンは緑字で示しています。
より良いディープラーニングについて話すんですが、特に連続学習に焦点を当てます。普通の一時的な学習とは違うんやっていうことを説明しますわ。
そして、ディープラーニングが連続学習には向いてへんっていう話をします。新しいより良いディープラーニングには名前をつけてみました。ダイナミック・ディープラーニングっていうんですけど、これは数日前に思いついたばっかりやから、どうなるかわかりませんけどね。
ダイナミック・ディープラーニングでは、ネットワークをユニットごとに成長させていって、時間とともに連続的に学習していきます。
キーアイデアは、バックボーンっていうのがあって、それは安定していて、その周りにフリンジっていうのがあって、そっちの方が動的で探索的やっていうことです。
フリンジはバックボーンの役に立とうとしていて、うまくいったらバックボーンの一部になるんです。
これを実現するには新しいアルゴリズムがいくつか必要になりますが、今日のトークでそれを想像してみましょう。
最後に言うておきたいのは、まだやることはたくさんあるんやけど、どれも特に難しそうには見えへんってことです。だから、前向きで楽観的であるべきやと思います。
さて、連続学習っていうのは、常に学習し続けるってことです。あらゆる瞬間が訓練であり、テストでもあるんです。
一方、従来のディープラーニングは一時的な学習やから、特別な訓練フェーズで学習して、それ以降は学習せえへんのです。つまり、通常の動作中には学習せえへんわけです。
この訓練とテストの分離は、めっちゃ人工的やと思います。一時的な学習は人工的なもので、自然なシステムはみんな連続的に学習しています。
私の観点からすると、連続学習は普通の学習で、特別な名前をつける必要もないくらいです。動物も人間も、みんな連続学習をしているんであって、一時的な学習をしているわけやないんです。
従来のディープラーニングは、少なくとも連続学習には不満足です。理由はいくつかあります。
時間とともに可塑性を失うんです。ネットワークが新しいことを学ぶ能力を失ってしまうんです。
破滅的忘却が起こることもあります。新しいことを学ぶと、古いことを忘れてしまうんですが、必要以上に忘れてしまうんです。実際、過去に学んだ最も重要なことを優先的に忘れてしまう傾向があります。
強化学習では、ポリシーの崩壊っていうのも見られます。ディープ強化学習エージェントを長時間走らせると、パフォーマンスが劇的に低下することがあるんです。問題を解決したように見えても、走らせ続けると崩壊してしまうんです。これはちょっと変な現象ですね。
この可塑性の喪失とポリシーの崩壊については、シャバンやフェルナンドらが示していて、数週間後には主要な出版物で発表される予定です。
一般的に言うて、ディープラーニングは遅くて脆弱です。訓練セットのすべての例を、相関のない方法で繰り返し提示せなあかんのです。ちょっとでもやり方を間違えると、忘却や可塑性の喪失が起こる可能性があります。
まあ、これくらいにしておきましょうか。バックプロパゲーションを使った通常のディープラーニングだけでは足りへんっていうことがわかりましたね。もっと違う考え方をせなあかんのです。
これは私の「頑張ろう」スライドです。今は2024年で、ディープラーニングが主流ですが、まだ違う考え方ができます。エージェントや強化学習に必要なものには、ディープラーニングはあんまりうまく機能しません。だから、それを手放して、リラックスして、勇気を持って違う考え方をせなあかんのです。
みなさん、違う考え方をする準備はできてますか?よっしゃ、行きましょう!
まず、従来のディープラーニングネットワークには、このような層状構造や、各部分に特定の役割がある層状構造など、あらかじめ設計された固定構造があることを認識しておきましょう。
一方で、私が考えているのは、もっと有機的なシステムです。ダイナミック・ディープラーニングネットワークは、ユニットごとに蓄積されていくんです。つまり、最大限に柔軟な成長構造を持つわけです。
これはカームが取り組んできたネットワークですが、実際に成長しています。単一の出力ノードと多くの入力から始まって、中間のユニット、つまり特徴ユニットを導入し、それらをどんどん追加していくことで、多層の大規模なネットワークになっていくんです。
これがダイナミック・ディープラーニングで目指す方向やと思います。ネットワークの成長方法について具体的なアルゴリズムは示しませんが、成長することを前提にして、どないしたらええかを一緒に考えていきましょう。
さて、これが最初の大きなステップです。最も重要なステップは、既に学習されたネットワークの部分を、残りの部分と区別することです。
この既に学習された部分を、私はバックボーンと呼びます。ここに私がボードに描いたネットワークの絵があります。青いのは無用なユニットで、黒いのがバックボーンです。
完全に学習されたディープネットワークには、機能に貢献せえへん死んだユニットがたくさんあることがわかっています。シャバンとフェルナンドが連続バックプロップの研究で示したように、学習の終わりには半分以上のユニットが死んでいることもあります。
そういったユニットを取り除いて、バックボーンだけを残します。もうちょっと考えてみましょう。
バックボーンは既に学習された部分です。言うたら、獲得された知識みたいなもんです。それは保存され、保護されるべきです。新しいことを学ぶときに、既に学んだことを解体したらあかんのです。
残念ながら、ディープラーニングはそれをしてしまうんですが、そうすべきやないんです。バックボーンを持って、それに頼って、どんどん蓄積して、もっと学んでいくべきなんです。
もうちょっと具体的に考えてみましょう。これらをReLUユニットと考えます。つまり、重み付き和があって、それに活性化関数を適用して各ユニットの値を生成するんです。
ユニットの値はxで、重みはwです。例えば、入力に重みをかけて和を取り、それに活性化関数を適用して出力を得ます。
ここでは、ネットワークを通る特定の活動の流れを示しています。1という入力が与えられて、それが伝播していきます。重み付き和を計算して、それが0より大きければその値が出力になります。
ノード内の数字はノードの出力です。数字が見えにくいかもしれませんが、後で詳しく説明します。
さて、バックボーン以外の部分をフリンジと呼びます。フリンジはより探索的で動的な部分で、バックボーンに役立つものを見つけようとします。もしバックボーンに役立つものを見つけたら、バックボーンがそれを取り入れて、フリンジの一部がバックボーンの一部になるんです。
フリンジユニットの数は、おそらくバックボーンユニットの数より多いと思います。特に始めのうちはね。ここでは2つだけ示していますが。
この例から注目してほしいのは、出力への接続です。ここでは特定の言葉を使います。このユニットについて、入力重みと出力重みについて話します。これらが入力重みで、これが出力重みです。この場合、出力重みは1つだけで3です。
フリンジユニットは、通常(必ずではありませんが)出力重みが0です。なぜなら、システムの振る舞いに影響を与えへんからです。フリンジにあるっていうことは、システムに影響を与えへんっていうことやから、バックボーンへの重みは0でなければなりません。
でも、これらの重みは学習できます。バックボーンがこの重みを大きくすることを選べば、フリンジユニットが有用な特徴を形成した場合、バックボーンの一部になれるんです。
これが一般的なアイデアです。フリンジは、バックボーンにほぼ入りかけているユニットで構成されていて、バックボーンに加わることが目標です。このようにしてバックボーンを成長させていくんです。
もうちょっと詳しく説明しましょう。これは普通の教師あり学習やから、目標値を持つことができます。ここでは、出力ノードに来る目標値が5で、実際の出力である3より大きいケースを示しています。
つまり、正の誤差があります。目標値と実際の出力の差です。これをe(t)と書きます。損失は e(t) の二乗だと考えてください。
そうすると、勾配はこんな形になります。実は「勾配」っていうのはちょっと言い方が悪くて、勾配は全ての偏微分のベクトルなんですが、慣例的にあちこちで勾配という言葉を使います。例えば、この重みの勾配はこの偏微分のことです。
ユニットの活性に関する二乗誤差の勾配についても話したいと思います。これは別のもので、「ハンガー(飢え)」と呼びたいと思います。
アイデアとしては、バックボーンは自身の構造だけで可能な限り学習していて、誤差を減らすこと、つまりハンガーを減らすことで学習しています。
でも、残差があります。つまり、リソースや信号、特徴がないために0にできないハンガーがあるんです。もちろん、すべてが0になれば完了ですが、通常はそうはなりません。
だから、新しい特徴を求めてハンガーが残るんです。これを「ハンガー」と呼ぶのは、最後のノードには正のハンガーがあるからです。目標値が出力より大きいからですね。
このノードには負のハンガーがあります。この負の重みのせいです。これを高くするために、このノードは低くなりたい、つまり活性化したくないんです。
ネットワークが人生を送る中で何が起こるか考えてみましょう。ここでは、ある瞬間のスナップショットを示しています。特定の入力と出力、その間のすべての値があって、いくつかの誤差があります。
次の時間ステップでは、別の例と別の目標値があり、異なる誤差の集合ができます。これらすべての誤差やハンガーを減らしたいんです。そのために、それらを減らすことができる特徴を提供するフリンジユニットを見つけようとしています。
ああそうそう、これらのラベルを追加しました。ノードについて質問したいときに、A から G までのノード名を参照できるようにですね。
さて、このデザインには複数の新しいアルゴリズムが必要です。バックボーン内での学習、フリンジ内での学習、バックボーンの発見、境界の維持などが必要です。これらについて簡単に話し合って、頭の中で考えてみましょう。
バックボーン内での学習は、普通のバックプロップでいけます。ステップサイズの最適化と組み合わせたいですね。バックボーンを保護したいからです。バックボーンは我々の知識やから、大きな変更は避けたいんです。ゆっくり動きたいんです。ステップサイズの最適化がそれを実現してくれます。バックボーン内でステップサイズを小さくするよう学習するんです。
フリンジ内での学習は本当にチャレンジングです。なぜフリンジ内でバックプロップが使えへんのか?バックプロップでは、誤差に関する重みの勾配に従って重みを動かします。
定義上、フリンジの重みの勾配はすべて0です。なぜなら、定義によりフリンジは出力に影響を与えへんからです。誤差に影響を与えへんので、すべての勾配が0になるんです。
だから、別のことをせなあかんのです。標準的なアルゴリズムが新しい特徴を見つけられへんのは奇妙やと思いませんか?少なくとも、ゼロからは見つけられへんのです。
バックボーンの発見についてはどうでしょう。みなさん、どないして見つけると思います?ネットワークのうち、出力に影響を与える部分と、影響を与えへん部分を区別するにはどうしたらええでしょうか?
バックボーンを見つける方法はいくつかあると思います。例えば、重みにわずかな摂動を加えて、出力に影響があるかどうかを見る方法があります。それは機能するでしょうね。
別の方法もあります。平衡状態にある場合、すべての平均勾配は0になります。上がったり下がったりして平衡に達しているからです。だから、勾配の平均は取れません。
でも、勾配が0でない場合、その重みはその時間ステップで効果があったということです。だから、勾配の二乗の平均を取れば、バックボーンが見つかると思います。
これが一番シンプルなアイデアやと思います。バックプロップに依存していますが、バックプロップは勾配を計算する方法やからね。バックプロップを行えば、どこでも勾配が得られて、それが0でないかどうかを見るだけです。
連続学習を想像してみましょう。ある期間、似たようなサンプルを見ているとします。一部の勾配は0になりますが、0でない勾配があるということは、必ずしもバックボーンにあるということではありません。
それはすべて有効な考え方です。でも、第三の方法を紹介したいと思います。
出力ユニットはバックボーンにあることは分かっています。そして、よく考えてみると、出力ユニットへの正か負の非ゼロの重みを持つ他のユニットも、バックボーンにあるはずです。
そして、閉包性があります。そのユニットがバックボーンにあるなら、それが使用する他のユニットもバックボーンにあるはずです。これは後ろに伝播していきます。
これはバックプロップとは違います。この伝播は重みの値だけに基づいていて、バックプロップは瞬間的な活性値に依存しています。
重みの値だけに依存するこの遅い後方伝播は、バックプロップができない状況でも使えるので、実装上の利点が多いです。バックプロップができない場合でも、この遅い効用の伝播はできます。これが私のおすすめする方法です。
では、先に進みましょう。次は実際にこれについて話します。効用というものについて話します。効用については以前にも聞いたことがあるでしょう。シャバンとフェルナンドが連続バックプロップで使っています。
非自明な量の効用を持つユニットをバックボーンにあると定義します。もちろん、出力ユニットはバックボーンにあります。これがバックボーンの始まりです。
そして、効用を持つ各バックボーンユニットは、その一部を、非ゼロの重みを持つ先行ユニットに渡します。これらは、そのユニットが使用する重みです。
ここで重要なのは、効用が保存されるということです。先行ユニットに効用を渡すと、その分の効用を失います。効用の総量は限られているんです。
効用が閾値を下回ると、もはやバックボーンにはありません。これが効用伝播アルゴリズムの概要です。
さて、最大の疑問点について話しましょう。フリンジ内での学習がどのように機能するかについてです。
まず言葉で説明して、それから図で説明します。定義上、フリンジの重みの勾配はすべて常に0なので、バックプロップは使えません。
その代わりに、各フリンジユニットはバックボーン上にマスターユニットを持ち、そのマスターに聞いてもらおうとします。
マスターは、フリンジユニットが仕えたい、価値を提供したい、そして効用を得たいと望むバックボーン上のユニットUです。
設計上、フリンジユニットからマスターへの重みは極めて小さくなければなりません。0か極小です。もし大きな重みがあれば、マスターを妨害することになり、バックボーンを妨害し、既に学んだことを妨害することになります。その場合、もうバックボーンにあることになってしまいます。
定義上、設計上、各フリンジユニットはバックボーンへの重みが0か極小で、そのステップサイズも小さくなります。0の重みでも大きなステップサイズがあれば、すぐに大きな重みを得て、バックボーンを妨害することになるからです。
フリンジユニットからマスターへの重みは0ですが、それでもフリンジユニットはマスターへの重みを成長させ、バックボーンに加わることを目指します。
そのために、シャドウ重みというものを持ちます。マスターへの+1か-1のシャドウ重みです。
セットアップとしては、マスターだけが実際の重みを変更できます。マスターが感じる誤差やハンガーの一部を見ているからです。
でも、もちろんフリンジユニットは自由にシャドウ重みを設定できます。
ここで、以前見た状況を思い出してください。今回はDとEの2つのユニットが追加されている点に注目してください。フリンジユニットの作成の瞬間を「インプリンティング」と呼びます。
インプリンティング時には、マスターが割り当てられます。ここでは、ユニットEのマスターはC、DのマスターはBです。
そして、シャドウ重みが割り当てられます。ここにシャドウ重みがあります。この重みは実際の重みをシャドウしています。
ユニットCのハンガーが正なので、シャドウ重みは+1に設定されます。Bのハンガーは負なので、-1のシャドウ重みになります。
あ、もう一つステップがありましたね。DとEを追加するとき、つまりインプリンティングするときに、入力接続を追加します。
入力接続の選び方はいろいろあります。ランダムに選ぶこともできますし、追加するユニットの前にあるユニット、つまりマスターの前にあるユニットから選ぶこともできます。
フィードフォワード構造を維持するために、ここではユニットDはAと入力に接続されています。Eは
BとRう力に接続されています。
フリンジユニットの重みは、作成時の入力パターンからインプリントされます。
これを理解する一番簡単な方法は、シャドウ重みを設定して、それから例を再生すると考えることです。
例を再生すると、正のハンガーがあります。もしシャドウ重みが実際の重みだったら、誤差が逆伝播して、Eは自身の重みを調整することになります。
これがインプリンティングで起こることです。ここでは正の1があります。勾配が逆伝播して、正になります。このノードの値を増やしたいので、1の入力がある場所では正の重みを、0の入力がある場所では負の重みを作ります。
このケースでは、ハンガーは負で、シャドウ重みも負です。でも、このユニットを押し下げたいわけではありません。シャドウ重みが負でも、このユニットが活性化して、Bに対して負の効果を持つことを望んでいます。
だから、正の入力に対しては重みを増やし、0の入力に対しては負の重みを作ります。
これがフリンジユニットをインプリントし、志望的にバックボーンに接続する方法です。シャドウ重みは、彼らがどのように接続されたいかという願望を表しています。
これがビジョンです。最後に、ステップサイズの最適化がこの不可欠な部分であることを思い出してください。ステップサイズを制御することで、破滅的忘却を防ぎ、より動的なフリンジからバックボーンを保護します。
フリンジユニットはシャドウ重みを作成し、マスターとの接続を持ちます。もしフリンジがバックボーンに提供するものがバックボーンにとって有用であれば、マスターへの重みのステップサイズがまず増加し、ステップサイズが無視できない大きさになると、重みが増加してバックボーンに加わることになります。
これが、より良いディープラーニングのビジョンです。一時的な学習ではなく、連続学習に最も適したものです。
これは動的なディープラーニングです。常に学習しているだけでなく、常に構造を変更しているからです。
基本的なアイデアは、バックボーンが安定していて、フリンジが動的で探索的であるということです。フリンジが成功すると、バックボーンの一部になります。シャドウ重みがそのキーとなります。
他の新しいアルゴリズムも必要で、今日はそれらを想像してみました。
明らかに、まだやるべきことはたくさんあります。省略された部分もあれば、完全に指定されていない部分もあります。
でも、少なくとも私には、特に難しそうには見えません。実際に、エージェントや強化学習により適したより良いディープラーニングを作ることができると思います。
どうもありがとうございました。


コメント