YutaroOgawa / pytorch_advanced

書籍「つくりながら学ぶ! PyTorchによる発展ディープラーニング」の実装コードを配置したリポジトリです
MIT License
844 stars 334 forks source link

【第7章】Attentionにおけるmaskの実装について #175

Open kawase621 opened 3 years ago

kawase621 commented 3 years ago

Attentionにおけるmaskの実装について質問させて下さい。 Maskの目的は、Self-Attentionの変数「weights」を求める際に、特定の単語に対して「pad」との関連度を反映させない係数にすること、と理解しています。 仮に、簡単な例で5単語(末尾に「pad」を2つ含む)からなる文章からweightsを計算する場合、下表のように関連度を計算することになると思います。

スクリーンショット 2021-07-23 11 36 49

このweightsに対してP.376の実装でmaskを掛けた場合、赤字の部分は「-1e9」に置き換わりますが、「?」で表現した部分は置き換わらない(何らかの数字が残る)ように思います。 これは問題ないのでしょうか? 変数weightsを行単位で捉えた場合、各要素は特定の単語と他の単語の関連度を示していると思います。 空欄を示す「pad」と他の単語との関連度が残っていることに違和感を覚えたので質問させてもらいました。

YutaroOgawa commented 3 years ago

@kawase621 さま

ご質問をいただき、誠にありがとうございます。

まず、質問いただいた内容の通りであると思います。

申し訳ございません。私の理解の限界があります。 以下私なりに考えた内容です。


上記 ?の部分も -1E+0.9 にすると、その後のsoftmaxを行方向に与えた場合に、 犬行や猫行、鳥行は列は0になります。

一方で行は全部の要素が -1E+0.9 になるため、softmax後の行要素は上記の図の場合、 全部の列で1/5の値となります。

すなわち、softmax以前で何かしても、pad行の要素が0になることはありません。

このTransformerの章の参考文献だけでなく、BERTの場合も、mask処理はsoftmaxの前に実施しています。

よって、おそらく現在の書籍のままで、列方向でpadは考慮されているので良いのだと思います。

が、なんだか気持ち悪いのですが、そしてこれで良いのだと、論理的にうまく説明できないのですが、 どうぞよろしくお願い致します

kawase621 commented 3 years ago

お忙しい中、ご回答頂きありがとうございます。 ご回答の中の以下部分ですが、weightsのpad行の要素を全て-1E+0.9にした場合(すなわち、表の「?」部分も-1E+0.9にした場合)、これに対してsoftmaxを適用するとpad行は全て0になりませんか?5分の1になる理由を教えて頂けると助かります。 的外れな質問となっていれば申し訳ありません。

一方で行は全部の要素が -1E+0.9 になるため、softmax後の行要素は上記の図の場合、全部の列で1/5の値となります。 すなわち、softmax以前で何かしても、pad行の要素が0になることはありません。

kawase621 commented 3 years ago

しばらく悩んでみましたが、小川様の実装で問題ないように思います。以下の通り考えてみたので、認識の誤り等あればご指摘頂けると助かります。

・この次の段階で、softmax関数によって行単位で正規化し、weightsとvの掛け算を行う。  ・例えば、outputの「犬」行は、weightsの「犬」行をvの列方向(=つまり特徴量変換された各単語の分散表現の0次元目〜300次元目)に対して乗算していった結果となる。よって、weightsの「犬」行について「pad」との関連度を示す列部分が0になっていると、「犬」を考えるにあたって「pad」は考慮に入らなくなるので、正しい。 ・その一方で、outputの「pad」行を考えると、weightsの「pad」行をvの列方向(=つまり特徴量変換された各単語の分散表現の0次元目~300次元目)に対して乗算していくことになるが、上表の「?」部分に値が残っていた場合、「pad」を考えるにあたって、「犬」や「猫」や「鳥」は考慮するが「pad」は考慮しなかった、という意味になり、違和感を感じる(今回の私の疑問)。 ・1回目のAttentionを通過した後に、outputの「pad」行に何らかの数字が残ったとする。このoutputは次のAttentionでも使われる。すなわち、特徴量変換された後に、また同じように各要素の類似度が計算(=qと転置したkのドット積)される。これによって新しく作られるweightsの行要素、例えば「犬」と他の単語の類似度を計算する場合について考える。1列目は「犬」自身との類似度、2列目は「猫」との類似度、、、と進み、「pad」との類似度も計算される。この「pad」には何らかの値が残っているはずで、「犬」ベクトルとのドット積で特定の数字が算出されるが、これは実装上、maskによって消される。すなわち、outputの「pad」行に値が残っていて、特定の単語との類似度が計算されてしまったとしても、weightsを作成する際にはmaskで消されるので問題ない。

