在“Attention Is All You Need”中,作者实现了位置嵌入(添加有关单词在序列中位置的信息)。为此,他们使用正弦嵌入:
PE(pos,2i) = sin(pos/10000**(2*i/hidden_units))
PE(pos,2i+1) = cos(pos/10000**(2*i/hidden_units))
其中 pos 是位置,i 是维度。它必须产生形状为 [max_length, embedding_size] 的嵌入矩阵,即,给定序列中的位置,它返回 PE[position,:] 的张量。
我找到了
Kyubyong's实现,但我并不完全理解它。 我尝试通过以下方式在 numpy 中实现它:
hidden_units = 100 # Dimension of embedding
vocab_size = 10 # Maximum sentence length
# Matrix of [[1, ..., 99], [1, ..., 99], ...]
i = np.tile(np.expand_dims(range(hidden_units), 0), [vocab_size, 1])
# Matrix of [[1, ..., 1], [2, ..., 2], ...]
pos = np.tile(np.expand_dims(range(vocab_size), 1), [1, hidden_units])
# Apply the intermediate funcitons
pos = np.multiply(pos, 1/10000.0)
i = np.multiply(i, 2.0/hidden_units)
matrix = np.power(pos, i)
# Apply the sine function to the even colums
matrix[:, 1::2] = np.sin(matrix[:, 1::2]) # even
# Apply the cosine function to the odd columns
matrix[:, ::2] = np.cos(matrix[:, ::2]) # odd
# Plot
im = plt.imshow(matrix, cmap='hot', aspect='auto')
我不明白这个矩阵如何提供有关输入位置的信息。有人可以首先告诉我这是否是正确的计算方法,然后告诉我其背后的基本原理是什么?
谢谢你。
:
# keep dim 0 for padding token position encoding zero vector
position_enc = np.array([
[pos / np.power(10000, 2*i/d_pos_vec) for i in range(d_pos_vec)]
if pos != 0 else np.zeros(d_pos_vec) for pos in range(n_position)])
position_enc[1:, 0::2] = np.sin(position_enc[1:, 0::2]) # dim 2i
position_enc[1:, 1::2] = np.cos(position_enc[1:, 1::2]) # dim 2i+1
return torch.from_numpy(position_enc).type(torch.FloatTensor)
其中 d_pos_vec 是嵌入维度,n_position 是最大序列长度。
编辑:
在论文中,作者表示,嵌入矩阵的这种表示允许“模型推断出比训练期间遇到的序列长度更长的序列长度”。
两个位置之间的唯一区别是
pos
变量。检查下图以获得图形表示。
:我还没有读过这篇论文。我刚刚从同事那里看到这个公式,这让我开始思考 为了方便起见,在此处复制问题中的公式:
PE(pos,2i) = sin(pos/10000**(2*i/hidden_units))
PE(pos,2i+1) = cos(pos/10000**(2*i/hidden_units))
对于位置 0 (pos=0),我们交替使用 SIN(0) 和 COS(0) 作为位置嵌入,即对于位置 0,该方案仅区分位置嵌入中的奇数和偶数维度。
在查看其他职位之前: 如果观察分母项
10000**(2*i/hidden_units)
,它是从 0(i=0) 到 2(i=hidden_units) 的 10000 幂级数。考虑
i >= (hidden_units/2)
时的情况。请注意,对于这样的 i
,10,000 的幂 > 1。如果“pos 不管 pos),该方案实际上在连续维度之间没有太大区别,除非它们可能是奇数/偶数维度。<<< 10000", then the case degenerates to SIN(0) and COS(0). Thus for higher dimensions of the position embedding ( 这也让我们看到了看待位置嵌入的另一种方式。我们现在知道位置嵌入的较低维度比位置嵌入的较高维度对“pos”更敏感。 因此,可能值得看看位置嵌入的维度如何相对于不同位置而变化。
我们可以将 SIN 和 COS 函数视为 SIN(wt) 和 COS(wt),其中“pos”是“t”,
(1/d**(2*i/hidden_units))
是“w”
可以观察到,随着i
从
0
到 hidden_units
,频率从 1 下降到非常小的数字。这与我们上面的观察一致,即更高维度的嵌入对“pos”(低频波)不敏感
TL/DR现在,我们可以看到嵌入的维度是频率递减的正弦波的采样。
“pos”代表时间分量。
正弦波根据其频率平滑变化。通过使用不同频率的波,我们对不同维度的位置(不仅仅是相邻位置)的不同相似性进行编码。这允许网络从适合给定单词的任何维度中选择相似度。
SIN 和 COS 术语怎么了?我相信他们的存在是为了引起一些差异。也许,你们中的一位可以纠正我并澄清
如果 pos 接近hidden_units怎么办好吧,这些现在是模型的超参数。我认为该计划使我们能够进行实验并找出最有效的方法。也许,你们中的一个人可以更好地阐述。