nlp/搜广推
transformer结构?

encoder-decoder模型。编码组件由6个encoder组成,解码组件由6个decoder组成。
每个encoder结构相同,但不共享参数。每个encoder可以分为两个子层:自注意力层和前馈神经网络。每个decoder可以分为三层:自注意力层、编码-解码注意力层、前馈神经网络。
注意力层包括:多头注意力机制、ResNet和LayerNorm。前馈神经网络层包括:前馈神经网络、ResNet和LayerNorm。
位置编码的作用?
位置编码:解决时序问题。“我爱你”和“你爱我”不同。
基于正余弦:
解释 self-attention?
self-attention宏观上做了这件事:要更好的理解句中某个特定单词的含义,你要把它放到整个语境之中去理解,比如通过对上下文的把握。所以self-attention计算其他词语对判断特定词语词义的重要程度,把该词编码为该词在内的所有词的加权和。
self-attention怎么计算?由编码器的输入向量乘不同的权重生成三个向量:查询向量Q、键向量K、值向量V(在论文中的维度是64,multihead attention设置8个头,每个头的维度是512/8=64)
QKV的作用是什么?
Q:当前单词的表示形式,用于对于其他单词评分
K:序列中所有单词的标签,我们找相关单词时的对照物
V:单词的实际表示,一旦我们队每个单词的相关度打分之后,我们就要读value进行相加表示当前正在处理的单词的value
每个计算步骤的作用?
Q K T QK^T QKT:计算两个单词的相似度
/ √ ( d k ) /√(d_k) /√(dk):随着 d k d_k dk增大, Q K T QK^T QKT结果也随之增大,这样会将softmax函数推向非常小的取余,使收敛困难,可能会出现梯度消失的情况。(假设Q和K是具有均值为0方差为1的独立随机变量,那它们的点积均值为0方差为 d k d_k dk)
s o f t m a x ( ) softmax() softmax():使所有单词的分数归一化,得到分数是正值且和为1
⋅ V ·V ⋅V:留下我们想要关注的词的value,把其他不相关的词丢掉
attention中 /√(d_k) 的作用是什么?
随着 d k d_k dk增大, Q K T QK^T QKT结果也随之增大,这样会将softmax函数推向非常小的取余,使收敛困难,可能会出现梯度消失的情况。(假设Q和K是具有均值为0方差为1的独立随机变量,那它们的点积均值为0方差为 d k d_k dk)
s o f t m a x ( ) softmax() softmax():使所有单词的分数归一化,得到分数是正值且和为1
解释Multi-Head Attention?
multi-head attention的作用?
① 扩展了模型专注于不同位置的能力(不会把过多注意力放在自己身上)
② 得出了注意力层的多个表示子空间,每个注意力透支关注输出序列的一个子空间,相互独立。
multi-head attention怎么做?
① 输入向量乘 W Q W_Q WQ、 W K W_K WK、 W V W_V WV得到Q、K、V
② 经过linear层得到8个不同的Q、K、V
③ 计算八次self-attention
④ 得到八个结果,将它们concat起来
⑤ 乘一个附加权重 W O W_O WO

FeedForward的作用?
全连接的前馈神经网络,它对输入的特征进行非线性变换,以增加模型的表达能力和复杂度

