@@ -80,8 +80,8 @@ import tensorflow as tf
80
80
``` {.python .input}
81
81
#@save
82
82
def masked_softmax(X, valid_lens):
83
- """通过在最后一个轴上掩蔽元素来执行 softmax 操作 """
84
- # `X`: 3D张量,` valid_lens`: 1D或2D 张量
83
+ """通过在最后一个轴上掩蔽元素来执行softmax操作 """
84
+ # X: 3D张量,valid_lens:1D或2D张量
85
85
if valid_lens is None:
86
86
return npx.softmax(X)
87
87
else:
@@ -100,8 +100,8 @@ def masked_softmax(X, valid_lens):
100
100
#@tab pytorch
101
101
#@save
102
102
def masked_softmax(X, valid_lens):
103
- """通过在最后一个轴上掩蔽元素来执行 softmax 操作 """
104
- # `X`: 3D张量,` valid_lens`: 1D或2D 张量
103
+ """通过在最后一个轴上掩蔽元素来执行softmax操作 """
104
+ # X: 3D张量,valid_lens:1D或2D张量
105
105
if valid_lens is None:
106
106
return nn.functional.softmax(X, dim=-1)
107
107
else:
@@ -120,8 +120,8 @@ def masked_softmax(X, valid_lens):
120
120
#@tab tensorflow
121
121
#@save
122
122
def masked_softmax(X, valid_lens):
123
- """通过在最后一个轴上掩蔽元素来执行 softmax 操作 """
124
- # `X`: 3D张量,` valid_lens`: 1D或2D 张量
123
+ """通过在最后一个轴上掩蔽元素来执行softmax操作 """
124
+ # X: 3D张量,valid_lens:1D或2D张量
125
125
if valid_lens is None:
126
126
return tf.nn.softmax(X, axis=-1)
127
127
else:
@@ -201,7 +201,7 @@ class AdditiveAttention(nn.Block):
201
201
"""加性注意力"""
202
202
def __init__(self, num_hiddens, dropout, **kwargs):
203
203
super(AdditiveAttention, self).__init__(**kwargs)
204
- # 使用 'flatten=False' 只转换最后一个轴,以便其他轴的形状保持不变
204
+ # 使用'flatten=False'只转换最后一个轴,以便其他轴的形状保持不变
205
205
self.W_k = nn.Dense(num_hiddens, use_bias=False, flatten=False)
206
206
self.W_q = nn.Dense(num_hiddens, use_bias=False, flatten=False)
207
207
self.w_v = nn.Dense(1, use_bias=False, flatten=False)
@@ -210,17 +210,17 @@ class AdditiveAttention(nn.Block):
210
210
def forward(self, queries, keys, values, valid_lens):
211
211
queries, keys = self.W_q(queries), self.W_k(keys)
212
212
# 在维度扩展后,
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)
215
215
# 使用广播的方式进行求和
216
216
features = np.expand_dims(queries, axis=2) + np.expand_dims(
217
217
keys, axis=1)
218
218
features = np.tanh(features)
219
- # ` self.w_v` 仅有一个输出 ,因此从形状中移除最后那个维度。
220
- # `scores` 的形状:(` batch_size` ,查询的个数,“键-值”对的个数)
219
+ # self.w_v仅有一个输出 ,因此从形状中移除最后那个维度。
220
+ # scores的形状:( batch_size,查询的个数,“键-值”对的个数)
221
221
scores = np.squeeze(self.w_v(features), axis=-1)
222
222
self.attention_weights = masked_softmax(scores, valid_lens)
223
- # `values` 的形状:(` batch_size` ,“键-值”对的个数,值的维度)
223
+ # values的形状:( batch_size,“键-值”对的个数,值的维度)
224
224
return npx.batch_dot(self.dropout(self.attention_weights), values)
225
225
```
226
226
@@ -239,24 +239,24 @@ class AdditiveAttention(nn.Module):
239
239
def forward(self, queries, keys, values, valid_lens):
240
240
queries, keys = self.W_q(queries), self.W_k(keys)
241
241
# 在维度扩展后,
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)
244
244
# 使用广播方式进行求和
245
245
features = queries.unsqueeze(2) + keys.unsqueeze(1)
246
246
features = torch.tanh(features)
247
- # ` self.w_v` 仅有一个输出 ,因此从形状中移除最后那个维度。
248
- # `scores` 的形状:(` batch_size` ,查询的个数,“键-值”对的个数)
247
+ # self.w_v仅有一个输出 ,因此从形状中移除最后那个维度。
248
+ # scores的形状:( batch_size,查询的个数,“键-值”对的个数)
249
249
scores = self.w_v(features).squeeze(-1)
250
250
self.attention_weights = masked_softmax(scores, valid_lens)
251
- # `values` 的形状:(` batch_size` ,“键-值”对的个数,值的维度)
251
+ # values的形状:( batch_size,“键-值”对的个数,值的维度)
252
252
return torch.bmm(self.dropout(self.attention_weights), values)
253
253
```
254
254
255
255
``` {.python .input}
256
256
#@tab tensorflow
257
257
#@save
258
258
class AdditiveAttention(tf.keras.layers.Layer):
259
- """Additive attention ."""
259
+ """Additiveattention ."""
260
260
def __init__(self, key_size, query_size, num_hiddens, dropout, **kwargs):
261
261
super().__init__(**kwargs)
262
262
self.W_k = tf.keras.layers.Dense(num_hiddens, use_bias=False)
@@ -267,17 +267,17 @@ class AdditiveAttention(tf.keras.layers.Layer):
267
267
def call(self, queries, keys, values, valid_lens, **kwargs):
268
268
queries, keys = self.W_q(queries), self.W_k(keys)
269
269
# 在维度扩展后,
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)
272
272
# 使用广播方式进行求和
273
273
features = tf.expand_dims(queries, axis=2) + tf.expand_dims(
274
274
keys, axis=1)
275
275
features = tf.nn.tanh(features)
276
- # ` self.w_v` 仅有一个输出 ,因此从形状中移除最后那个维度。
277
- # `scores` 的形状:(` batch_size` ,查询的个数,“键-值”对的个数)
276
+ # self.w_v仅有一个输出 ,因此从形状中移除最后那个维度。
277
+ # scores的形状:( batch_size,查询的个数,“键-值”对的个数)
278
278
scores = tf.squeeze(self.w_v(features), axis=-1)
279
279
self.attention_weights = masked_softmax(scores, valid_lens)
280
- # `values` 的形状:(` batch_size` ,“键-值”对的个数,值的维度)
280
+ # values的形状:( batch_size,“键-值”对的个数,值的维度)
281
281
return tf.matmul(self.dropout(
282
282
self.attention_weights, **kwargs), values)
283
283
```
@@ -289,7 +289,7 @@ class AdditiveAttention(tf.keras.layers.Layer):
289
289
290
290
``` {.python .input}
291
291
queries, keys = d2l.normal(0, 1, (2, 1, 20)), d2l.ones((2, 10, 2))
292
- # `values` 的小批量数据集中 ,两个值矩阵是相同的
292
+ # values的小批量数据集中 ,两个值矩阵是相同的
293
293
values = np.arange(40).reshape(1, 10, 4).repeat(2, axis=0)
294
294
valid_lens = d2l.tensor([2, 6])
295
295
@@ -301,7 +301,7 @@ attention(queries, keys, values, valid_lens)
301
301
``` {.python .input}
302
302
#@tab pytorch
303
303
queries, keys = d2l.normal(0, 1, (2, 1, 20)), d2l.ones((2, 10, 2))
304
- # `values` 的小批量 ,两个值矩阵是相同的
304
+ # values的小批量 ,两个值矩阵是相同的
305
305
values = torch.arange(40, dtype=torch.float32).reshape(1, 10, 4).repeat(
306
306
2, 1, 1)
307
307
valid_lens = d2l.tensor([2, 6])
@@ -315,7 +315,7 @@ attention(queries, keys, values, valid_lens)
315
315
``` {.python .input}
316
316
#@tab tensorflow
317
317
queries, keys = tf.random.normal(shape=(2, 1, 20)), tf.ones((2, 10, 2))
318
- # `values` 的小批量 ,两个值矩阵是相同的
318
+ # values的小批量 ,两个值矩阵是相同的
319
319
values = tf.repeat(tf.reshape(
320
320
tf.range(40, dtype=tf.float32), shape=(1, 10, 4)), repeats=2, axis=0)
321
321
valid_lens = tf.constant([2, 6])
@@ -369,13 +369,13 @@ class DotProductAttention(nn.Block):
369
369
super(DotProductAttention, self).__init__(**kwargs)
370
370
self.dropout = nn.Dropout(dropout)
371
371
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,查询的个数)
376
376
def forward(self, queries, keys, values, valid_lens=None):
377
377
d = queries.shape[-1]
378
- # 设置 `transpose_b=True` 为了交换 `keys` 的最后两个维度
378
+ # 设置transpose_b=True为了交换keys的最后两个维度
379
379
scores = npx.batch_dot(queries, keys, transpose_b=True) / math.sqrt(d)
380
380
self.attention_weights = masked_softmax(scores, valid_lens)
381
381
return npx.batch_dot(self.dropout(self.attention_weights), values)
@@ -390,13 +390,13 @@ class DotProductAttention(nn.Module):
390
390
super(DotProductAttention, self).__init__(**kwargs)
391
391
self.dropout = nn.Dropout(dropout)
392
392
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,查询的个数)
397
397
def forward(self, queries, keys, values, valid_lens=None):
398
398
d = queries.shape[-1]
399
- # 设置 `transpose_b=True` 为了交换 `keys` 的最后两个维度
399
+ # 设置transpose_b=True为了交换keys的最后两个维度
400
400
scores = torch.bmm(queries, keys.transpose(1,2)) / math.sqrt(d)
401
401
self.attention_weights = masked_softmax(scores, valid_lens)
402
402
return torch.bmm(self.dropout(self.attention_weights), values)
@@ -406,15 +406,15 @@ class DotProductAttention(nn.Module):
406
406
#@tab tensorflow
407
407
#@save
408
408
class DotProductAttention(tf.keras.layers.Layer):
409
- """Scaled dot product attention ."""
409
+ """Scaleddotproductattention ."""
410
410
def __init__(self, dropout, **kwargs):
411
411
super().__init__(**kwargs)
412
412
self.dropout = tf.keras.layers.Dropout(dropout)
413
413
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,查询的个数)
418
418
def call(self, queries, keys, values, valid_lens, **kwargs):
419
419
d = queries.shape[-1]
420
420
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)),
470
470
1 . 当查询和键具有相同的矢量长度时,矢量求和作为评分函数是否比“点-积”更好?为什么?
471
471
472
472
:begin_tab:` mxnet `
473
- [ Discussions] ( https://discuss.d2l.ai/t/346 )
473
+ [ Discussions] ( https://discuss.d2l.ai/t/5751 )
474
474
:end_tab:
475
475
476
476
:begin_tab:` pytorch `
477
- [ Discussions] ( https://discuss.d2l.ai/t/1064 )
477
+ [ Discussions] ( https://discuss.d2l.ai/t/5752 )
478
478
:end_tab:
0 commit comments