一、python
1、常用的数据类型
- 字符串(str)
- 列表(list):有序集合,可以向其中添加或删除元素
- 元组(tuple):有序集合,元组不可变
- 字典(dict):无序集合,由键值对构成
- 集合(set):一组key的集合,每个元素都是唯一,不重复且无序
2、字符串常用方法
- 分割,直接在字符串后面跟[a:b],切割的范围为[a,b)
- format控制输出格式
- join连接字符串
- replace字符串替换
- split根据指定字符分割
3、列表常用方法
(1)分割,同str
(2)拼接
- +:返回新的列表
- append:修改原来的列表,会把整个list作为一个元素添加进去
- expend:修改原来的列表,可迭代,把数据拆分成单个元素加进去
(3)删除 - del():根据下标删除元素
- pop():删除最后一个元素
- remove():删除指定元素
(4)排序
sort,默认按照从小到大排序,添加reverse=True
可以从大到小排序
4、字典的常用方法
(1)清空,clear()
(2)指定删除,.pop(‘key’)
(3)遍历
三种遍历方式,分别是key,value,item
dict = {'key1':1,'key2':2}
mykey = [key for key in dict.keys()]
print(mykey)
myvalue = [value for value in dict.values()]
print(myvalue)
myitem = [item for item in dict.items()]
print(myitem)
(4)创建新字典fromkeys
给一个key列表,然后给一个key值,可接受一个或两个参数,若一个则value为None,若两个则value为指定数
key = ['1','2','3','4','6']
dict = dict.fromkeys(key,0)
5、集合的常用方法
(1)创建
set创建可接收可迭代对象
set = {1,2,3}
set1 = set(list)
(2)删除
- remove()
- discard()
- clear()
remove在元素不存在时会报错,而discard不会。
(3)判断是否存在in
(4)长度获取len()
(5)并union()
或|
(6)交intersection()
或&
(7)差difference()
或-
(8)对称差
仅存在于其中一个集合中的元素构成的集合,symmetric_difference()
或^
6、元组的常用方法
元组和数组存储的数据格式大致一致,但无法改变。
count()
:记录某个元素的出现次数index()
:返回指定元素在元组中出现的第一个位置
7、is和==的区别
- is比较的是对象的值
- ==比较的是对象的内存地址
8、python函数中的参数类型
- 位置参数:参数是按照它们在函数定义中的位置来传递的
- 关键字参数:通过参数名进行传递的。在函数调用中,指定参数名并提供相应的值。
- 默认参数:函数定义时为参数制定默认值。若在函数调用中为提供该参数的值,则使用默认值。
- 可变参数:允许函数接受任意数量的参数。在函数定义中,使用星号(*)表示可变参数。
9、*arg和**kwargs作用
*arg和**kwargs是用来处理函数调用中的可变数量的参数的常用约定。它们分别用于处理位置参数和关键字参数。
*args将传递给函数的所有位置参数都收集到一个元组中。
**kwargs将传递给函数的所有关键字参数都收集到一个字典中。
10、深浅拷贝
浅拷贝,指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用,修改里面的子元素,比如说嵌套的list,会导致都改变
深拷贝,是指重新分配一块内存,创建一个新的对象,并将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中,因此,新对象和原对象没有任何关联。
注意:在python中,元组(tuple)和字符串(str)是不可变对象,这意味着他们的值一旦被创建就无法更改。因此,在进行深拷贝和浅拷贝时,不会创建新的对象副本,而是复制引用。
11、init和new的区别
- __new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例对象,是个静态方法。
- __init__是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值,通常用在初始化一个类实例的时候,是一个实例方法。
(1)__new__至少要有一个参数cls,代表当前类,此参数在实例化时由python解释器自动识别。
(2)__new__必须要有返回值,返回实例化出来的实例,可以return父类(通过super(当前类名,cls))__new__出来的实例,或者直接是object的__new__出来的实例。
(3)__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其他初始化的动作,__init__不需要返回值。
(4)如果__new__创建的是当前类的实例,会自动调用__init__函数,通过return语句里面调用的__new__函数的第一个参数是cls来保证是当前类实例,如果是其他类的类名,那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__函数,也不会调用其他类的__init__函数。
12、isinstance和type的区别
isinstance()函数来判断一个对象是否是一个已知的类型,类似type()
- type()不会认为子类是一种父类类型,不考虑继承关系;
- isinstance()会认为子类是一种父类类型,考虑继承关系。
二、深度学习
1、Relu激活函数的作用
f(x)=max(0,x),它的作用是将输入值限制在非负范围内,并且在正半轴上具有线性性质
作用:
- 增强模型非线性表达的能力
- 加速模型训练速度,加大稀疏性,减少模型参数
2、损失函数
(1)均方误差(MSE)
均方误差也叫方法损失函数或最小二乘法。
数学表达式:
通过计算每个预测值和实际值之间的差值的平方和再求平均,平方损失函数是光滑的,可以用梯度下降法求解,但是当预测值和真实值差异较大时,它的惩罚力度较大,因此对异常点较为敏感。
(2)平方差
两个数先求差值再求平方
(3)方差以及期望
3、IoU
IoU(Intersection over Union,交并比)是衡量两个边界框重叠程度的指标,广泛应用于目标检测任务。计算IoU的步骤如下:
(1)计算交集
- 找到另个边界框的重叠区域
- 计算这个重叠区域的面积
(2)计算并集 - 计算两个边界框的总面积
- 并集面积等于两个边界框总面积-交集面积
(3)计算IoU - 用交集面积除以并集面积
4、模型评估标准
TOP-1和TOP-5
(1)TOP-1准确率
- TOP-1准确率是指在预测结果中,模型输出的最可能的类别与真实标签相符的比例。
- 简单来说,若模型给出的最高概率的类别与真实标签相符,则该样本被视为预测正确。
- TOP-1准确率的计算公式是正确分类的样本数/总样本数。
(2)TOP-5准确率 - TOP-5准确率是指在预测结果中,模型输出的前五个最可能的类别中包含了真实标签的比例。
- 通常来说,TOP-5准确率更宽容,若模型的真实标签在其前五个预测中,则被视为预测正确。
- TOP-5准确率的计算方式是至少有一个正确分类的样本数/总样本数。
5、卷积核与池化层
(1)卷积层
- 输出特征图的宽度 = (输入特征图宽度 - 卷积核宽度 + 2 * 填充)/ 步长 + 1
- 输出特征图的高度 = (输入特征图高度 - 卷积核高度 + 2 * 填充)/ 步长 + 1
- 输出特征图的通道数 = 卷积核个数
- 若有多个输入通道(如RGB图像),则每个通道都会有一个对应的卷积核,最后输出特征图是所有通道的卷积结果的叠加。
(2)池化层
- 输出特征图的宽度 = (输入特征图宽度 - 卷积核宽度) / 步长 + 1
- 输出特征图的高度 = (输入特征图的高度 - 卷积核高度) / 步长 + 1
- 池化操作通常是不填充的,因此输出的尺寸会相应地缩小。
- 池化层不改变特征图的深度(通道数),每个通道的赤化操作是独立进行的。
6、全卷积
核心思想:
- 不含全连接层的全卷积网络,可适应任何尺寸输入;
- 反卷积层增大图像尺寸,输出精细结果;
- 结合不同深度层结果的跳级结构,确保鲁棒性和精确性。
7、梯度下降优化算法
(1)SGD
- 基本思想:SGD在每一步更新中仅使用一个(或一小批)样本来计算梯度,而不是整个数据集。这种方法可以显著减少计算量,使得训练大规模数据集变得可行。
- 学习率:SGD通常需要手动调整学习率,并且可能会使用如学习率衰减这样的技巧来帮助模型收敛。学习率的选择对SGD的性能影响很大。
- 收敛速度:SGD的收敛速度通常比较慢,尤其是在接近最小值的平坦区域。
- 泛化能力:研究表明,由于SGD的噪声更大,它可能有助于模型找到泛化能力更好的解。
(2)Adam(自适应矩估计) - 基本思想:Adam是一种自适应学习率的优化算法,它结合了动量和RMSprop的优点。Adam会为不同的参数计算不同的自适应学习率。
- 学习率:Adam自动调整学习率,通常不需要像SGD那样手动微调学习率,这使得Adam在很多情况下都能较快地收敛;
- 收敛速度:由于自适应学习率的特性,Adam在初期训练阶段通常比SGD收敛得更快。
- 泛化能力:尽管Adam在许多任务中都显示出了较快的收敛速度,但对于某些问题,Adam可能导致过拟合,泛化能力不如SGD。
(3)应用场景 - Adam:由于其易用性和快速收敛的特点,Adam非常适合在需要快速得到结果的场景中使用,特别是在计算资源有限或模型较复杂时。
- SGD:如果模型训练时出现过拟合,或者当你有足够的时间和资源来精细调整学习率时,SGD可能是更好的选择。对于大规模分布式训练,SGD的泛化能力可能更优。
8、层归一化
(1)LayerNorm
对每个样本的特征进行归一化,而不是对整个批次的特征进行归一化。
计算公式:
其中,x是输入的特征向量,μ是特征向量的均值,σ是特征向量的标准差,γ和β是学习的缩放系数和平移系数,ε是一个很小的数用于稳定计算。
(2)RMS Norm 均方根Norm
简化了LayerNorm,去掉了计算平均值的部分。计算速度更快,效果甚至略有提升。
(3)DeepNorm
Deep Norm可以缓解爆炸式模型更新的问题,把模型更新限制在常数,使得模型训练过程更稳定。
Deep Norm方法在执行Layer Norm之前,up-scale了残差连接(alpha > 1);另外在初始化阶段down-scale了模型参数(beta < 1)。
(4)Norm层添加位置
LN在LLMs中的不同位置有什么区别?
①Post LN:
x
t
+
1
=
N
o
r
m
(
x
t
+
F
t
(
x
t
)
)
x_{t+1} = Norm(x_t + F_t(x_t))
xt+1=Norm(xt+Ft(xt))
- 位置:LN在残差连接之后
- 缺点:Post LN在深层的梯度范式逐渐增大,导致使用Post LN的深层transformer容易出现训练不稳定的问题。
②Pre LN: x t + 1 = x t + F t ( N o r m ( x t ) ) x_{t+1}=x_t + F_t(Norm(x_t)) xt+1=xt+Ft(Norm(xt)) - 位置:LN在残差连接中
- 优点:相比于Post LN,Pre LN在深层额梯度范式近似相等,所以使用Pre LN的深层transformer训练更稳定,可以缓解训练不稳定的问题
- 缺点:相比于Post LN,Pre LN的模型效果略差
③Sandwich LN - 位置:在Pre LN的基础上,额外插入了一个Layer Norm
- 优点:Cogview用来避免值爆炸的问题
- 缺点:训练不稳定,可能会导致训练崩溃
(5)现在的模型应用 - GPT3: Pre Layer Norm
- LLaMA:Pre RMS Norm
- baichuan:Pre RMS Norm
- ChatGLM-6B:Post Deep Norm
- ChatGLM2-6B:Post RMS Norm
- Bloom:Pre Layer Norm
- Falcon:Pre LayNorm
9、激活函数
(1)全连接层激活函数
F
F
N
(
x
)
=
f
(
x
W
1
+
b
1
)
W
2
+
b
2
FFN(x)=f(xW_1+b_1)W_2+b_2
FFN(x)=f(xW1+b1)W2+b2
(2)GeLU激活函数
相较于ReLU函数,GELU函数在负值区域有一个非0的梯度,从而避免了死亡神经元的问题。另外,GELU在0附近比RELU更加平滑,因此在训练过程中更容易收敛。值得注意的是,GELU的计算比较复杂,因此需要消耗更多资源。
(3)Swish激活函数
S
w
i
s
h
(
x
)
=
x
⋅
s
i
g
m
o
i
d
(
β
⋅
x
)
Swish(x) = x \cdot sigmoid(\beta \cdot x)
Swish(x)=x⋅sigmoid(β⋅x)
其中,β是一个可学习的参数。Swish激活函数的特点是:在x≤0时,它的形状类似RELU,而在x > 0时,它更加平滑,在大部分情况下,它的导数都是正的。
Swish函数的优点在于,相比于relu等激活函数,它在一些任务上能取得更好的性能,如图像分类、自然语言处理等。并且,Swish激活函数的导数计算相对简单,不涉及复杂的指数运算,因此也提高了模型训练的效率。
(4)主流模型
10、CNN、RNN、LSTM
(1)CNN
CNN是一种专门用于处理具有网格结构数据,比如图像的深度学习模型。
由卷积层、池化层和全连接层组成。卷积层通过卷积核在输入数据上滑动,提取特征;池化层通过对局部区域进行下采样,减少数据维度,提高计算效率,同时保留重要特征;全连接层用于将高层抽象特征映射到输出类别。
CNN主要用于图像处理任务,比如图像分类、目标检测、图像分割等等。
(2)RNN
RNN是一类用于处理序列数据的神经网络,具有记忆功能,可以捕捉序列中的时间依赖关系。
由输入层、隐藏层和输出层组成。输入层接受序列数据的当前时间步输入,隐藏层通过循环连接,将前一时间步的隐藏状态与当前输入结合,计算新的隐藏状态;输出层生成当前时间步的输出。RNN的问题就是它存在梯度消失和梯度爆炸问题,难以捕捉长期依赖。RNN主要用于处理时间序列数据,比如文本生成、机器翻译等等。
(3)LSTM
LSTM是一种特殊的RNN,专门设计用于解决传统RNN的梯度消失问题,从而更好捕捉长期依赖关系。
LSTM有多个门控机制组成,输入门控制当前输入信息进入记忆细胞,遗忘门控制前一时间步的记忆细胞信息是否保留;输出门控制记忆细胞信息输出到隐藏状态。LSTM应用于需要捕捉长期依赖的序列任务,如语言建模、情感分析等等。
三、Transformer
1、什么是深度学习,和机器学习的区别?
深度学习是机器学习的一个分支。
传统机器学习的特征提取主要依赖人工,针对特定简单任务时人工提取特征会简单有效,但是并不能通用。
深度学习的特征提取并不依靠人工,而是机器自动提取的。
2、简单介绍Transformer
Transformer是一种基于自注意力机制的神经网络模型。Transformer模型由编码器和解码器两部分组成,编码器用于将输入序列编码成一个高维向量表示,解码器用于将这个向量表示解码成目标序列。Transformer最核心的部分是自注意力机制,它能够让模型在不同位置之间进行信息传递和交互,从而更好地学习输入序列中的信息。
3、Transformer输入是什么
Transformer的输入是词向量与位置向量之和,,词向量可以通过预训练的词向量模型或是在模型内部学习得到。位置向量可以通过固定位置编码公式获得或者在模型内部学习得到。
4、固定位置编码和可学习位置编码优缺点
固定位置编码优点是可以根据公式快速获得句子的位置信息,无需在训练中继续学习;缺点是不能处理变化的序列。
可学习位置编码的优点是可以通过训练动态理解句子的位置信息;缺点是需要大量的数据才能获取比较全的位置信息。
5、Transformer的Encoder模块
由多个相同的层堆叠而成,每一层由两个子层组成,分别是多头注意力机制和前馈神经网络。在多头注意力机制中,输入序列会经过是三个线性变换,分别是Q,K,V,然后进行多头注意力计算,得到每个位置对其他位置的注意力权重,再将输入序列加权求和得到多头注意力的输出。在前馈神经网络中,多头注意力的输出经过两个全连接层和ReLU激活函数的变换,得到每个位置的特征表示。接下来,这两个子层会经过残差连接和层归一化操作,使得模型更容易训练,也能更好地捕捉输入序列间的相关性。
6、为什么transformer使用LayerNorm而不是BatchNorm
LN是一种能够应对不同序列长度的归一化方法,它对每个样本的特征值进行归一化。BN是一种在深度神经网络中广泛使用的归一化方法,通过对每个小批量的输入进行归一化,从而使得网络的训练更加稳定,并加速收敛速度。但是,在自然语言处理任务中,输入序列长度通常是不同的,因此很难将不同长度的序列组成一个小批量进行归一化。
7、Transformer输入只能相加吗
在Transformer模型中,输入的两个部分是词向量和位置编码,它们是分别生成的,然后进行相加得到最终的输入表示。因此,在Transformer中,输入确实只能相加,即词向量和位置编码不能进行其他的运算,如乘法、除法等。这是因为词向量和位置编码的维度是相同的,都是模型的隐藏层维度,而它们的作用是不同的,词向量用于表达单词的语义信息,位置编码用于表示单词在句子中的位置信息。因此,将它们相加可以将这两种信息融合在一起,从而为模型提供更加丰富的输入信息。如果进行其他的运算,如乘法、除法等,可能会破坏词向量和位置编码的信息,影响模型的性能。
8、Transformer为什么使用多头注意力机制
提高模型的表达能力,多头注意力机制可以让模型在不同的注意力空间下学习到不同的特征,从而能够更好地表达输入序列的信息。如果只使用一个注意力头,那么模型可能会在学习特定的特征时出现瓶颈,导致模型的表达能力受限。
9、Transformer为什么Q和K使用不同的权重矩阵生成,为什么不能使用同一值进行自身的点乘
在Transformer中,Q和K使用不同的权重矩阵生成是为了让模型在学习不同的特征时更加灵活。Q和K的区别在于它们所代表的的信息不同,Q代表查询信息,K代表键信息,它们的作用不同,因此使用不同的权重矩阵可以让模型在不同的注意力空间下学习到更加丰富的特征,并提高模型的表达能力。如果使用同一个权重矩阵进行自身的点乘操作,可能会使模型在学习特定的特征时出现瓶颈,导致模型表达能力受限,从而影响模型的性能。
10.Transformer计算attention时为何选择点乘而不是加法
是因为点乘计算的方式是一种更有效的方式,可以更好地捕捉输入序列的相关性。与加法相比,点乘可以使模型在计算注意力时更加精确,同时也具有更好的计算效率。
11、在计算attention时,为什么进行softmax之后需进行scaled(为什么除以dk的平方根)
在计算self-attention时,需要进行softmax操作,以计算每个输入序列位置对其他位置的注意力权重。为了避免softmax函数的指数计算导致数值溢出或下溢,Transformer模型中使用了scaled dot-product attention,即在softmax之前对向量点乘结果进行了缩放操作,用于控制点乘结果的大小。
具体来说,该缩放操作是将点乘结果除以一个值,这个值是输入向量的维度的平方根,即dk的平方根,其中dk表示每个向量的维度。这个缩放因子的作用是:当输入向量的维度增加时,点乘结果的大小也会增加,导致softmax函数的指数计算变得困难,缩放因子能够使点乘结果的大小保持在一个合适的范围内,从而提高计算的稳定性。
12、Transformer的Decoder模块
Transformer模型的Decoder模块用于将Encoder模块的输出映射到目标序列的一组连续表示的核心部分。该模块由多个Decoder层组成,每个Decoder层包含以下部分:
- 自注意力层:与Encoder中的自注意力层类似,Decoder中的自注意力层也是将输入序列中每个位置的表示向量作为查询向量、键向量和值向量,通过多头注意力计算得到每个位置的上下文向量。
- 编码器-解码器注意力层:该层用于将Encoder模块的输出和Decoder中上一层的输出结合起来,以便更好地理解输入和输出之间的关系。具体来说,该层将Encoder模块的输出作为键向量和值向量,将Decoder中上一层的输出作为查询向量,通过多头注意力机制计算得到每个位置的上下文向量。
- 前馈神经网络层:该层经过自注意力层和编码器解码器注意力层编码的信息进行非线性变换,以提高模型的表达能力。
- 残差连接层和层归一化层:这两个层和Encoder模块中的残差连接层和层归一化层类似,用于保证模型的稳定性和加速训练。在每个Decoder层之间,都进行了层归一化处理。
Decoder模块的最后一层输出的表示向量经过一个线性变换和softmax函数,得到每个位置上每个单词的概率分布。然后可以根据分布进行单词的选择和预测。
13、Decoder阶段的多头自注意力和Encoder的多头自注意力有什么区别
(1)查询向量不同
在Encoder的多头自注意力中,每个词向量都被用作查询、键和值,即Q=K=V,而在Decoder的多头自注意力中,查询向量是上一个Decoder层的输出,而键和值向量则是Encoder模块的输出。
(2)掩码
在Decoder的多头自注意力中,需要使用掩码来防止当前时间步的解码器看到未来时间步的信息。具体来说,将未来时间步的位置的注意力全中设置为0,这样在计算当前时间步的注意力分数时,就不回考虑未来时间步的信息。
(3)添加编码
在Decoder的多头自注意力中,需要将编码器的输出添加到键向量和值向量中,以便解码器能够了解输入序列的信息。
(4)位置编码
在Decoder的多头自注意力中,位置编码的计算方式与Encoder中的位置编码不同。Encoder中的位置编码是为了表示输入序列中单词的位置关系,而Decoder中的位置编码是为了表示输出序列中单词的位置关系。
14、Transformer的并行化体现在哪些地方?Decoder端可以做并行化吗
(1)多头注意力机制
多头注意力机制将输入序列分成多个子序列,并同时计算每个子序列的注意力表示,从而实现了多头并行计算。这种并行计算方式可以有效加速模型的训练和推理过程。
(2)Encoder端的并行化
在Encoder端,Transformer模型将输入序列分成多个子序列,并分别在不同的计算设备上进行计算。这种并行计算方式可以显著提高模型训练的速度。
而在Decoder端,由于每个时间步的计算需要依赖上一个时间步的输出,因此无法进行完全的并行化。但是,可以通过一定的技巧提高Decoder的并行化效率,例如:
(3)延迟编码
在训练时,可以将目标序列分成多个子序列,并在不同的计算设备上同时进行解码。但是,在推理时,由于无法知道整个目标序列,因此需要使用延迟解码的方式,即在每个时间步上进行解码,并将上一个时间步的输出作为当前时间步的输入。
(4)Beam Search并行化
在推理时,可以使用Bean Search算法来生成目标序列,并通过将不同的Bean分配到不同计算设备上来实现推理的并行化。
因此,虽然Decoder端无法像Encoder端那样进行完全的并行化,但是可以通过一定的技巧来提高其并行化效率。
15、Transformer和RNN对比
(1)RNN
- 顺序执行,无法并行,效率低
- 输入序列过长时,无法处理上下文有效信息
(2)Transformer
位置编码+多头注意力,可以并行化运算,可以关联较远位置信息。
16、GPT温度T对softmax的改进操作
T越大,softmax的输出越均匀;T越小,softmax的输出分布越尖锐。通过调整温度T,来调整softmax输出内容的多样性。
17、为什么需要位置编码
Transformer不像ANN那样可以利用序列的先后顺序,所以需要添加位置编码,计算补充位置信息。
Transformer如何实现位置编码?
通过不同频率的正弦余弦对
为什么要同时使用正余弦函数
单独使用正弦或余弦函数不能很好地表示序列中相对位置的差异,因为它们只能提供位置在周期内的相对位置信息。
为了解决这个问题,我们同时使用正弦和余弦函数,并且在编码中使用不同的频率(或称为角速度),这样才能表示相对位置信息。
18、自注意力机制
(1)目的
在一个序列中建立各个位置之间的关联性,并且在处理序列时捕捉到不同位置之间的依赖关系。
(2)为什么QK的维度比词向量空间维度更小?
- 提高计算效率,使得模型在处理长序列时更加有效。
- 压缩模型信息量,提高对抽象特征的学习能力,模型可以更好地学习到抽象的语义特征,而不是过于依赖具体的词嵌入表示。这有助于提高模型对于不同语境下的泛化能力。(3)计算过程举例
- 假设有一个简单的句子“Thinking machines”,我们想要理解“machines”的上下文含义。在自注意力机制中,我们会对句子中的每个词进行编码,生成对应的Q,K,V向量。
- 查询(Q):代表我们想要理解的词(例如“machines”)的向量表示;
- 键(K):代表句子中所有词(包括Thinking和machines)的向量表示,用于与Q进行比较;
- 值(V):同样代表句子中所有词的向量表示,但是当计算出Q和K的相似度后,将用于加权求和,生成输出。
具体步骤:
①对于“machines”,计算它与句子中所有词的Q和K向量之间的相似度;
②是用这些相似度得分来加权句子中每个词的V向量;
③将加权的V向量求和,得到一个新的向量,这个向量现在编码了“machines”在给定上下文中的含义。
通过这种方式,自注意力机制允许“machines”这个词不仅考虑自身的含义,还考虑到与“Thinking”这个词之间的关系,从而在句子级别上获得更加丰富和准确的表示。
19、多头注意力机制
(1)成功原因
- 不专注于捕获某种特定格式
- 并行计算的加速,利用GPU对并行计算的加速来扩大模型规模,获得更好的效果。
(2)注意力头之间的数据切分是怎样的
数据被分割到多个注意力头中,以便每个注意力头都可以独立处理它。然而,需要注意的一点是,这只是逻辑上的分割,Q,K和V在物理上并未分割成单独的矩阵。单个数据矩阵分别用于查询、键和值,每个注意力头具有逻辑上独立的矩阵部分。类似的,也不存在单独的线性层,所有注意力头共享相同的线性层,但只是对数据矩阵的“自己”逻辑部分进行操作。
也就是说,代码实现层面是一起的,只是从逻辑上运算自己那一片的数据,实现了类似多头的操作。
20、注意力机制后处理:前馈神经网络层
多头注意力后,将所有注意力头拼接起来,因为前馈层的大小限制,所以将多头注意力层乘以一个权重矩阵,使其大小规整。
(1)作用
增强拟合能力,考虑注意力机制可能对复杂过程的拟合程度不够,通过增加两层网络来增强模型的拟合能力。具体来说,是通过relu激活函数增强非线性表达能力
(2)构造
两层全连接+中间一层relu激活函数
21、残差块
(1)为什么需要残差块
解决网络退化能力。
网络退化:在模型能够收敛的情况下,随着网络层数的增加,模型的性能(如准确率)并未得到提升。甚至深层网络效果不如浅层网络。
(2)残差块做法
残差连接允许模型的某一层的输出直接跳过一层或多层,作为后续层的输入。这种跳层连接的方式使得梯度可以更容易地反向传播,从而有助于训练深度网络。
在残差网络中,一个或多个层的输出(称为残差)会被添加到这些层的输入中,形成所谓的残差块。通过这种方式,网络能够学习输入和输出之间的残差表示,而不是直接学习从输入到输出的完整映射。这有助于网络更容易地优化和学习复杂的函数。
残差块通常采用两种连接方式:
1)恒等映射:y = x + F(x)
2)投影映射:y = x + F(x) * W,其中W是一个可学习的1x1卷积
22、归一化
(1)什么是归一化
在神经网络中,有时候输入的数据范围很大,有时候很小,这可能会导致模型训练的不稳定,难以收敛到最优解。归一化就像是调整食材的用量一样,它帮助我们把输入的数据调整到一个合适的范围内,以便更好地训练模型。
归一化的目的就是让模型更容易学习到数据的特征,而不受数据范围的影响。这样做可以加快训练的速度,提高模型的性能和泛化能力。
(2)LN&BN
- BN:在每一层的处理过程中,先把每批数据的平均值和方差调整到一致,再进行其他计算。这有助于网络更快地学习,并且对于不同批次的数据表现得更稳定。想象你在做烹饪,需要调整一大锅汤的味道,你可能会尝试先把整锅汤的味道调整到平均水平,然后再进行其他调整。
- LN:在每个样本数据的每个特征维度上进行调整,而不是整批数据。这种方法更适用于处理较小的数据集或是在RNN中使用。就像是你在烹饪的每一步都进行调整,而不是等整锅汤都煮好了后再调整。
四、损失函数设计与训练(预训练)
1、词向量表?词汇表?
- 词汇表:使用one-hot编码,每个词使用一个长度为N的向量表示,N表示词典的数量。这种方法能区分每个词,但是它有一个缺陷,one-hot向量两两之间乘积为0,不能通过向量的相似度推理出单词的相似度。
- 词向量表:将词汇表中的每个词映射到一个高维向量空间中的向量表。词向量表由预训练或在特定任务中训练的词嵌入模型生成,常见方法包括Word2Vec。
- 联系:
- 依赖关系:词向量表依赖词汇表,因为词向量表中的每个向量对应词汇表中的一个词。
- 应用流程:先构建词汇表,然后在此基础上训练或使用预训练词向量生成词向量表。
2、Word2Vec
假设我们有以下一段文本:
“猫喜欢吃鱼,狗喜欢吃骨头。猫和狗都是宠物。”
(1)构建词汇表
首先,我们对文本进行分词,得到词汇表:
[‘猫’, ‘喜欢’, ‘吃’, ‘鱼’, ‘狗’, ‘骨头’, ‘和’, ‘都是’, ‘宠物’]
(2)生成训练数据
接下来,我们生成CBOW或Skip-gram模型的训练数据。以Skip-gram为例,假设我们选择窗口大小为2,即每个中心词的上下文词包含前后各两个词。
对于句子“猫喜欢吃鱼”,Skip-gram模型的训练对如下:
(中心词, 上下文词):
(‘猫’, ‘喜欢’)
(‘猫’, ‘吃’)
(‘喜欢’, ‘猫’)
(‘喜欢’, ‘吃’)
(‘喜欢’, ‘鱼’)
(‘吃’, ‘猫’)
(‘吃’, ‘喜欢’)
(‘吃’, ‘鱼’)
(‘吃’, ‘骨头’)
(‘鱼’, ‘喜欢’)
(‘鱼’, ‘吃’)
(‘鱼’, ‘骨头’)
对于完整的文本,训练对包括:
(‘猫’, ‘喜欢’), (‘猫’, ‘吃’)
(‘喜欢’, ‘猫’), (‘喜欢’, ‘吃’), (‘喜欢’, ‘鱼’)
(‘吃’, ‘猫’), (‘吃’, ‘喜欢’), (‘吃’, ‘鱼’), (‘吃’, ‘骨头’)
(‘鱼’, ‘喜欢’), (‘鱼’, ‘吃’), (‘鱼’, ‘骨头’)
(‘狗’, ‘吃’), (‘狗’, ‘骨头’)
(‘骨头’, ‘狗’), (‘骨头’, ‘吃’)
(‘猫’, ‘和’), (‘狗’, ‘和’)
(‘和’, ‘猫’), (‘和’, ‘狗’), (‘和’, ‘都是’)
(‘都是’, ‘和’), (‘都是’, ‘宠物’)
(‘宠物’, ‘都是’)
(3)模型训练
我们使用这些训练对来训练Skip-gram模型。模型的目标是根据中心词预测上下文词。训练过程中,模型不断调整词向量,使得相似词在向量空间中更接近。
(4)生成词向量
训练完成后,我们得到每个词的词向量。例如,假设我们将每个词映射到一个3维向量空间:
猫: [0.5, 0.1, 0.3]
喜欢: [0.2, 0.4, 0.6]
吃: [0.3, 0.8, 0.7]
鱼: [0.9, 0.3, 0.2]
狗: [0.6, 0.5, 0.8]
骨头: [0.1, 0.7, 0.9]
和: [0.4, 0.2, 0.5]
都是: [0.3, 0.6, 0.4]
宠物: [0.7, 0.1, 0.3]
(5)词向量的应用
词向量可以用于各种NLP任务,如计算词语相似度、文本分类等。
例如,我们可以通过计算向量间的余弦相似度来比较“猫”和“狗”之间的相似度:
cosine_similarity(猫, 狗) = (0.5*0.6 + 0.1*0.5 + 0.3*0.8) / (sqrt(0.5^2+ 0.1^2 + 0.3^2) * sqrt(0.6^2+0.5^2 + 0.8^2))≈ 0.764
这个相似度值较高,表示“猫”和“狗”在向量空间中相对较近,反映了它们都是宠物这一语义关系。
3、如何进行损失函数计算
交叉熵损失(Cross-Entropy LOSS)
计算公式:
当预测结果与目标结果越接近时,交叉熵损失函数的值越小;反之,预测偏差越大,交叉熵损失函数的值就越大。
假设X1-X4是一条训练语料文本序列:
- step 1:对预测结果矩阵中的每个值取对数,即 p i j = l o g 2 ( x i j ) p_{ij}=log_2(x_{ij}) pij=log2(xij),这样就得到了一个对数矩阵;
- step 2:将这个对数矩阵与目标矩阵进行逐个位置的相乘(注意不是点积)。由于目标矩阵绝大多数都为0,可以预见到,计算结果的大部分位置也为0,只有和目标矩阵中同为1的位置乘积不为0。
- step 3:将所有乘积结果求和后再取负,得到这个预测结果矩阵的交叉熵损失总和。
- step 4:将这个总和除以token的个数,就得到了这条语料序列的平均交叉熵损失。
【注意】训练数据并非一个一个token进行,而是多个token组成一条序列,多条序列组成一个批次,一批一批送入transformer。将训练数据样本中每条序列都按上述步骤计算出平均交叉熵损失,然后再进行统一的平均数计算,得到整个模型本次预训练的平均交叉熵损失值loss。也就是说,预训练中的loss,一般是针对整个样本集来说,而非具体某条样本语料。
4、起始梯度的计算
即进行梯度下降法的第一个梯度。
用训练样本进行第一次推理后形成的预测结果矩阵,和目标结果矩阵进行逐位的减法运算后,所形成的的差值矩阵,就是起始梯度。
5、反向传播-链式求导法则
简单理解,可以把梯度计算的过程看成一个函数,输入包括上一层输出并传递过来的梯度矩阵和本层的参数矩阵,输出就是本层的梯度矩阵。
五、BERT
1、简述BERT的结构
BERT是google在2018年提出的一种基于transformer的预训练语言模型。bert的设计理念是通过大规模无标注语料库的预训练,使得模型能够学习到丰富的语言知识,并将其用于下游自然语言处理任务中。
BERT的最大特点是采用了双向编码器来处理自然语言,因此不同于传统的自然语言处理模型,可以双向预测上下文中的词语。BERT模型采用transformer作为编码器,具有多层的transformer encoder结构,使其能够处理长文本,并且在各种自然语言处理任务重取得了非常优秀的结果。
BERT的训练过程采用了两种预训练任务,即Masked Language Model和Next Sentence Prediction。Masked Language Model是通过将一些输入的单词随机遮盖掉,然后让模型来预测这些被遮盖的单词,从而使得模型能够学习到上下文相关的单词表示。而Next Sentence Prediction则是通过输入两个句子,并让模型来判断这两个句子是否是连续的,从而使得模型能够学习到句子间的关系。
BERT模型的预训练任务完成之后的作用,可以将其微调到各种下游自然语言处理任务中,如情感分析、命名实体识别、句子关系判断等等。
2、bert的embedding向量是什么
bert的embedding向量是一种将自然语言中的单词转化为向量表示的方法。在bert模型中,每个单词都被映射为一个固定长度的向量,这个向量的长度由模型的超参数决定,通常为768维或1024维。bert的embedding向量是在预训练阶段通过训练模型得到的,其中每个单词的embedding向量被训练出来,使得相似的单词在向量空间中距离更近,不相似的单词距离更远。
3、bert的三个embedding
bert的三个embedding分别是token embeddings、segment embeddings和position embeddings。这三个embedding的作用是将输入的文本转换为模型可以处理的向量表示。
- token embeddings是将输入的单词或词组映射为对应的向量,其中每个单词的向量从预训练的词表中获取。
- segment embeddings是用于区分不同的句子,它将不同的句子中的单词赋予不同的标识,以区分它们在不同句子中的位置。
- position embeddings用于编码单词在序列中的位置信息,以便模型能够学习到单词之间的相对距离和顺序关系。
三者包含的信息不同,相加不影响后期的解耦,若加权或乘除,后期很难解耦三者所表达的意义。
4、为什么BERT选择mask掉15%这个比例的词,可以是其他比例吗
在bert中选择mask掉15%的词是通过经验得到的。具体来说,这个15%的比例是在bert的开发过程中通过实验得出的最优比例,它能够在模型的训练中取得比较好的效果。在预训练的过程中,bert随机将输入序列中的一些单词mask掉,即将这些单词用特殊标记(如[MASK])替换掉,然后让模型去预测这些被mask掉的单词。这个预测任务可以让模型学习到单词之间的上下文关系和语义信息,从而提高模型的表现。虽然15%的比例在BERT中表现良好,但是在不同的任务和数据集上,最优的mask比例可能会有所不同。因此,在具体的应用场景中,可以根据实际情况调整mask比例以获得更好的效果。
5、BERT怎么进行mask的呢?
随机把一句话中15%的替换为以下内容:
- 80%被替换为[MASK];
- 10%被替换掉任意其他词;
- 10%原封不动
6、bert的mask相较于CBOW有什么异同
- mask的策略不同:在CBOW中,不会使用mask的策略。CBOW的训练是基于固定长度的滑动窗口,即将一段长度为m的文本序列划分成若干个长度为n的文本片段。对于每个文本片段,模型会将中心词周围的n个单词作为输入,然后预测中心词。相比之下,bert用的是mask策略,即将文本序列中随机抽取的一部分单词替换为特殊的[MASK]标记,然后预测这些被mask的单词。
- 输入信息不同:CBOW输入的是固定长度的文本片段,而bert的输入是整个文本序列。在CBOW中,由于每个文本片段长度固定,因此无法捕捉到长距离的语义信息;而在bert中,由于输入的是整个序列,因此可以捕捉到更长的语义信息,从而提高模型的表现。
- 模型的复杂度不同:bert相比于CBOW更复杂。bert用到了一个双向transformer模型,其中包含12(或24)个transformer层,每个层都包含了多头自注意力机制和前馈神经网络等多个子层。相比之下,CBOW只使用了一个浅层神经网络。
7、word2vec到BERT改进了什么
- 模型的深度和复杂度:bert比word2vec更加深更加复杂。其中包含12(或24)个transformer层,每个层都包含了多头自注意力机制和前馈神经网络等多个子层,从而可以处理更复杂的文本信息。
- 上下文信息的利用:word2vec只考虑了单词的局部上下文信息,而bert使用了mask策略来随机屏蔽一些单词并预测它们,从而可以同时考虑全局和局部的上下文信息。
- 多任务学习:bert使用了多任务学习的方法,在训练时同时进行了掩码语言建模和下游任务的学习,从而可以在不同任务中共享学习到的知识,提高模型的泛化能力和效果。
- pre-training和fine-tuning两阶段的训练方式:在pre-training阶段,bert在大规模文本语料库上进行预训练,学习语言的通用知识;在fine-tuning阶段,bert将预训练的模型微调到特定的下游任务中,以获得更好的性能和效果。
8、使用bert为什么最多添加512个词
bert模型输入的限制是因为模型架构的设计和计算资源的限制。为了在输入序列中引入位置信息,bert在输入序列中增加了特殊的[CLS]和[SEP]标记,其中[CLS]标记用于表示整个序列的分类信息,[SEP]表示用于区分不同的句子或文本片段。
9、有什么方法可以解决BERT输入长度的限制
- 截断输入序列:可以选择截断序列的开始或结尾部分,或者根据序列中的关键信息来选择截断位置。但需注意,截断过多可能会导致模型性能下降;
- 分段式输入:可以将长序列划分为多个段落,每个段落都是bert模型的输入。在输入序列中,每个段落之间使用[SEP]标记分隔。这种方式可以有效地解决输入长度的限制,但需要根据任务需求设计合适的分段策略。
10、BERT中的[CLS]有什么用
[CLS]标记可看作是整个输入序列的一个摘要或汇总,它可以代表整个输入序列的语义信息。因为,[CLS]一开始没有任何意义,自注意力机制使其关注了到了整个序列的信息。
11、什么任务适合bert,什么不适合
- 适合:文本分类、问答系统、命名实体识别、语言生成;
- 不适合:不需要或不侧重于理解自然语言中的语义信息,或者是因为数据量不足或任务本身的限制。
12、bert的优缺点
(1)优点
- 预训练:bert通过大规模无监督语料预训练,可以学习到丰富的语言知识,为下游任务提供更好的特征表示;
- 可迁移性:bert在多个下游任务中均取得了优异的性能,说明它的特征表示具有很强的可迁移性;
- 长文本处理:bert采用了transformer结构,可以较好地处理长文本,而且可以并行计算,训练速度更快;
- 上下文敏感:bert考虑了上下文信息,可以更好地处理多义词等语言现象,提高了自然语言处理的效果;
(2)缺点 - 计算资源消耗大:bert模型较大,需要较高的计算资源,训练时间和成本较高;
- 数据量需求大:bert需要大量的无监督语料进行预训练,数据量需求较大。
- 长度限制:BERT输入长度有限制,只能输入512个词,且只能处理两个句子的关系。
- 预测效率低:BERT模型较大,需要较长的推理时间,不适合实时应用场景。
13、elmo、GPT和bert三者区别
- 模型结构:Elmo使用的是双向LSTM模型,GPT使用的是单向Transformer模型,而BERT使用的是双向Transformer模型。BERT是目前最先进的模型,它在模型结构上做了一些改进,如使用了双向Transformer模型和Masked Language Modeling和Next Sentence Prediction任务。
- 预训练任务:Elmo使用的是单向和双向语言模型,GPT使用的是单向语言模型,BERT使用的是Masked Language Modeling和Next Sentence Prediction任务。其中,BERT使用的Masked Language Modeling任务与传统的预测下一个词的语言模型不同,它要求模型从输入文本中掩盖一部分词汇,让模型学会在输入缺失的情况下仍然能够准确预测缺失部分的单词。
- 文本编码:Elmo将词向量和上下文信息分别进行编码,得到一个表示每个单词的向量和一个表示整个句子的向量。GPT和BERT都采用了基于Transformer的模型,可以将整个句子作为输入,同时考虑单词在上下文中的位置信息和词与词之间的交互作用。
- 应用场景:Elmo适用于对上下文敏感的自然语言处理任务,如命名实体识别、关键词提取等。GPT适用于自然语言生成和对话系统等任务,BERT适用于各种自然语言处理任务,包括文本分类、问答系统、命名实体识别等。
14、为什么 BERT 比 ELMo 效果好?
- 双向Transformer模型:BERT使用了双向Transformer模型,可以同时考虑上下文中的左侧和右侧信息,而ELMo只使用了双向LSTM模型,只能考虑左侧或右侧的上下文信息。
- 预训练任务:BERT使用了Masked Language Modeling和Next Sentence Prediction两个任务进行预训练。Masked Language Modeling任务要求模型从输入文本中掩盖一部分词汇,让模型学会在输入缺失的情况下仍然能够准确预测缺失部分的单词。Next Sentence Prediction任务则要求模型判断两个句子是否相邻,以提高模型对上下文信息的理解能力。而ELMo则只使用了单向和双向的语言模型进行预训练。
- Fine-tuning的方式:BERT在微调阶段引入了一个分类任务,可以根据具体任务要求,将预训练的模型微调到特定任务上。同时BERT在预处理阶段采用了WordPiece技术,可以将单词分成更小的子词,进一步提高模型的泛化能力。而ELMo则是将预训练的向量表示作为输入特征进行下游任务的微调。
15、BERT 的结构可以用LSTM替换吗?
BERT的结构不能简单地用LSTM替换。BERT模型采用的是Transformer结构,而LSTM则是一种递归神经网络结构,二者在结构和运算方式上有很大的不同。
Transformer结构的优点在于其能够并行计算,使得训练速度更快,并且可以处理更长的文本序列。而LSTM则需要按照时间步序列逐步计算,训练速度较慢,并且无法很好地处理长文本序列。
另外,BERT模型中引入了预训练的机制,可以利用大规模无标注数据进行预训练,学习到更丰富的语言知识,使其在下游任务中表现更加出色。而LSTM等传统的神经网络结构则需要更多标注数据进行训练,而且其表示能力也有限。
五、T5
1、介绍
T5(Text-to-Text Transfer Transformer)模型结构仍是一个由transformer层堆叠而成的encoder-decoder结构,它将各种NLP任务都视为Text-to-Text任务,即输入是text,输出也是text,有次可以方便地评估在阅读理解、摘要生成、文本分类等一系列任务上,不同的模型结构、预训练目标函数、无标签数据集等的影响。
T5与原生的Transformer结构非常类似,区别在于:
(1)作者采用了一种简化版的Layer Normalization,去掉了Layer Norm的bias,将layer norm放在残差连接外面。
(2)位置编码:T5采用了一种简化版的相对位置编码,即每个位置编码都是一个标量,被加到logits上用于计算注意力全中。各层共享位置编码,但是在同一层内,不同注意力头的位置编码都是独立学习的。一定数量的位置embedding,每一个对应一个可能的 key-query 位置差。作者学习了32个Embedding,至多适用于长度为128的位置差,超过位置差的位置编码都使用相同的Embedding。
六、GPT-3
GPT-3是一种基于深度学习原理的语言预测模型。它是由OpenAI开发的,可以从互联网数据中生成任何类型的文本。它只需要一小段文本作为输入,就可以生成大量的准确和复杂的机器生成文本。
GPT-3是基于Transformer模型的,使用了仅有解码器的自回归架构。它使用下一个单词预测目标进行训练。GPT-3有8个不同的模型,参数从1.25亿到1750亿不等。最大的GPT-3模型有1750亿参数,是有史以来参数最多的神经网络模型。
GPT-3在许多任务上展示了强大的零样本和少样本的能力。它可以从非常少的数据中学习,不需要进行微调¹²。GPT-3在文本生成、机器翻译和数据有限的领域方面取得了实质性进展,但在阅读理解、自然语言推理和常识推理等任务上表现较差。
七、参数高效微调(PEFT)
1、增加额外参数
(1)Adapter Tuning
在预训练模型每层中插入用于下游任务的参数,在微调时将模型主体冻结,仅训练特定任务的参数,从而减少训练时的算力开销。
设计了Adapter结构,并将其嵌入transformer的结构中,针对每一个transformer层。增加了两个adapter结构(分别是多头注意力的投影之后和第二个前馈神经网络之后),在训练时,固定原来与训练模型的参数不变,只对新增的adapter结构和layer norm层微调。
(2)Prompt Tuning
给预训练模型的一些线索和提示,让它更好地理解我们提出的问题.
比如最常见的文本分类问题,输入:'I love this movie.'的话,模型会输出positive或者negative。然而,对于本身是做文本生成的模型,它是不懂得分类的,但我们可以对原始输入进行适当地转换,构造成适合它处理的方式,让它输出 ‘positive’ / ‘negative’ 这些词,从而应用到文本分类这种下游任务。
具体来说,我们可以将 ‘I love this movie.’构造成:
‘I love this movie. Overall, it was a _____ movie.’
I love this movie用于填入原始的输入文本,后面的实下划线则用于给模型预测答案文本,至于其余部分则作为提供给模型的线索。
于是,这个做文本生成的模型就可能会预测出一些诸如 ‘fantastic’, ‘boring’… 等等这些词汇作为答案。最终,我们再对这个模型的预测结果映射到所需的答案空间,比如:
fantastic -> positive;
boring -> negative
这么一来,通过 prompt 的方式,就可以让原本做文本生成的模型也可以处理文本分类任务了。
(3)p-tuning
①背景
传统的prompt技术采用离散的prompt,如“[x]的首都是[y]”。然而,这些离散prompt的微小变化,例如将“首都”改为“首都城市”,都会导致模型性能的显著波动,因此如何设计稳定且高效的prompt,是prompt技术面临的关键挑战。
②技术原理
为了解决离散prompt不稳定问题,p-tuning提出了在离散prompt之间插入连续prompt embedding。这些连续prompt embedding 是可训练的,可以学习到有助于稳定和提升性能的表示。p-tuning的核心思想是利用连续prompt embedding 增强语言模型的表达能力。在训练过程中,连续prompt embedding与离散prompt串联后输入语言模型,通过反向传播更新连续prompt嵌入,使其学习到有助于稳定和提升性能的表示。
计算流程:
- 基于任务场景设计多个模板,模板中包含占位符(virtual token),用来插入输入和需要预测的标签,比如“这个电影是[mask]的,因为[输入文本]”
- 用一个可训练的encoder将模板中的输入和可学习的prompt映射到语言模型隐藏层;
- 将固定的离散prompt和可学习连续prompt的隐藏层串联,让后输入语言模型进行预测;
- 通过反向传播更新virtual token,使其学习到有助于稳定和提升性能的表示;
- 重复上述步骤,直至virtual token收敛;
- 在测试时,使用最优化的virtual token串联离散prompt,输入语言模型进行预测。
(4)p-tuning v2
选择性使用重参数化的编码器,重参数化(structural re-parameterization)指的是首先构造一系列结构(一般用于训练),并将其参数等价转换为另一组参数(一般用于推理),从而将这一系列结构等价转换为另一系列结构。我们可以回忆一下lora的结构,在已经预训练好的模型结构旁加上A和B两个结构,因此lora就属于重参数化的一种方法。相应的,prefix tuning中的mlp,p-tuning中的lstm也是同样的道理,然后对于自然语言理解任务呢,这种技术的好处还得取决于任务和数据集。比如对于RTE数据集,它是将一系列年度文本蕴含挑战赛的数据集进行整合而来的,主要任务就是判断句子对是否蕴含,为二分类任务,那么mlp的重参数化带来了比嵌入更稳定的改善;但是对于BoolQ数据集,一个阅读理解数据集,每个实例包括一个问题、一个段落和一个为yes或no的答案,重参数化没有任何效果;甚至对于coNLL12数据集,一个用于命名实体识别和关系抽取的数据集,重参数化会使得结果更糟。因此考虑到重参数化在NLU任务的不稳定性,p-tuning v2决定根据具体的任务来选择性地使用重参数化。其实网上很多资料直接说的是移除重参数化,但是我们可以看到p-tuning v2这张图,重参数化是可选的,而不是像p-tuning那样对于所有任务都是必须的;而且在论文原文中,作者也只是提到了重参数化对于特定任务的效果并没有那么好,并没有提到“移除”的字眼。
其次,不同的任务采用不同的提示长度,一般来说,简单的分类任务偏向于更短的提示(少于20个);硬序列标记任务偏向于更长的提示(大约100个)。
引入多任务学习,先在多任务的Prompt上进行预训练,然后再适配下游任务,实验证明多任务学习可以作为p-tuning v2的有益补充,在大部分时候效果甚至比全参数微调还要好。
最后一个优化是回归传统的分类标签范式,而不再使用verbalizer。在比如prompt tuning中会用到verbalizer这种方式,成为标签词映射,我们可以看到上面这张图,我们只对部分词感兴趣,所以需要一个映射关系,比如如果[MASK]预测的词是great,那么verbalizer就会将great映射到positive类,如果是terrible则映射到negative类。虽然verbalizer能够将one-hot类标签变成有意义的词,但是这也限制了模型在不同任务上的应用,比如现在我们只能完成文本分类任务,而无法完成问答任务,因此作者决定使用传统的分类标签范式,也就是我们之前在bert模型提到的cls token,它完全可以应用于分类、问答、实体命名识别任务中,大大增强了模型的通用性。
2、选择一部分参数更新
(1)BitFit
训练时只更新Bias的参数。
对于transformer模型而言,冻结大部分transformer-encoder参数,只更新bias参数和特定任务的分类层参数,涉及到:①attention模块中计算q,k,v;
②合并多个attention结果时;
③MLP层中的bias;
④layer normalization层的bias参数
3、重参数化
(1)LORA
通过低秩分解来模拟参数的该变量。
在设计到矩阵相乘的模块,在原始的预训练语言模型旁增加一个新的通路,通过前后两个矩阵A,B相乘,第一个矩阵A负责降维,第二个矩阵B负责升维。
在下游任务训练时,固定模型的其他参数,只优化新增的两个矩阵的权重参数,将预训练语言模型形成的通路两部分的结果加起来作为最终的结果。
lora的矩阵怎么初始化?
矩阵B被初始化为0,矩阵A正常高斯初始化。如果AB都初始化为0,那么缺点和深度网络全0初始化一样,很容易导致梯度消失。如果AB全部高斯初始化,那么在网络训练刚开始就会有几率得到一个过大的偏移值,从而引入太多噪声,导致难以收敛。因此,一部分初始化为0,一部分正常初始化是为了在训练开始时维持网络的原有输出,即初始偏移为0,但同时也保证在真正开始学习后能够更好地收敛。