Mask矩阵在深度学习中的应用

定义

mask矩阵是一个由0和1组成的矩阵。在NLP中,一个常见的问题是输入序列长度不等,而mask可以帮助我们处理。虽然RNN等模型可以处理不定长的输入,但是在实践中,需要对输入中长度较短的句子进行填充,即在句尾填充0占位,转换成固定大小的tensor,方便矩阵操作。

举个例子:

1
2
case 1: I like cats.
case 2: He does not like cats.

假设默认的序列长度是5,一般会对case 1做pad处理,变成

1
I like cats <PAD> <PAD>

在上述例子数字编码后,开始做embedding,而pad也会有embedding向量,但pad本身没有实际意义,参与训练可能还是有害的。因此,有必要维护一个mask tensor来记录哪些是真实的value,上述例子的两个mask如下:

1
2
1 1 1 0 0
1 1 1 1 1

后续再梯度传播中,mask起到了过滤的作用。

使用TensorFlow实现上述过程:

1
2
3
4
5
6
7
8
import tensorflow as tf
maxlen = 5
lengths = [[3, 5, 4], [1, 3, 2]]
mask = tf.cast(tf.sequence_mask(lengths, maxlen), tf.float32)
sess = tf.Session()
mask = sess.run(mask)
print(mask)

运行结果:

1
2
3
4
5
6
7
[[[1. 1. 1. 0. 0.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 0.]]
[[1. 0. 0. 0. 0.]
[1. 1. 1. 0. 0.]
[1. 1. 0. 0. 0.]]]

作用

  1. 使用mask矩阵是为了让那些被mask掉的tensor不会被更新。一个tensor T和同样大小的mask矩阵M相乘在梯度回传的时候,T对应mask为0的地方梯度为0。因此权重不会被更新。

  2. 语言模型中可以防止未来信息泄露

    在语言模型中,常常需要从上一个词预测下一个词,而现阶段attention是标配,比如Transformer中的self attention,如果不做mask,在decoder的时候很容易把下一个词的信息泄露了,即按上诉例子,不能在预测like这个词时已经知道like后面的词了。使用mask矩阵可以很好的解决这一问题。

TensorFlow生成mask对角矩阵:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import tensorflow as tf
import matplotlib.pyplot as plt
def subsequent_mask(size):
"Mask out subsequent positions."
attn_mask = tf.ones([size, size])
mask = tf.matrix_band_part(attn_mask, -1, 0)
return mask
sess = tf.Session()
mask = sess.run(subsequent_mask(10))
print(mask)
# Display matrix
plt.matshow(mask)
plt.show()

运行结果:

1
2
3
4
5
6
7
8
9
10
[[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[1. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 0. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 0. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 1. 0. 0. 0.]
[1. 1. 1. 1. 1. 1. 1. 1. 0. 0.]
[1. 1. 1. 1. 1. 1. 1. 1. 1. 0.]
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]]

参考

[1]: Mask矩阵在深度学习中有哪些应用场景?

[2]: 浅谈mask矩阵

显示 Gitment 评论