2021SC@SDUSC
embedding层中BERT模型的输入表示是token embedding、segmentation embedding、position embedding的总和。分别的意义是:token符号、segmentation分割、position位置和顺序。
token embedding是将各个词转换成了一定维度上的向量。BERT通常固定维度为768。
segment embedding分割编码,是用来区分上下句子,表示当前词在句子中的位置。
position embedding位置编码(PE),是给模型传递字符输入顺序的信息,给每个单词添加其在句子中的位置的信息,也就是位置信息编码。
简单来说,embedding对句子的处理就是先将一个句子每个单词和字符符号都转化为 向量 ,也就是token embedding,再将这样之后会出现一些分句,为了将它们区分,就给每个分句加上它们的特有分割编码,也就是segment embedding,最后再给每个字符加上特有的位置编码,也就是position embedding,以便分辨或确认他们的顺序和位置。
__init__()定义了三个编码信息。
将三者求和就是模型的输入。
def forward()定义了前向传播时经过embedding层的流程,就是根据句段文本建立矩阵,再分别将得到的token embedding、position embedding、segmention embedding进行求和作为模型输入传递给下一层。
接下来的是MultHeadedSelfAttention层
class MultiHeadedSelfAttention(nn.Module):
""" Multi-Headed Dot Product Attention """
def __init__(self, cfg):
super().__init__()
self.proj_q = nn.Linear(cfg.dim, cfg.dim)
self.proj_k = nn.Linear(cfg.dim, cfg.dim)
self.proj_v = nn.Linear(cfg.dim, cfg.dim)
self.drop = nn.Dropout(cfg.p_drop_attn)
self.scores = None # for visualization
self.n_heads = cfg.n_heads
def forward(self, x, mask):
"""
x, q(query), k(key), v(value) : (B(batch_size), S(seq_len), D(dim))
mask : (B(batch_size) x S(seq_len))
* split D(dim) into (H(n_heads), W(width of head)) ; D = H * W
"""
# (B, S, D) -proj-> (B, S, D) -split-> (B, S, H, W) -trans-> (B, H, S, W)
q, k, v = self.proj_q(x), self.proj_k(x), self.proj_v(x)
q, k, v = (split_last(x, (self.n_heads, -1)).transpose(1, 2)
for x in [q, k, v])
# (B, H, S, W) @ (B, H, W, S) -> (B, H, S, S) -softmax-> (B, H, S, S)
scores = q @ k.transpose(-2, -1) / np.sqrt(k.size(-1))
if mask is not None:
mask = mask[:, None, None, :].float()
scores -= 10000.0 * (1.0 - mask)
scores = self.drop(F.softmax(scores, dim=-1))
# (B, H, S, S) @ (B, H, S, W) -> (B, H, S, W) -trans-> (B, S, H, W)
h = (scores @ v).transpose(1, 2).contiguous()
# -merge-> (B, S, D)
h = merge_last(h, 2)
self.scores = scores
return h
MultHeadedSelfAttention 多头注意力机制
__init__()中用nn.Linear()分别定义了q/k/v接入全连接层的输入和输出的维度,q/k/v之前我们前置知识的时候讲过,分别是输入向量的Query、Key、Value。nn.Dropout(p)是常用的防止过拟合的技术,防止或减轻过拟合,同时可以提升模型鲁棒性。里面有个概率p,p是使某个神经元激活值不参与或置为0的概率。heads是层数,在BERT模型里面一般是12层。
forward()定义了前向传播中Multi-Head Attention层的运行流程这和我们之前讲过的self-attention类似,不过使升级版。也就是将 Scaled Dot-Product Attention的过程执行heads次最后合并起来。
关于selfattention的计算过程前面有讲到,不过多赘述。
多头注意力机制的公式如下: