
9,783 文字

大規模言語モデルに「マイケル・ジョーダンは何のスポーツをするんや」っていう文を与えて、次に来る言葉を予測させたら、正しく「バスケットボール」って答えたとしますやん。
これは、何億ものパラメーターの中に、特定の人物と特定のスポーツに関する知識が組み込まれてるってことを示唆してますな。
実際、こういうモデルで遊んだことがある人なら、膨大な量の事実を記憶してるって実感あるはずやと思います。
せやから、これがどういう仕組みで動いてるんか、そしてその事実がどこに保存されてるんかっていう疑問が出てくるんは当然やと思います。
去年の12月に、Google DeepMindの研究者何人かが、この問題に関する研究について発表しましてな。
彼らは選手とスポーツのマッチングっていう具体例を使ってたんです。
事実がどう保存されてるかっていう完全な理解はまだ解決されてへんけど、面白い部分的な結果がいくつかありました。
その中でも大きな結論として、事実はネットワークの特定の部分、ファンシーな名前で多層パーセプトロン(MLP)って呼ばれてる部分に保存されてるらしいんです。
ここ数章、私らは大規模言語モデルや他の最新のAIの基礎となってるトランスフォーマーっていうアーキテクチャの詳細を掘り下げてきました。
前回の章では、アテンションっていう部分に焦点を当てましたな。
今回は、ネットワークのもう一つの大きな部分を占めるこの多層パーセプトロンの中で何が起こってるのかを詳しく見ていきます。
ここでの計算は、アテンションと比べるとかなり単純で、本質的には2つの行列の掛け算と、その間にある簡単な何かってことになります。
ただ、これらの計算が何をしてるのかを解釈するのはめちゃくちゃ難しいんです。
今回の主な目標は、この計算過程を順を追って説明して、覚えやすくすることです。
ただ、これをする時に、このブロックの一つがどうやって具体的な事実を保存できるのかっていう具体例を示したいと思います。
特に、「マイケル・ジョーダンがバスケットボールをする」っていう事実を保存する例を見ていきます。
ちなみに、このレイアウトは、さっき言うたDeepMindの研究者の一人、ニール・ナンダさんとの会話からインスピレーションを得たもんです。
基本的には、前の2章を見たか、トランスフォーマーの基本的な理解があることを前提に話を進めますけど、おさらいは悪くないんで、全体の流れを簡単に復習しましょか。
私らが勉強してきたモデルは、テキストを入力として受け取って、次に何が来るかを予測するように訓練されてます。
まず、入力テキストはトークンって呼ばれる小さな塊に分割されます。
これらのトークンは普通、単語とか単語の一部分です。
そして、各トークンは高次元のベクトル、つまり長い数字のリストと関連付けられます。
このベクトルの列は、2種類の操作を繰り返し通過します。
一つはアテンションで、これによってベクトル同士が情報をやり取りできます。
もう一つが今日掘り下げる多層パーセプトロンです。
そして、その間には正規化のステップもあります。
このベクトルの列が、これらのブロックの多数の繰り返しを経た後、最終的には各ベクトルが、周りの言葉からの文脈と、訓練で学んだ一般的な知識の両方から十分な情報を吸収して、次にくるトークンを予測するのに使えるようになるっていうわけです。
ここで押さえておきたい重要な考え方は、これらのベクトルが非常に高次元の空間に存在してて、その空間の中の異なる方向が異なる種類の意味をエンコードできるっていうことです。
よく使われる例として、「女性」のエンベディングから「男性」のエンベディングを引いて、その差を「おじさん」みたいな男性名詞に足すと、対応する女性名詞の近くに着地するっていうのがあります。
この意味で、この特定の方向は性別の情報をエンコードしてるわけです。
アイデアとしては、この超高次元空間の他の独立した方向が、モデルが表現したい他の特徴に対応する可能性があるってことです。
トランスフォーマーでは、これらのベクトルは単に一つの単語の意味だけをエンコードするんとちゃいます。
ネットワークを通過する間に、周りの文脈やモデルの知識に基づいて、もっと豊かな意味を吸収していきます。
最終的には、各ベクトルは単一の単語の意味をはるかに超えたものをエンコードする必要があります。次に何が来るかを予測するのに十分なものでなあかんからです。
アテンションブロックがどうやって文脈を取り込むかはすでに見てきましたけど、モデルパラメータの大半は実はこのMLPブロックの中にあるんです。
そして、これらが事実を保存するための追加容量を提供してるんやないかっていう考え方があります。
さっき言うたように、今回の授業では「マイケル・ジョーダンがバスケットボールをする」っていう具体的なおもちゃの例を中心に見ていきます。
このおもちゃの例では、私らがいくつかの仮定をせなあかんのですけど。
まず、この高次元空間の一つの方向が「ファーストネームのマイケル」っていう概念を表すと仮定します。
そして、ほぼ垂直な別の方向が「ラストネームのジョーダン」っていう概念を表すと。
さらに、3つ目の方向が「バスケットボール」っていう概念を表すと仮定します。
具体的に言うと、ネットワークの中から処理中のベクトルの一つを取り出して、そのベクトルと「ファーストネームのマイケル」方向との内積が1なら、そのベクトルがその名前の人をエンコードしてるってことを意味します。
そうでない場合、その内積は0かマイナスになって、そのベクトルがその方向とあんまり整列してへんってことを示します。
簡単にするために、その内積が1より大きい場合が何を意味するかっていう、まあ合理的な疑問は完全に無視することにします。
同様に、他の方向との内積を見ることで、そのベクトルがラストネームのジョーダンやバスケットボールを表してるかどうかがわかります。
例えば、あるベクトルがフルネームの「マイケル・ジョーダン」を表すとしたら、この両方の方向との内積が1になるはずです。
「マイケル・ジョーダン」っていうテキストは2つの異なるトークンにまたがるんで、これは早い段階のアテンションブロックが、2つ目のベクトルに情報を上手く渡して、両方の名前をエンコードできるようにしたっていう仮定も必要になります。
これらを全部仮定した上で、今日の本題に入っていきましょか。
多層パーセプトロンの中で何が起こってるんでしょうか?
このベクトルの列がブロックに流れ込むっていうイメージを持ってもらえたらと思います。
覚えておいてほしいんですけど、各ベクトルは元々、入力テキストのトークンの一つと関連付けられてます。
ここで起こるのは、この列の各ベクトルが短い一連の操作を経て、最後に同じ次元の別のベクトルになるっていうことです。
これらの操作はすぐに詳しく見ていきます。
その別のベクトルが、元々流れ込んできたベクトルに足されて、その和が結果として出て行くわけです。
この一連の操作は、入力の各トークンに関連する列の各ベクトルに適用されます。
しかも、これは全部並列で起こります。
特に、このステップでは、ベクトル同士は互いにやり取りせず、みんな自分のことだけをしてるんです。
これは私らにとっては実はかなり単純にしてくれます。
だって、一つのベクトルにこのブロックで何が起こるかを理解できれば、実質的に全部のベクトルに何が起こるかを理解できるってことやからです。
このブロックが「マイケル・ジョーダンがバスケットボールをする」っていう事実をエンコードするって言うたときに意味してるのは、ファーストネームのマイケルとラストネームのジョーダンをエンコードしたベクトルが流れ込んできたら、この一連の計算がその位置のベクトルにバスケットボールの方向を含むものを足すっていうことです。
この過程の最初のステップは、そのベクトルを非常に大きな行列で掛けることです。
驚くことはありませんな、これはディープラーニングですから。
この行列は、これまで見てきた他の行列と同じように、データから学習したモデルパラメータで埋められています。
これらのパラメータは、モデルの動作を決定するためにチューニングされる、ツマミやダイヤルのようなもんやと考えてもらえたらええです。
行列の掛け算を考える良い方法の一つは、その行列の各行を独自のベクトルとして想像して、それらの行と処理中のベクトル(これをエンベディングEって呼びましょう)との内積をたくさん取るってことです。
例えば、最初の行が、私らが存在すると仮定してる「ファーストネームのマイケル」方向と等しかったとします。
そしたら、この出力の最初の成分、ここの内積は、そのベクトルがファーストネームのマイケルをエンコードしてる場合は1になって、そうでない場合は0かマイナスになります。
もっと面白いのは、その最初の行が「ファーストネームのマイケル」プラス「ラストネームのジョーダン」方向やったらどうなるかを考えることです。
簡単にするために、これをM+Jって書くことにしましょう。
そしたら、このエンベディングEとの内積を取ると、きれいに分配されて、M・E + J・Eっていう形になります。
これが意味するのは、最終的な値がフルネームの「マイケル・ジョーダン」をエンコードしてる場合は2になって、そうでない場合は1かそれより小さくなるってことです。
そして、これはこの行列の一つの行に過ぎません。
他の全ての行も、並行して他の種類の質問をしてる、つまり処理中のベクトルの他の種類の特徴を探ってるって考えられます。
このステップでは、よく出力にもう一つのベクトルを足すことがあります。
これもデータから学習したモデルパラメータで埋められています。
このもう一つのベクトルは、バイアスって呼ばれます。
私らの例では、このバイアスの最初の成分の値が-1やと想像してください。
つまり、最終的な出力は、関連する内積からマイナス1を引いたものになります。
なんでモデルがこれを学習したと仮定してほしいのか、合理的に疑問に思うかもしれません。
すぐにわかると思いますけど、ベクトルがフルネームの「マイケル・ジョーダン」をエンコードしてる場合にのみプラスになって、そうでない場合は0かマイナスになる値があると、非常にきれいで良いんです。
この行列の行の総数、つまり尋ねられる質問の数みたいなもんですけど、GPT-3の場合、これまで見てきた数字に従うと、ほぼ50,000です。
実際には、このエンベディング空間の次元数の正確に4倍です。
これは設計上の選択です。
もっと多くすることもできるし、少なくすることもできますけど、きれいな倍数にするとハードウェアにとって都合がええんです。
この重みでいっぱいの行列が、より高次元の空間に写像するんで、これを略してW上って呼ぶことにします。
処理中のベクトルはEって呼び続けます。
このバイアスベクトルをB上って呼んで、全部図に戻して書き込みましょか。
この時点で問題なのは、この操作が純粋に線形やってことです。
でも言語は非常に非線形なプロセスです。
我々が測ってる項目が「マイケル」プラス「ジョーダン」に対して高い値を示すんやったら、必然的に「マイケル」プラス「フェルプス」や「アレクシス」プラス「ジョーダン」に対しても、概念的には無関係やのに、ある程度反応してしまうんです。
本当に欲しいのは、フルネームに対する単純なイエスかノーです。
そこで次のステップとして、この大きな中間ベクトルを非常に単純な非線形関数に通します。
よく選ばれるのは、全ての負の値を0にマッピングして、正の値はそのまま残す関数です。
ディープラーニングの伝統に則って、大げさな名前を付けるんですけど、この非常に単純な関数は、整流線形ユニット、略してReLUって呼ばれることが多いです。
グラフはこんな感じです。
さっき想像した例を取ると、中間ベクトルの最初の項目が、フルネームが「マイケル・ジョーダン」の場合にのみ1で、それ以外は0かマイナスになるっていう場合、ReLUを通すと、全ての0とマイナスの値が0に切り詰められて、非常にきれいな値になります。
つまり、この出力はフルネーム「マイケル・ジョーダン」の場合は1で、それ以外は0になります。
言い換えると、ANDゲートの動作を非常に直接的に模倣してるわけです。
モデルはよく、JLUって呼ばれる少し修正された関数を使います。
これは基本的な形は同じですけど、ちょっと滑らかになってます。
でも、今回の目的では、ReLUだけを考えた方がちょっとわかりやすいんで。
また、トランスフォーマーのニューロンって言うてる人がいたら、ここの値のことを指してます。
ニューラルネットワークの一般的な図で、ドットの層があって、前の層につながる線がたくさんあるやつ、この講座の初めの方で見たやつですけど、あれは通常、この線形ステップ(行列の掛け算)と、それに続く単純な項ごとの非線形関数(ReLUみたいなもの)の組み合わせを表してるんです。
この値が正の時、このニューロンがアクティブやって言うて、値が0の時はインアクティブやって言います。
次のステップは最初のとよく似てます。
非常に大きな行列を掛けて、ある種のバイアス項を足します。
この場合、出力の次元数はそのエンベディング空間のサイズに戻るんで、これを下方投影行列って呼ぶことにします。
今回は、行ごとに考えるんじゃなくて、列ごとに考えた方が実はええんです。
行列の掛け算を頭の中で別の方法で捉えられるんですけど、それは行列の各列を取って、処理中のベクトルの対応する項を掛けて、それらの拡大縮小された列を全部足し合わせるっていう方法です。
この方法で考えた方がええ理由は、ここでは列がエンベディング空間と同じ次元を持ってるんで、それらをその空間の方向として考えられるからです。
例えば、モデルが最初の列を、我々が存在すると仮定した「バスケットボール」方向にすることを学習したと想像してみましょう。
これが意味するのは、最初の位置の関連するニューロンがアクティブな時、この列を最終結果に足すってことです。
でも、そのニューロンがインアクティブ、つまりその数が0やったら、これは何の影響も与えません。
そして、バスケットボールだけやなくて、モデルはこの列に、フルネーム「マイケル・ジョーダン」と関連付けたい他の特徴もたくさん組み込めるんです。
同時に、この行列の他の全ての列は、対応するニューロンがアクティブな場合に最終結果に何が足されるかを教えてくれます。
この場合にバイアスがあるとしたら、それはニューロンの値に関係なく、毎回足されるものです。
これが何をしてるんか不思議に思うかもしれません。
ここにあるパラメータでいっぱいのオブジェクトと同じく、正確に何をしてるかを言うのは難しいです。
ネットワークが必要とする何らかのブックキーピングかもしれませんけど、今のところは無視してもええです。
表記をもうちょっとコンパクトにするために、この大きな行列をW下って呼んで、同様にそのバイアスベクトルをB下って呼びます。
そしてこれを図に戻して書き込みましょう。
最初に予告したように、この最終結果でするのは、ブロックにその位置で流れ込んできたベクトルに足すことです。
そうすると最終結果が得られます。
例えば、流れ込んできたベクトルがファーストネームのマイケルとラストネームのジョーダンの両方をエンコードしてたとしたら、この一連の操作がそのANDゲートを発火させるんで、バスケットボールの方向を足すことになります。
結果として出てくるものは、それら全てを一緒にエンコードすることになります。
そして覚えておいてほしいんですけど、これは全てのベクトルに並列で起こってる過程なんです。
特に、GPT-3の数字を使うと、このブロックには単に5万個のニューロンがあるだけやなくて、入力のトークン数掛ける5万個のニューロンがあるってことになります。
これで操作全体の説明は終わりです。2回の行列の積、それぞれにバイアスを足して、その間に単純なクリッピング関数があるだけです。
この講座の初期の動画を見た人なら、この構造が我々がそこで勉強した最も基本的な種類のニューラルネットワークやって認識するはずです。
あの例では、手書きの数字を認識するように訓練されてました。
ここでは、大規模言語モデル用のトランスフォーマーのコンテキストで、これはより大きなアーキテクチャの一部分で、これが正確に何をしてるかを解釈しようとするなら、情報を高次元のエンベディング空間のベクトルにエンコードするっていう考え方と密接に絡み合ってます。
これが中心的な授業内容ですけど、ここで2つのことについて振り返りたいと思います。
1つ目は一種のブックキーピングで、2つ目は私がトランスフォーマーを掘り下げるまで実は知らんかった、高次元に関する非常に考えさせられる事実についてです。
前の2つの章で、私らはGPT-3の全パラメータ数を数え上げて、それらがどこにあるかを正確に見始めました。
ここでそのゲームを手短に終わらせましょう。
すでに言うたように、この上方投影行列には5万弱の行があって、各行はエンベディング空間のサイズに一致します。
GPT-3の場合、これは12,288です。
これらを掛け合わせると、その行列だけで6億400万のパラメータになります。
下方投影は転置した形で同じ数のパラメータを持ちます。
そんで、合わせると約12億のパラメータになります。
バイアスベクトルにも数パラメータありますけど、全体のごく一部なんで、ここでは示しません。
GPT-3では、このエンベディングベクトルの列が1つやなくて96個の異なるMLPを通過します。
そんで、これらのブロック全てに使われるパラメータの総数は約1160億になります。
これはネットワーク全体のパラメータの約3分の2です。
そして、これを前に数えたアテンションブロック、エンベディング、アンエンベディングの全てに足すと、確かに宣伝通りの1750億っていう総数になります。
おそらく言及する価値があるのは、この説明では省略した正規化ステップに関連する別のパラメータセットがあることです。
でも、バイアスベクトルと同じく、全体のごくわずかな割合しか占めません。
2つ目の振り返りのポイントについてですけど、私らが長い時間をかけて見てきた中心的なおもちゃの例が、実際の大規模言語モデルで事実が保存される方法を反映してるんかどうか疑問に思うかもしれません。
最初の行列の行がこのエンベディング空間の方向として考えられるってのは確かに事実です。
そして、これは各ニューロンの活性化が、与えられたベクトルが特定の方向にどれだけ整列してるかを教えてくれるってことを意味します。
また、2番目の行列の列が、そのニューロンがアクティブな場合に結果に何が足されるかを教えてくれるってのも数学的な事実です。
しかし、証拠が示唆するのは、個々のニューロンが「マイケル・ジョーダン」みたいな単一のきれいな特徴を非常にまれにしか表さへんってことです。
そして、実はこれには非常に良い理由があるかもしれません。
これは今、解釈可能性の研究者の間で浮上してる「重ね合わせ」っていうアイデアに関連してます。
これは、モデルが特に解釈しにくい理由と、驚くほどうまくスケールする理由の両方を説明するのに役立つかもしれない仮説です。
基本的なアイデアはこうです。n次元の空間があって、その空間で全て互いに垂直な方向を使って多くの異なる特徴を表現したいとします。
つまり、ある方向に成分を足しても、他の方向には影響を与えへんようにしたいわけです。
そしたら、最大で収まる方向の数は次元数nだけです。
数学者にとっては、実はこれが次元の定義なんです。
でも、面白くなるのは、この制約をちょっと緩めて、ある程度のノイズを許容した場合です。
例えば、これらの特徴を表す方向が完全に垂直やなくて、ほぼ垂直、つまり89度から91度の間くらいでええってことにしたら。
2次元や3次元やったら、これはほとんど違いを生みません。
ベクトルをもっと詰め込むための余裕はほとんどできません。
これが、高次元になると答えが劇的に変わるっていうのがますます直感に反する理由です。
これの簡単で雑な例を、ちょっとした Python のコードで示せます。
100次元のベクトルのリストを作って、各ベクトルをランダムに初期化します。
このリストには1万個の異なるベクトルを入れるんで、次元数の100倍のベクトルがあることになります。
このプロットは、これらのベクトルのペア間の角度の分布を示してます。
ランダムに始めたんで、これらの角度は0度から180度の間のどれでもありうるんですけど、すでにランダムなベクトルでも90度に近くなる強い偏りがあるのに気づくでしょう。
そして、これらのベクトルを少しずつ動かして、お互いにもっと垂直に近づけようとする最適化プロセスを繰り返し実行します。
これを何度も繰り返した後の角度の分布がこれです。
実際、ここで拡大せなあかんほどです。
ベクトルのペア間のあり得る角度が全て89度から91度の間のこの狭い範囲に収まってるからです。
一般に、ジョンソン・リンデンストラウスの補題として知られるものの結果として、このようにほぼ垂直に詰め込めるベクトルの数は、次元数に対して指数関数的に増加します。
これは大規模言語モデルにとって非常に重要です。
独立した考えをほぼ垂直な方向と関連付けることで恩恵を受ける可能性があるからです。
これは、割り当てられた空間の次元よりもはるかに多くのアイデアを保存できる可能性があるってことを意味します。
これは、モデルのパフォーマンスがサイズに応じてうまくスケールするように見える理由の一部を説明してるかもしれません。
10倍の次元数を持つ空間は、10倍以上の独立したアイデアを保存できるんです。
これは、モデルを流れるベクトルが存在するエンベディング空間だけやなく、我々が今勉強した多層パーセプトロンの真ん中にあるニューロンでいっぱいのベクトルにも関係してきます。
つまり、GPT-3のサイズやったら、単に5万個の特徴を探るだけやなくて、代わりにこの空間のほぼ垂直な方向を使うことで得られる膨大な追加容量を活用すれば、処理中のベクトルの遥かに多くの特徴を探ることができるかもしれません。
でも、もしそうしてたら、個々の特徴が単一のニューロンが点灯するっていう形では見えへんってことになります。
代わりに、ニューロンの特定の組み合わせ、重ね合わせとして見えるはずです。
これについてもっと知りたい人のために、関連する重要な検索用語は「スパース自己符号化器」です。
これは、解釈可能性の研究者たちが、これらのニューロンに非常に重ね合わされてても、真の特徴を抽出しようとするのに使うツールです。
これに関する素晴らしいAnthropicの投稿へのリンクを貼っておきます。
この時点で、トランスフォーマーの全ての詳細には触れてませんけど、私らは最も重要なポイントは押さえました。
次の章で取り上げたい主なことは、訓練プロセスです。
一方で、訓練がどう機能するかの短い答えは、全部バックプロパゲーションやってことです。
バックプロパゲーションについては、この講座の前の章で別のコンテキストで取り上げました。
でも、もっと議論することがあります。
例えば、言語モデルに使われる特定のコスト関数とか、人間のフィードバックを使った強化学習による微調整のアイデアとか、スケーリング則の概念なんかです。
活発に追跡してくれてる皆さんへの注意ですけど、次の章を作る前に、機械学習に関係のない動画をいくつか作りたいと思ってるんで、少し時間がかかるかもしれません。
でもいずれ必ず作るって約束します。
ありがとうございました。


コメント