NLP中的Mask全解

©PaperWeekly 原创 · 作者|海晨威

学校|同济大学硕士生

研究方向|自然语言处理

Mask 在 NLP 中是一个很常规的操作,也有多种应用的场景和形式,下面尝试从以下几个方面去全解(用了夸张的修辞手法)Mask,并尽可能地辅以图片说明和代码解释: 

1. Mask 的作用 

  • 处理非定长序列

    • RNN 中的 Mask 

    • Attention 中 Mask 

2. 防止标签泄露 

  • Transformer 中的 Mask 

  • BERT 中的 Mask 

  • XLNet 中的 Mask

Mask的作用

对于 NLP 中 mask 的作用,先上结论: 

1. padding mask:处理非定长序列,区分 padding 和非 padding 部分,如在 RNN 等模型和 Attention 机制中的应用等;

2. sequence mask:防止标签泄露,如:Transformer decoder 中的 mask 矩阵,BERT 中的 [Mask] 位,XLNet 中的 mask 矩阵等。

PS:padding mask 和 sequence mask非官方命名。

处理非定长序列 

在 NLP 中,文本一般是不定长的,所以在进行 batch 训练之前,要先进行长度的统一,过长的句子可以通过 truncating 截断到固定的长度,过短的句子可以通过 padding 增加到固定的长度,但是 padding 对应的字符只是为了统一长度,并没有实际的价值,因此希望在之后的计算中屏蔽它们,这时候就需要 Mask。

上图(图片参考 [1])为中文场景下,一个 batch=5 的,以字为单位的输入矩阵(也可以在分词后以词为单位)和 mask 矩阵,左图已经将文本 padding 到统一长度了,右图中的 1 表示有效字,0 代表无效字。

RNN中的Mask 

对于 RNN 等模型,本身是可以直接处理不定长数据的,因此它不需要提前告知  sequence length,如下是 PyTorch 下的 LSTM 定义:

nn.LSTM(input_size, hidden_size, *args, **kwargs)

最终,R-MeN 将这 3 个编码向量反馈给基于 CNN 的解码器,返回一个三元组的得分。

但是在实践中,为了 batch 训练,一般会把不定长的序列 padding 到相同长度,再用 mask 去区分非 padding 部分和 padding 部分。 

区分的目的是使得 RNN 只作用到它实际长度的句子,而不会处理无用的 padding 部分,这样 RNN 的输出和隐状态都会是对应句子实际的最后一位。另外,对于 token 级别的任务,也可以通过 mask 去忽略 padding 部分对应的 loss。 

不过,在 PyTorch 中,对 mask 的具体实现形式不是 mask 矩阵,而是通过一个句子长度列表来实现的,但本质一样。实现如下,sentence_lens 表示的是这个 batch 中每一个句子的实际长度(参考 [2])。

embed_input_x_packed = pack_padded_sequence(embed_input_x, sentence_lens, batch_first=True)
encoder_outputs_packed, (h_last, c_last) = self.lstm(embed_input_x_packed)
encoder_outputs, _ = pad_packed_sequence(encoder_outputs_packed, batch_first=True)

btw,在 PyTorch 的 Embedding 和 Loss 中也有对 padding 值的设置:

# padding_idx (int, optional): If given, pads the output with the embedding vector at 
# `padding_idx` (initialized to zeros) whenever it encounters the index.
embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)

# ignore_index (int, optional): Specifies a target value that is ignored
# and does not contribute to the input gradient.
criterion = nn.CrossEntropyLoss(ignore_index=0)

Attention中Mask 

在 Attention 机制中,同样需要忽略 padding 部分的影响,这里以 transformer encoder 中的 self-attention 为例: 

self-attention 中,Q 和 K 在点积之后,需要先经过 mask 再进行 softmax,因此,对于要屏蔽的部分,mask 之后的输出需要为负无穷,这样 softmax 之后输出才为 0。

▲ The self-attention calculation in matrix form (图片参考 [3])

def attention(query, key, value, mask=None, dropout=None):
    "Compute 'Scaled Dot Product Attention'"
    d_k = query.size(-1)
    scores = torch.matmul(query, key.transpose(-2, -1)) \
             / math.sqrt(d_k)
    if mask is not None:
        scores = scores.masked_fill(mask == 0, -1e9) # mask步骤,用 -1e9 代表负无穷
    p_attn = F.softmax(scores, dim = -1)
    if dropout is not None:
        p_attn = dropout(p_attn)
    return torch.matmul(p_attn, value), p_attn

▲ 代码参考 [4]

PS:上述两个参考都是非常好的 transformer 介绍文章,参考 1,图片与文字相得益彰,参考 2,代码与讲解相辅相成。

防止标签泄露

在语言模型中,常常需要从上一个词预测下一个词,但如果要在 LM 中应用 self attention 或者是同时使用上下文的信息,要想不泄露要预测的标签信息,就需要 mask 来“遮盖”它。不同的 mask 方式,也对应了一篇篇的 paper,这里选取典型的几个。 

Transformer中的Mask 

Transformer 是包括 Encoder和 Decoder的,Encoder中 self-attention 的 padding mask 如上,而 Decoder 还需要防止标签泄露,即在 t 时刻不能看到 t 时刻之后的信息,因此在上述 padding mask 的基础上,还要加上 sequence mask。 

sequence mask 一般是通过生成一个上三角矩阵来实现的,上三角区域对应要 mask 的部分。 

在 Transformer 的 Decoder 中,先不考虑 padding mask,一个包括四个词的句子 [A

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值