import torch import torch.nn as nn vocab_size = 4 emb_dim = 3 embeddings = nn.Embedding(vocab_size, emb_dim) print(embeddings.weight)
Parameter containing:
tensor([[ 0.2671, 1.1044, 0.4217],
[ 0.5168, 1.4011, 1.3565],
[ 2.3420, -1.9554, 0.0828],
[-1.6999, 0.3869, 1.1587]],, requires_grad=True)
x = torch.tensor([1]) score = embeddings(x) print(score)
tensor(0.5168, 1.4011, 1.3565,
grad_fn=<EmbeddingBackward>)
y = torch.sum(score)
print(y)
tensor(3.2745, grad_fn=<SumBackward0>)
y.backward()
print(embeddings.weight.grad)
tensor([[0., 0., 0.],
[1., 1., 1.],
[0., 0., 0.],
[0., 0., 0.]])
順伝播の時には $1$ の one-hot 表現 $\begin{pmatrix}0 & 1 & 0 & 0\end{pmatrix}$ に対応して
\begin{align*}
\begin{pmatrix}0 & 1 & 0 & 0\end{pmatrix} \begin{pmatrix}
0.2671 & 1.1044 & 0.4217 \\
0.5168 & 1.4011 & 1.3565 \\
2.3420 & -1.9554 & 0.0828 \\
-1.6999 & 0.3869 & 1.1587
\end{pmatrix} =
\begin{pmatrix}0.5168 & 1.4011 & 1.3565\end{pmatrix}
\end{align*}
が得られ、逆伝播ではインデックス $1$ に対応するところに値が入ってきて
\begin{align*}
\begin{pmatrix}
0 & 0 & 0 \\
1 & 1 & 1 \\
0 & 0 & 0 \\
0 & 0 & 0
\end{pmatrix}
\end{align*}
が得られていることがわかる。何で逆伝播をこう計算するのが良いのかはよく分からないけど。ゼロつく 2 本の通りなんだと思うけど、まだまだシックリとはこない。
・・・って、あぁ、そうか。ここで $x = \begin{pmatrix}0 & 1 & 0 & 0\end{pmatrix}$ は定数であって、これについて偏微分をとるのではなく、重み行列 $W = (w_{ij})$ のほうか。$f(W) = x \cdot W$ なので $\frac{\del f}{\del w_{ij}}$ で生き残るのは $i=1$ の行の成分だけになると。「Back propagation in an embedding layer」という記事が参考になった。