【Attention篇】:CNN-RNN-LSTM-GRU-【Encoder-Decoder模式】-Attention-【Self-Attention】-Transformer-GPT-BERT
-
【CNN】:卷积依靠卷积网络的深度来捕捉长距离依赖,太多层卷积的堆叠则有可能导致信息的丢失
-
【RNN】:Y=f(wX+b),加入隐状态H(H可以①提取特征②转换为输出),则
编码:H1=f(uH0+wX1+b),H2=f(uH1+wX2+b),……。
解码:Y1=softmax(vH1+c)。
符合类似结构的都可以称为encoder-decoder模型。
【RNN局限】:若句子较长,RNN不断用前一个状态计算后一个状态,会导致【RNN只有短期记忆,会忘记长序列中前面的内容】。 -
【LSTM(Long Short Term Memory,长短期记忆)】:设有 遗忘门、输入门、输出门,用于决定 记住谁、忘记谁,初步具备【注意力】
-
【GRU(gate recurrent unit门控循环单元)】:LSTM的优化,遗忘门+输入门=>更新门
-
【Encoder-Decoder模式】:上述RNN\LSTM\GRU都可以称为Encoder-Decoder模型,都符合先编码(压缩特征)、后解码(转换为输出)的pattern
【Encoder-Decoder局限】:只用一个【向量c】来传递信息,且长度固定。 -
【Attention】:
h_j:【上下文句子context】中第j个单词的语义编码,【文章-上下文句子context】编码器状态 H:(h1,h2,h3,…,hn)
x_i:【问题】中第i个单词的语义编码【提出问题的句子】解码器状态 X:(x1,x2,x3,…,xn)
Q_i:Q_i = W_q * x_i
K_j:K_j = W_k * h_j
V_j:V_j = W_v * h_j(与k同源)
f(q,k):f(q,k)=W3* tanh(Wq* x_i + Wk* h_j )= Q_i^T K_j / √d_k=f(Q_i,K_j) ,通过除以√d_k,将方差重新缩放回1,防止softmax梯度消失
a_ij:a_ij = softmax(f(x_i, h_j))=softmax( f(Q_i,K_j) ),【输出】第i个单词时,【上下文句子context】中第j个单词的【注意力权重】
c_i: c_i = a_i1 * h1 + a_i2 * h2 + a_i3 * h3 + … = Σa_ij*h_j (j∈[1, 上下文句子context的长度])=softmax( f(Q_i,K_j) )*V_j,【输出/解码】第i个单词时所需的【编码向量c_i】
Attention(Q,K,V) = Σc_i = softmax(QK^T/√d_k)V
①不再是【一个向量c(enc->[c]->dec)】,而是用【若干个向量c_i(enc->[c1,c2,c3,…,cn]->dec)】传递信息
②最重要的是c_i【加权求和】的过程
③生成句子的过程:y1=f1(c1),y2=f1(c2,y1),y3=f1(c3,y1,y2) -
【自注意力机制Self-Attention】:
Self-Attention与Attention的区别:QKV都是相同的序列。
输入序列: X = {x_1,…,x_n},
Q_i = W_q * x_i
K_i = W_k * x_i
V_i = W_v * x_i
```其余推导与上述【Attention】相同
在 Encoder 的输出中,每个 token 的表示是 【自身与其它所有 token 表示的加权和】,权重由自注意力机制计算得出,类似一种【对自己的全连接】。
捕捉token之间的长距离依赖关系,一次多义调整表示,生成更高质量的上下文表示。 -
【Self-Attention 计算实例】:
假设输入序列为:[“The”, “cat”, “ate”, “the”, “fish”]。
每个 token 的初始表示(词嵌入 + 位置编码):
“The”:[0.1, 0.2, 0.3]
“cat”:[0.4, 0.5, 0.6]
“ate”:[0.7, 0.8, 0.9]
“the”:[1.0, 1.1, 1.2]
“fish”:[1.3, 1.4, 1.5]
“cat” 的表示是 “The”、“cat”、“ate”、“the”、“fish” 的加权和,权重分别为 [0.1, 0.6, 0.2, 0.05, 0.05]。权重越高越相关。
“ate” 的表示是 “The”、“cat”、“ate”、“the”、“fish” 的加权和,权重分别为 [0.05, 0.2, 0.5, 0.1, 0.15]。
“cat” 的输出表示:0.1⋅[0.1,0.2,0.3]+0.6⋅[0.4,0.5,0.6]+0.2⋅[0.7,0.8,0.9]+0.05⋅[1.0,1.1,1.2]+0.05⋅[1.3,1.4,1.5],计算结果为 [0.45, 0.55, 0.65]。
“ate” 的输出表示:0.05⋅[0.1,0.2,0.3]+0.2⋅[0.4,0.5,0.6]+0.5⋅[0.7,0.8,0.9]+0.1⋅[1.0,1.1,1.2]+0.15⋅[1.3,1.4,1.5],计算结果为 [0.75, 0.85, 0.95]。
“cat” 的输出表示 [0.45, 0.55, 0.65] 不仅包含自身的语义信息 [0.4, 0.5, 0.6],还包含了与 “ate” 和 “fish” 的关系信息。
“ate” 的输出表示 [0.75, 0.85, 0.95] 不仅包含自身的语义信息 [0.7, 0.8, 0.9],还包含了与 “cat” 和 “fish” 的关系信息。 -
【Transformer-GPT-BERT 进化关系】
Transformer(2017):
首次提出【自注意力机制】+【多头注意力机制】,
并提供了【编码器】(理解输入序列)和【解码器】(生成输出序列)架构,
主要用于 seq2seq的机器翻译。
GPT(2018):
继承了Transformer的基础架构,但是只使用【解码器】,
引入了【预训练+微调】的训练范式,预训练任务是自回归地【生成下一个词】,单向建模(单向生成),
主要用于 文本生成、对话系统 等【生成任务】。
BERT(2018):
继承了Transformer的基础架构,但是只使用【编码器】,
继承了GPT的【预训练+微调】的训练范式,预训练任务是【mask掉一个词+判断两句话是否是上下文】,双向建模(注意到了前后所有单词),
主要用于 语义理解、问答、文本分类等【理解任务】。 -
【encoder与decoder】
encoder:没有掩码(Mask),可以同时看到整个输入序列。
输出:编码后的上下文表示(Contextualized Representations)。
decoder:使用掩码,防止模型看到未来的信息(自回归生成)。
输出:目标序列的下一个词的概率分布。 -
【mask】
BERT 预训练时的 mask:掩码机制(MLM)是 预训练任务的一部分,用于让模型学会预测被掩码的词。
encoder的 mask:不使用掩码,编码时可以同时看到整个输入序列,做到双向建模。
decoder的 mask:使用掩码,看不到下文,解码时只能根据当前内容完成 单向的 自回归生成。 -
【模型部件】
embedding:处理输入序列的语义、位置、分段信息。
自注意力机制:捕捉序列内部的依赖关系,动态分配权重。
多头注意力机制:扩展自注意力机制,捕捉不同子空间的信息。类似卷积核。
前馈神经网络:对每个位置的表示进行非线性变换,增强表达能力。 -
【embedding阶段】
①都有【词向量嵌入】,从离散的token映射为向量,拥有训练好的【词向量矩阵W_token】
②都有【位置编码】,transformer使用固定的正弦余弦函数计算位置编码,gpt、bert有自己可学习的【位置向量矩阵W_pos】
③仅bert有【分段嵌入segment】,用于区分不同的句子段落(如 问题-答案),有自己的【分段嵌入矩阵W_seg】
关于token本身,transformer无特殊token,gpt有[SOS][EOS],bert有[CLS][SEP]
transformer、gpt、bert的【输入形状】都是(batch_size, seq_len),如(1,512),
【输出阶段形状】都是(batch_size, seq_len, 词嵌入维度),如(1, 512, 1024),
该信息即将进入encoder,包含着【词嵌入信息+位置信息(+分段嵌入信息)】。
ps:最后的embedding结果由【语义、位置、分段】三种信息相加得到,它们无法直接分离每个部分的贡献。 -
【多头注意力机制】:
目的:为了【在不同子空间内 学习到更丰富的特模式】,做到并行化学习。
实现:计算时,Q/K/V从(batch_size, seq_len, d_model=1024)被重塑为(batch_size, h=8, seq_len, d_k=128),每个头独立计算注意力分数, 计算后的所有8个头的输出再拼接在一起,拼回(batch_size, seq_len, d_model),再通过W_o投影融合,强制不同头的特征交互,避免子空间孤立。
头数与并行与硬件:头数通常选为2的幂次(如8、16)的硬件友好向,便于GPU并行计算时的内存对齐和线程调度,
同时 头数需满足d_model % h = 0,且d_k≥64(经验阈值)
训推头数不一致:训练(【8】x128)与推理(【16】x64)时分出来的头数不一样时,存在需要微调的可能性。 -
【前馈神经网络FFN】
标准ffn:mma+激活函数relu+mma(+dropout)+ 残差 + layernrom,FFN(x)=ReLU(xW 1 +b 1 )W 2 +b 2
bert的ffn:layernorm+mma+激活函数gelu+mma(+dropout)+ 残差 + layernrom,①开头多了个laynernorm②使用gelu而不是relu
为什么是layernorm不是bn:
layernorm在channelC维度做归一化,bn在batch维度做归一化;
①文本是变长序列,bn不好处理
②layernorm在channelC特征维度做归一化更适合文本数据的特性
③layernorn在训练与推理时行为一致不受batch size影响
为什么是gelu不是relu:
①relu在x=0处不可导,训练效果不好
②gelu公式是【x*高斯正态分布(x)】,平滑可导适合深度训练,且可以看作是对输入的概率加权,适合处理文本中的概率分布 -
【Bert large模型结构】
1 BertModel(
2 (embeddings): BertEmbeddings(
3 (word_embeddings): Embedding(30522, 1024, padding_idx=0)
4 (position_embeddings): Embedding(512, 1024)
5 (token_type_embeddings): Embedding(2, 1024)
6 (LayerNorm): LayerNorm((1024,), eps=1e-12, elementwise_affine=True)
7 (dropout): Dropout(p=0.1, inplace=False)
8 )
9 (encoder): BertEncoder(
10 (layer): ModuleList(
11 (0-23): 24 x BertLayer(
12 (attention): BertAttention(
13 (self): BertSdpaSelfAttention(
14 (query): Linear(in_features=1024, out_features=1024, bias=True)
15 (key): Linear(in_features=1024, out_features=1024, bias=True)
16 (value): Linear(in_features=1024, out_features=1024, bias=True)
17 (dropout): Dropout(p=0.1, inplace=False)
18 )
19 (output): BertSelfOutput(
20 (dense): Linear(in_features=1024, out_features=1024, bias=True)
21 (LayerNorm): LayerNorm((1024,), eps=1e-12, elementwise_affine=True)
22 (dropout): Dropout(p=0.1, inplace=False)
23 )
24 )
25 (intermediate): BertIntermediate(
26 (dense): Linear(in_features=1024, out_features=4096, bias=True)
27 (intermediate_act_fn): GELUActivation()
28 )
29 (output): BertOutput(
30 (dense): Linear(in_features=4096, out_features=1024, bias=True)
31 (LayerNorm): LayerNorm((1024,), eps=1e-12, elementwise_affine=True)
32 (dropout): Dropout(p=0.1, inplace=False)
33 )
34 )
35 )
36 )
37 (pooler): BertPooler(
38 (dense): Linear(in_features=1024, out_features=1024, bias=True)
39 (activation): Tanh()
40 )
41 ) -
【Bert Large shape计算流描述】
【embeddding阶段】——设置bert large词向量长度【d】是1024,token长度【n】是512
输入:三份【1, 512】的token、mask、seg信息,
经过三份对应的权重W_token[30522, 1024],W_mask[512, 1024],W_seg[2, 1024](只有0与1)的gather算子,
最后经过一个layernrom算子,输出:【1, 512, 1024】
【encoder阶段】
【attention】
【Wq、Wk、Wv[1024, 1024]】
【X_emb * Wq = Q[1, 512, 1024],X_emb * Wk = K[1, 512, 1024],X_emb * Wv = V[1, 512, 1024]】
其中自然意义是8个head,每个head 128维; 因芯片有16个spc,实际上是16x64地去计算。
【Q1[512, 64] * K1^T[64, 512] = Q1K1[512, 512],
softmax( Q1K1)[512, 512]*V1[512, 64]=multihead1[512, 64]】
【multihead1】~【multihead16】 concat在一起,得到【Attention[512, 64x16]=Attention[512, 1024]】
【ffn】
Attention【512, 1024】->【layernorm1024, 1024】
->[512, 1024]->【gelu1024, 4096】
->[512, 4096]->【layernorm4096, 1024】
->encoder_out【512, 1024】
Nx【encoder阶段】
bert large是24个encoder头尾链接(输入输出都是[512, 1024]),bert base是12个(bert large词向量长度是768)
【任务阶段】
第24个encoder结束后,可以连接不同的后处理算子,达到做不同任务的目的,
如 问答任务、命名实体识别任务、情绪判定任务等。
更多推荐

所有评论(0)