ResNet 和 LayerNorm的作用?
避免梯度消失和梯度爆炸。
为什么用layernorm不用batchnorm?
① 在 NLP 中,序列的长度可以变化,而 Batch Normalization 对每个批次的序列长度有一定的要求
Batch Normalization 在 NLP中对每个批次的序列长度要求是序列长度一致,即在每个批次中的所有序列的长度必须相同。这是因为 Batch Normalization 中对每个feature 的均值和方差的计算是基于每个 feature 在一个 batch 中的样本计算的,而如果序列的长度不一致,则无法直接应用Batch Normalization。因此,在使用 Batch Normalization 进行神经网络训练时,需要保证每个 batch中的序列长度相同。
② Layer Normalization 是在每个样本的特征维度上进行归一化,因此能够处理长度不同的序列。
[扩展]batchnorm/layernorm/instancenorm/groupnorm
nlp: [b, seq_len, d_model]
bn: [b, seq_len, 1]
ln: [1, seq_len, d_model]
in: [1, seq_len, 1]
gn: [1, seq_len, group]
cv: [b, h, w, d_model]
bn: [b, h, w, 1]
ln: [1, h, w, d_model]
in: [1, h, w, 1]
gn: [1, h, w, group]
decoder中的注意力层和encoder有什么不同?
- 带masked的Multi-Head Attention,本质是Self-Attention,该自注意力层只允许关注已输出位置的信息
- 不带masked的Multi-Head Attention,本质是Cross-Attention
【补充】最后的linear层和softmax
linear:将解码器生成的向量映射到logits向量中,logits向量维数是词表大小,每一维对应一个单词的分数
softmax:将这些分数转化为概率,选择其中概率最大的位置的词汇作为当前时间步的输出
[来自Transformer通俗笔记:从Word2Vec、Seq2Seq逐步理解到GPT、BERT]
手撕multi-head attention?
import math
import torch
import collections
import numpy as np
import torch.nn as nn
class MultiHeadAttention(nn.Module):
def __init__(self, heads, d_model, dropout=0.1):
super().__init__()
#输入的特征维度
self.d_model=d_model
#每个头的特征维度
self.d_k=d_model//heads
#头数
self.h=heads
# K Q V三个矩阵,分别是输入通过三个矩阵投影得到的
self.q_linear=nn.Linear(d_model,d_model)
self.k_linear=nn.Linear(d_model,d_model)
self.v_linear=nn.Linear(d_model,d_model)
self.dropout=nn.Dropout(dropout)
#输出线性层
self.out=nn.Linear(d_model,d_model)
def attention(self,q,k,v,mask=None):
scores=torch.matmul(q,k.transpose(-2,-1))/math.sqrt(self.d_k)
if mask is not None:
scores=scores.masked_fill(mask==0,float('-inf'))
#对score进行softmax
score=torch.nn.functional.softmax(scores,dim=-1)
score=self.dropout(score)
output=torch.matmul(score,v)
return output
def forward(self,q,k,v,mask=None):
batch_size=q.shape[0]
#转换成(batch个 head个 序列长度 特征维度)的张量
q=self.q_linear(q).view(batch_size,-1,self.h,self.d_k).transpose(1,2)
k=self.k_linear(k).view(batch_size,-1,self.h,self.d_k).transpose(1,2)
v=self.v_linear(v).view(batch_size,-1,self.h,self.d_k).transpose(1,2)
score=self.attention(q,k,v,mask)
concat=score.transpose(1,2).contiguous().view(batch_size,-1,self.h*self.d_k)
output=self.out(concat)
return output
if __name__ == '__main__':
heads=4
d_model=128
dropout=0.1
model=MultiHeadAttention(heads,d_model,dropout)
batch_size=2
seq_len=5
q=torch.rand(batch_size,seq_len,d_model)
k=torch.rand(batch_size,seq_len,d_model)
v=torch.rand(batch_size,seq_len,d_model)
output=model.forward(q,k,v)
loss=output.mean()
loss.backward()