YutaroOgawa commented 3 years ago

@kawase621 さま

早速の返信ならびに、推考を誠にありがとうございます。 私も勉強になります。

softmaxを適用するとpad行は全て0になりませんか?5分の1になる理由を教えて頂けると助かります。

softmaxの適用で、まず要素に対してsigmoid関数が計算され、1E-9のような要素は”ほぼ0”になります。

pad行はsigmoidで全要素、"ほぼ0"になるのですが、softmaxでは規格化が入るので、全要素の和が1になるようになります。 よって、全要素”ほぼ0”を全部足して1になるように規格化されるので、5列ある今、”ほぼ0”の要素は1/5になる。

と私は考えました。


すなわち、outputの「pad」行に値が残っていて、特定の単語との類似度が計算されてしまったとしても、weightsを作成する際にはmaskで消されるので問題ない。

はい、2回目以降のAttention層(Transformer層)でもmaskは作用するので、outputにpad列の要素が残っていても、maskで消える、この点私も同意です。

一方で、pad行に要素が残るのですが、「もうTransformerはこんなものなのかな~。pad列のmaskで完全に考慮されたことになるのかなあ?」と思っています(私の違和感が拭えないところではあります)。。。

ただ、pad行も0になると、そもそもweight行列がランク落ちして、計算が不安定になりそう感もあります。

非常に重要なご質問を誠にありがとうございます。

適切にバシッと回答できず大変申し訳ございませんが、返答いただいて感じた内容を上記記載いたしました。

kawase621 commented 3 years ago

小川様

ご回答ありがとうございます。

仰る通り、softmaxで正規化することを考えると、結局のところ0にはならないのですね。

そう考えると、むしろ表で「?」にしたところを-1E+0.9に置き換えてしまった場合、weightsにおけるpad行pad列の値は0から離れてしまう様に思います。

今回の実装上、weightsにおいて、計算に影響を与えるのはpad行で言うとpad列の要素のみと思います。逆に言うと表で「?」にしたところは何らかの計算自体は行われるものの、その後の動きに影響を与えることはない要素と思います。

これらを勘案すると、weightsのpad行において、出来る限りpad列を0に近付けるために、以降の計算上関係ない要素である「?」の部分は敢えて値を残しておく、と考えると整合的と思うのですが、如何でしょうか?

kawase621 commented 3 years ago

先程の私のコメントですが、よくよく考えてみると、weightsのpad行は、pad列も含めてそもそも使わない(計算はされるが、後々その結果が使用される部分はmaskされる)ので、pad行のpad列を出来る限り0に近付ける必要もないですね…。すみません。

YutaroOgawa commented 3 years ago

@kawase621 さま

今回も興味深く、重要な質問をいただき、ありがとうございます。

はい、最後にコメントいただいた通りです。 なんだかモヤモヤが残る回答しかできず、誠に申し訳ございません。

私も今後、理解に進展がありましたら、追記いたします。

学びが深まる、重要な質問をありがとうございます!

kawase621 commented 3 years ago

とんでもございません、お忙しい中ご対応頂きありがとうございました!