【第7章】Attentionクラスの計算について
kawase621 opened this issue · 4 comments
小川様
p.376でAttentionクラスの変数weightsを計算する際、単語の特徴量次元の「平方根」で割っている数学的な意味を教えてもらえないでしょうか?
この変数weightsはこの後、softmax関数に入力されますが、softmax関数は入力が大きいと微分値がゼロに近くなり、学習が上手く進まないため、単語の特徴量次元が大きいほどその内積も大きくなることを加味し、単語の特徴量次元の大きさに応じて変数weightsの大きさを調整する、というのが意図と思います。
ただ、その場合、単に「単語の特徴量次元の大きさ=今回の場合は300」で割ることでも目的を実現できるように思います。
わざわざ「平方根」にした上で割っている目的を知りたいです。
このAttentionクラスに入力される前に、LayerNormalizationクラスで各単語の持つ300要素の特徴量に対して、平均が0、標準偏差が1になるように正規化(標準化)されていると思いますが、この辺りが関係しているのでしょうか?
それとも、こういったモデルに良くある、何故かは分からないが、実装上よい結果が出た変数、という意味なのでしょうか?
お忙しいところ恐れ入りますが、回答をお願い致します。
@kawase621 さま
こちらは元論文に記載があるのですが、理論的な導出ではなく、他の論文でのやり方や、今回のやり方での経験的に、これが良いだろう(とくに特徴量の次元が大きいとき)となります。
論文:Attention is all you need. In Advances in neural information processing systems
https://arxiv.org/pdf/1706.03762.pdf
論文のp.4の「3.2.1 Scaled Dot-Product Attention」が詳細解説となります。
どうぞよろしくお願いいたします。
ご回答ありがとうございます、理解できました!
@kawase621 さん
書籍では説明を省いていた重要な内容について、ご質問たまわり、誠にありがとうございます!
ご存知とは思いますが、ご参考です。
以下コードの通り、平均0、標準偏差1で正規化した配列aとbのドット積(コードでは変数c)を計算した場合、当該変数についての平均は0、分散は300くらいになります(ご教示頂いた論文の脚注4と一致)。
この変数cを300の平方根で割る(コードでは変数d)と、分散がちょうど1くらいに戻ります。また、平均も変数cで求めた場合に比べてより0に近くなります。
数学的な検証までは出来ていませんが、平方根で除算することによる理論的な意味はこの辺りにあると思います。
import numpy as np
a = np.random.normal(loc=0,
scale = 1,
size = (256,300))
b = np.random.normal(loc=0,
scale = 1,
size = (256,300))
c=np.dot(a,b.T)
print(c.mean())
print(c.var())
d=c/np.sqrt(300)
print(d.mean())
print(d.var())