__init__需要初始化:
输入维度、多头注意力维度、头数
输入linear层,输出linear层
self-attention中的dropout层
self-attention中:
q/k/v的形状都是[b,h,seq_len,dk]
q k T qk^T qkT计算两个维度的内积,维度是[b, h, seq_len, seq_len],转置用transpose,内积用torch.matmul,根号用math.sqrt
如果需要mask,masked_fill是 PyTorch 中的一个函数,用于将 mask == 0 为 True 的位置的 scores 值替换为 float('-inf'),即负无穷大。为什么使用负无穷大?因为负无穷大会导致对应位置的 softmax 输出接近于零。
softmax用torch.nn.functional.softmax,dim=-1。 q k T / d k qk^T/sqrt{d_k} qkT/dk的维度是[b,h,seq_len,seq_len],dim=-1表示对[seq_len,seq_len]中的每行做softmax
dropout层将score中随机一些值设为0
与v相乘的内积依旧是torch.matmul
forward中:
input linear:qkv做linear
分成多头:view+transpose。为什么不直接view?因为 view 操作需要确保在内存中的数据布局是连续的,并且按照你指定的形状重新解释数据。然而,如果你直接尝试将 [batch_size, seq_len, d_model] 的张量 view 成 [batch_size, num_heads, seq_len, d_k],内存中的数据排列可能不会按照预期的顺序进行。
attention:得到的tensor的形状是[b,h,seq_len,dk]
concat:转换成[b,seq_len,h,dk],contiguous()保证内存连续,view转换回[b,seq_len,h*dk]
output linear:output linear
transfomer相比于cnn/rnn的优势是什么?
cnn:cnn提取的是局部特征,但是对于文本数据,忽略了长距离的依赖。卷积网络捕捉长依赖的能力非常弱,主要依靠深度来捕捉长距离依赖。
rnn:rnn随着距离的增加,信息衰减得越多。rnn只能用到前面的词,而transfomer可以用到前后的词。rnn是一个顺序的结构,无法同时并行计算,导致RNN的计算效率不高。
介绍一下bert?
-
BERT基于Transformer的编码器(Encoder)架构,利用了多层的Transformer编码器来处理输入文本。是一种双向模型。
-
BERT采用了“预训练+微调”的方法。它首先在大规模的文本语料库上进行无监督的预训练,然后通过监督学习在特定任务上进行微调。
预训练任务:
MLM:随机遮盖输入文本中的一些单词,并要求模型预测这些被遮盖的单词。
数据量:BERT会随机选择15%的单词,并用一个特殊的[MASK]标记替换其中的80%,用其他随机单词替换10%,保留原始单词的10%。
NSP:BERT在预训练阶段还会进行下一句预测任务。模型会输入成对的句子,并尝试判断第二个句子是否是第一个句子的实际后续句子。
数据量:50%的情况下,第二个句子确实是第一个句子的后续句子,另外50%的情况下则是随机抽取的一个无关句子。通过这个任务,BERT学习了句子间的关系和连贯性。
bert的输入有几个embedding?
每个单词有三个embedding:token embedding + 句子embedding + 位置信息embedding
bert对输入数据加入了哪些特殊标记?作用是什么?
两个句子之间通过分隔符「SEP」分割,最前面是起始标识「CLS」
[CLS] 标记: 用于表示整个输入序列的全局信息。在许多下游任务(如文本分类、情感分析、句子对分类等)中,最终的分类结果是基于 [CLS] 标记对应的隐藏状态向量进行的。
[SEP] 标记: 用于分隔两个句子或文本片段,在双句子任务中起到分隔符和句子结束标记的作用。
roberta和bert的区别?
和项目强相关,几乎每个面试官都问
- 增加了训练数据量和预训练时间,增加batchsize,调整学习率,增加输入序列长度。
- 删除NSP预训练任务:
- 动态masking:对于每一个输入样本序列,都会复制10条,然后复制的每一个都会重新进行mask,即拥有不同的masked tokens。确保了模型在训练过程中可以看到更多样化的掩码模式,从而使模型能够更好地学习到词汇在不同上下文中的语义关系。
为什么nsp不好?
- 引入噪声,学到与实际任务无关的特征
在实际场景中,不连续的句子可能仍然在语义上存在一定的关联,但 NSP 中的随机负样本通常与前一句没有任何语义联系,这使得任务本身变得相对容易。模型可能会过度依赖表面的统计特征(例如句子长度、词汇重复率等)来区分正负样本,而不是真正理解句子之间的复杂关系。
- 与语言建模任务的冲突,减少训练有效性
NSP 关注句子关系:NSP 任务要求模型判断句子之间的连续性,这引导模型关注的是句子级别的关系。
MLM 关注词汇和上下文:MLM 任务要求模型通过掩盖的单词推测其含义,模型需要更深入地理解单词在句子中的作用及其上下文关系。
NSP 任务所占用的训练时间和计算资源,可能本可以更好地用于更具挑战性的 MLM 任务。如果没有 NSP 任务,所有的训练资源都可以集中在 MLM 上,从而提高模型的整体训练效率。
为什么分类模型bert的最后一层不做/√(dk)?
在BERT中的最后一层中不进行向量除以根号下dk(dk为向量维度的平方根)操作的原因是为了保持更多的信息。在BERT模型中,每个位置的输入是在经过多层Transformer编码器的处理之后得到的表示,这些表示包含了丰富的语义信息。进行向量除以根号下dk的操作会降低向量的范数,可能导致一些信息的损失。
在BERT模型中,最后一层的输出经过softmax操作,并作为分类器的输入,从而实现文本分类等任务。在这个过程中,不进行向量除以根号下dk的操作可以更好地保留输入表示中的信息,有助于提高模型的性能和泛化能力。
auc是什么?数据分布会影响auc吗?
混淆矩阵:
Actual
1 0
Predicted 1 TP FP
0 FN TN
TPR(True Positive Rate)/真阳性率/灵敏度/召回率: TPR = TP TP + FN text{TPR} = frac{text{TP}}{text{TP} + text{FN}} TPR=TP+FNTP
FPR(False Positive Rate)/假阳性率: FPR = FP FP + TN text{FPR} = frac{text{FP}}{text{FP} + text{TN}} FPR=
文章来源于互联网:【记录贴 | 持续更新】搜广推/aigc 面试题记录
5bei.cn大模型教程网











