@@ -80,8 +80,8 @@ import tensorflow as tf
8080``` {.python .input}
8181#@save
8282def masked_softmax(X, valid_lens):
83- """通过在最后一个轴上掩蔽元素来执行 softmax 操作 """
84- # `X`: 3D张量,` valid_lens`: 1D或2D 张量
83+ """通过在最后一个轴上掩蔽元素来执行softmax操作 """
84+ # X: 3D张量,valid_lens:1D或2D张量
8585 if valid_lens is None:
8686 return npx.softmax(X)
8787 else:
@@ -100,8 +100,8 @@ def masked_softmax(X, valid_lens):
100100#@tab pytorch
101101#@save
102102def masked_softmax(X, valid_lens):
103- """通过在最后一个轴上掩蔽元素来执行 softmax 操作 """
104- # `X`: 3D张量,` valid_lens`: 1D或2D 张量
103+ """通过在最后一个轴上掩蔽元素来执行softmax操作 """
104+ # X: 3D张量,valid_lens:1D或2D张量
105105 if valid_lens is None:
106106 return nn.functional.softmax(X, dim=-1)
107107 else:
@@ -120,8 +120,8 @@ def masked_softmax(X, valid_lens):
120120#@tab tensorflow
121121#@save
122122def masked_softmax(X, valid_lens):
123- """通过在最后一个轴上掩蔽元素来执行 softmax 操作 """
124- # `X`: 3D张量,` valid_lens`: 1D或2D 张量
123+ """通过在最后一个轴上掩蔽元素来执行softmax操作 """
124+ # X: 3D张量,valid_lens:1D或2D张量
125125 if valid_lens is None:
126126 return tf.nn.softmax(X, axis=-1)
127127 else:
@@ -201,7 +201,7 @@ class AdditiveAttention(nn.Block):
201201 """加性注意力"""
202202 def __init__(self, num_hiddens, dropout, **kwargs):
203203 super(AdditiveAttention, self).__init__(**kwargs)
204- # 使用 'flatten=False' 只转换最后一个轴,以便其他轴的形状保持不变
204+ # 使用'flatten=False'只转换最后一个轴,以便其他轴的形状保持不变
205205 self.W_k = nn.Dense(num_hiddens, use_bias=False, flatten=False)
206206 self.W_q = nn.Dense(num_hiddens, use_bias=False, flatten=False)
207207 self.w_v = nn.Dense(1, use_bias=False, flatten=False)
@@ -210,17 +210,17 @@ class AdditiveAttention(nn.Block):
210210 def forward(self, queries, keys, values, valid_lens):
211211 queries, keys = self.W_q(queries), self.W_k(keys)
212212 # 在维度扩展后,
213- # `queries` 的形状:(` batch_size` ,查询的个数,1,` num_hidden` )
214- # `key` 的形状:(` batch_size` ,1,“键-值”对的个数,` num_hiddens` )
213+ # queries的形状:( batch_size,查询的个数,1,num_hidden)
214+ # key的形状:( batch_size,1,“键-值”对的个数,num_hiddens)
215215 # 使用广播的方式进行求和
216216 features = np.expand_dims(queries, axis=2) + np.expand_dims(
217217 keys, axis=1)
218218 features = np.tanh(features)
219- # ` self.w_v` 仅有一个输出 ,因此从形状中移除最后那个维度。
220- # `scores` 的形状:(` batch_size` ,查询的个数,“键-值”对的个数)
219+ # self.w_v仅有一个输出 ,因此从形状中移除最后那个维度。
220+ # scores的形状:( batch_size,查询的个数,“键-值”对的个数)
221221 scores = np.squeeze(self.w_v(features), axis=-1)
222222 self.attention_weights = masked_softmax(scores, valid_lens)
223- # `values` 的形状:(` batch_size` ,“键-值”对的个数,值的维度)
223+ # values的形状:( batch_size,“键-值”对的个数,值的维度)
224224 return npx.batch_dot(self.dropout(self.attention_weights), values)
225225```
226226
@@ -239,24 +239,24 @@ class AdditiveAttention(nn.Module):
239239 def forward(self, queries, keys, values, valid_lens):
240240 queries, keys = self.W_q(queries), self.W_k(keys)
241241 # 在维度扩展后,
242- # `queries` 的形状:(` batch_size` ,查询的个数,1,` num_hidden` )
243- # `key` 的形状:(` batch_size` ,1,“键-值”对的个数,` num_hiddens` )
242+ # queries的形状:( batch_size,查询的个数,1,num_hidden)
243+ # key的形状:( batch_size,1,“键-值”对的个数,num_hiddens)
244244 # 使用广播方式进行求和
245245 features = queries.unsqueeze(2) + keys.unsqueeze(1)
246246 features = torch.tanh(features)
247- # ` self.w_v` 仅有一个输出 ,因此从形状中移除最后那个维度。
248- # `scores` 的形状:(` batch_size` ,查询的个数,“键-值”对的个数)
247+ # self.w_v仅有一个输出 ,因此从形状中移除最后那个维度。
248+ # scores的形状:( batch_size,查询的个数,“键-值”对的个数)
249249 scores = self.w_v(features).squeeze(-1)
250250 self.attention_weights = masked_softmax(scores, valid_lens)
251- # `values` 的形状:(` batch_size` ,“键-值”对的个数,值的维度)
251+ # values的形状:( batch_size,“键-值”对的个数,值的维度)
252252 return torch.bmm(self.dropout(self.attention_weights), values)
253253```
254254
255255``` {.python .input}
256256#@tab tensorflow
257257#@save
258258class AdditiveAttention(tf.keras.layers.Layer):
259- """Additive attention ."""
259+ """Additiveattention ."""
260260 def __init__(self, key_size, query_size, num_hiddens, dropout, **kwargs):
261261 super().__init__(**kwargs)
262262 self.W_k = tf.keras.layers.Dense(num_hiddens, use_bias=False)
@@ -267,17 +267,17 @@ class AdditiveAttention(tf.keras.layers.Layer):
267267 def call(self, queries, keys, values, valid_lens, **kwargs):
268268 queries, keys = self.W_q(queries), self.W_k(keys)
269269 # 在维度扩展后,
270- # `queries` 的形状:(` batch_size` ,查询的个数,1,` num_hidden` )
271- # `key` 的形状:(` batch_size` ,1,“键-值”对的个数,` num_hiddens` )
270+ # queries的形状:( batch_size,查询的个数,1,num_hidden)
271+ # key的形状:( batch_size,1,“键-值”对的个数,num_hiddens)
272272 # 使用广播方式进行求和
273273 features = tf.expand_dims(queries, axis=2) + tf.expand_dims(
274274 keys, axis=1)
275275 features = tf.nn.tanh(features)
276- # ` self.w_v` 仅有一个输出 ,因此从形状中移除最后那个维度。
277- # `scores` 的形状:(` batch_size` ,查询的个数,“键-值”对的个数)
276+ # self.w_v仅有一个输出 ,因此从形状中移除最后那个维度。
277+ # scores的形状:( batch_size,查询的个数,“键-值”对的个数)
278278 scores = tf.squeeze(self.w_v(features), axis=-1)
279279 self.attention_weights = masked_softmax(scores, valid_lens)
280- # `values` 的形状:(` batch_size` ,“键-值”对的个数,值的维度)
280+ # values的形状:( batch_size,“键-值”对的个数,值的维度)
281281 return tf.matmul(self.dropout(
282282 self.attention_weights, **kwargs), values)
283283```
@@ -289,7 +289,7 @@ class AdditiveAttention(tf.keras.layers.Layer):
289289
290290``` {.python .input}
291291queries, keys = d2l.normal(0, 1, (2, 1, 20)), d2l.ones((2, 10, 2))
292- # `values` 的小批量数据集中 ,两个值矩阵是相同的
292+ # values的小批量数据集中 ,两个值矩阵是相同的
293293values = np.arange(40).reshape(1, 10, 4).repeat(2, axis=0)
294294valid_lens = d2l.tensor([2, 6])
295295
@@ -301,7 +301,7 @@ attention(queries, keys, values, valid_lens)
301301``` {.python .input}
302302#@tab pytorch
303303queries, keys = d2l.normal(0, 1, (2, 1, 20)), d2l.ones((2, 10, 2))
304- # `values` 的小批量 ,两个值矩阵是相同的
304+ # values的小批量 ,两个值矩阵是相同的
305305values = torch.arange(40, dtype=torch.float32).reshape(1, 10, 4).repeat(
306306 2, 1, 1)
307307valid_lens = d2l.tensor([2, 6])
@@ -315,7 +315,7 @@ attention(queries, keys, values, valid_lens)
315315``` {.python .input}
316316#@tab tensorflow
317317queries, keys = tf.random.normal(shape=(2, 1, 20)), tf.ones((2, 10, 2))
318- # `values` 的小批量 ,两个值矩阵是相同的
318+ # values的小批量 ,两个值矩阵是相同的
319319values = tf.repeat(tf.reshape(
320320 tf.range(40, dtype=tf.float32), shape=(1, 10, 4)), repeats=2, axis=0)
321321valid_lens = tf.constant([2, 6])
@@ -369,13 +369,13 @@ class DotProductAttention(nn.Block):
369369 super(DotProductAttention, self).__init__(**kwargs)
370370 self.dropout = nn.Dropout(dropout)
371371
372- # `queries` 的形状:(` batch_size` ,查询的个数,`d` )
373- # `keys` 的形状:(` batch_size` ,“键-值”对的个数,`d` )
374- # `values` 的形状:(` batch_size` ,“键-值”对的个数,值的维度)
375- # `valid_lens` 的形状: (` batch_size`,) 或者 (` batch_size` ,查询的个数)
372+ # queries的形状:( batch_size,查询的个数,d )
373+ # keys的形状:( batch_size,“键-值”对的个数,d )
374+ # values的形状:( batch_size,“键-值”对的个数,值的维度)
375+ # valid_lens的形状:( batch_size,)或者( batch_size,查询的个数)
376376 def forward(self, queries, keys, values, valid_lens=None):
377377 d = queries.shape[-1]
378- # 设置 `transpose_b=True` 为了交换 `keys` 的最后两个维度
378+ # 设置transpose_b=True为了交换keys的最后两个维度
379379 scores = npx.batch_dot(queries, keys, transpose_b=True) / math.sqrt(d)
380380 self.attention_weights = masked_softmax(scores, valid_lens)
381381 return npx.batch_dot(self.dropout(self.attention_weights), values)
@@ -390,13 +390,13 @@ class DotProductAttention(nn.Module):
390390 super(DotProductAttention, self).__init__(**kwargs)
391391 self.dropout = nn.Dropout(dropout)
392392
393- # `queries` 的形状:(` batch_size` ,查询的个数,`d` )
394- # `keys` 的形状:(` batch_size` ,“键-值”对的个数,`d` )
395- # `values` 的形状:(` batch_size` ,“键-值”对的个数,值的维度)
396- # `valid_lens` 的形状: (` batch_size`,) 或者 (` batch_size` ,查询的个数)
393+ # queries的形状:( batch_size,查询的个数,d )
394+ # keys的形状:( batch_size,“键-值”对的个数,d )
395+ # values的形状:( batch_size,“键-值”对的个数,值的维度)
396+ # valid_lens的形状:( batch_size,)或者( batch_size,查询的个数)
397397 def forward(self, queries, keys, values, valid_lens=None):
398398 d = queries.shape[-1]
399- # 设置 `transpose_b=True` 为了交换 `keys` 的最后两个维度
399+ # 设置transpose_b=True为了交换keys的最后两个维度
400400 scores = torch.bmm(queries, keys.transpose(1,2)) / math.sqrt(d)
401401 self.attention_weights = masked_softmax(scores, valid_lens)
402402 return torch.bmm(self.dropout(self.attention_weights), values)
@@ -406,15 +406,15 @@ class DotProductAttention(nn.Module):
406406#@tab tensorflow
407407#@save
408408class DotProductAttention(tf.keras.layers.Layer):
409- """Scaled dot product attention ."""
409+ """Scaleddotproductattention ."""
410410 def __init__(self, dropout, **kwargs):
411411 super().__init__(**kwargs)
412412 self.dropout = tf.keras.layers.Dropout(dropout)
413413
414- # `queries` 的形状:(` batch_size` ,查询的个数,`d` )
415- # `keys` 的形状:(` batch_size` ,“键-值”对的个数,`d` )
416- # `values` 的形状:(` batch_size` ,“键-值”对的个数,值的维度)
417- # `valid_lens` 的形状: (` batch_size`,) 或者 (` batch_size` ,查询的个数)
414+ # queries的形状:( batch_size,查询的个数,d )
415+ # keys的形状:( batch_size,“键-值”对的个数,d )
416+ # values的形状:( batch_size,“键-值”对的个数,值的维度)
417+ # valid_lens的形状:( batch_size,)或者( batch_size,查询的个数)
418418 def call(self, queries, keys, values, valid_lens, **kwargs):
419419 d = queries.shape[-1]
420420 scores = tf.matmul(queries, keys, transpose_b=True)/tf.math.sqrt(
@@ -470,9 +470,9 @@ d2l.show_heatmaps(d2l.reshape(attention.attention_weights, (1, 1, 2, 10)),
4704701 . 当查询和键具有相同的矢量长度时,矢量求和作为评分函数是否比“点-积”更好?为什么?
471471
472472:begin_tab:` mxnet `
473- [ Discussions] ( https://discuss.d2l.ai/t/346 )
473+ [ Discussions] ( https://discuss.d2l.ai/t/5751 )
474474:end_tab:
475475
476476:begin_tab:` pytorch `
477- [ Discussions] ( https://discuss.d2l.ai/t/1064 )
477+ [ Discussions] ( https://discuss.d2l.ai/t/5752 )
478478:end_tab:
0 commit comments