知识点-深度学习

深度学习相关知识点。

会一直持续更新。

人工智能算法面试大总结-总目录_人工智能面经-CSDN博客

基础篇

1. 正定矩阵和半正定矩阵判断

​ 判断矩阵是不是正定矩阵首先需要看主对角线是不是全大于0,如果对角线不是全大于0或者全小于0则这个矩阵一定是不正定矩阵。

​ 如果主对角线全大于零,就观察其顺序主子式,如果顺序主子式全大于0,那么这个矩阵就是正定的,如果所有主子式全大于等于0,那么这个矩阵就是半正定的。

2. L0、L1和L2范数

L0范数是指向量中非0的元素的个数。

L1范数是指向量中各个元素绝对值之和。其作用也是可以提高模型参数的稀疏性,效果没有L0范数好,但是更容易求解,更常用。

L2范数是指向量各元素的平方和然后求平方根。其作用是减小模型所有参数大小,可以防止模型过拟合,也很常用。

除了L1,L2范数之外,L1,L2损失函数也很常见。

L1 损失函数也叫平均绝对值误差(MAE)

优点:对异常的离群点有更好的鲁棒性

缺点:导数不连续,导致求解困难。

L1

L2 损失函数也叫均方损失函数(MSE)。

优点:使训练更容易,因为它的梯度随着预测值接近真实值而不断减小,不会轻易错过极值点。

缺点:收敛速度比 L1 慢,因为梯度会随着预测值接近真实值而不断减小,且对异常数据比 L1更敏感。

L2

除此之外,还有L1正则化与L2正则化,我们在下面提到……。

**3.**特征值和特征向量

​ 如果把矩阵看作是运动,那么特征值就是运动的速度,特征向量就是运动的方向。

​ 特征向量在一个矩阵的作用下作伸缩运动,伸缩的幅度由特征值确定。特征值大于1,所有属于此特征值的特征向量变长;特征值大于0小于1,特征向量缩短;特征值小于0,特征向量缩过了界,反方向到原点那边去了。

4.条件概率和贝叶斯公式

条件概率描述的就是在给定事件B发生的情况下,事件A发生的概率,我们把它记作P(A|B)。一般说到条件概率概念的时候,事件A和事件B都是同一实验条件下的不同的结果集合,事件A和事件B一般是有交集的,如果A和B互斥,则条件概率为0。
$$
P(A|B) = \frac{P(B|A)P(A)}{P(B)}
$$
贝叶斯公式就是对于一个已知事件B发生了,通过考虑到所有的可能情况,探究某一原因导致这一结果发生的概率。贝叶斯公式全盘考虑了这一原因占总原因的比例。

贝叶斯定理,通过已知的概率计算未知的概率。贝叶斯公式是由结果去反推原因条件,计算后验概率。贝叶斯:条件概率乘先验概率除以全概率得到后验概率。

5. 高斯分布和拉普拉斯分布以及正态分布

由中心极限定理知,很多独立随机变量均近似服从正态分布,所以现实中很多复杂系统都可以被建模成正态分布的噪声。因此即使在缺乏实数上分布的先验知识,默认选择高斯分布总是合适的。

拉普拉斯分布是一种连续的概率分布,出现极端大的值的概率,要远远大于正态分布。

6.线性回归和逻辑回归的区别

  1. 线性回归用于预测连续值,但不能解决分类问题。逻辑回归可用于解决分类问题。

  2. 线性回归利用拟合函数,样本输出值是连续值;逻辑回归利用预测函数,样本输出值只有0和1。

  3. 线性回归的参数计算方法是最小二乘法,逻辑回归的参数计算方法是最大似然估计。

(最大似然估计计算使数据出现可能性最大的参数,最小二乘法是计算误差损失)

7.常用的损失函数、分类和回归

损失函数用于度量模型的预测值与真实值的不一致程度。

常用损失函数:

  1. 0-1损失:预测值和目标值不相等为1, 否则为0。

0-1损失函数直接对应分类判断错误的个数,但是它是一个非凸函数,不太适用。感知机就是用的这种损失函数,函数相等这个条件太过严格,因此可以放宽条件,更加适用。

  1. 绝对值损失函数:计算预测值与目标值的差的绝对值。

  2. log对数损失函数:非常好的表征概率分布,适用很多问题特别是多分类问题,如果需要知道结果属于每个类别的置信度,利用log对数损失函数非常适合。

但是log对数损失函数健壮性不强,对噪声比较敏感。逻辑回归的损失函数就是log对数损失函数。

  1. hinge损失函数:表示如果被分类正确,损失为0,否则损失就为1-yf(x)。支持向量机就是使用这个损失函数。

hinge损失函数使分类器可以更专注于整体的误差。 健壮性相对较高,对异常点、噪声不敏感。

  1. L1 L2 损失函数。

L1 损失函数也叫平均绝对值误差(MAE)

优点:对异常的离群点有更好的鲁棒性

缺点:导数不连续,导致求解困难。

L1

L2 损失函数也叫均方损失函数(MSE)。

优点:使训练更容易,因为它的梯度随着预测值接近真实值而不断减小,不会轻易错过极值点。

缺点:收敛速度比 L1 慢,因为梯度会随着预测值接近真实值而不断减小,且对异常数据比 L1更敏感。

L2

8.激活函数作用?常见的激活函数有哪些?激活函数有哪些特点?如何选择激活函数?

激活函数作用:在神经网络中引入非线性因素,使模型能够学习和表示复杂的非线性关系。如果没有激活函数,网络只能表示线性变换,无法处理复杂数据。

常见激活函数:

Sigmoid 激活函数: $y=\frac{1}{1+e^{-x}}$

img

将取值为 (−∞,+∞) 的数映射到(0,1)之间

x非常大或非常小时,导数趋近于零,也就是权重的梯度趋近于零,即梯度消失。

Tanh激活函数:$y=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}$

img

x非常大或非常小时,导数也是趋近于零,梯度很小,权重更新非常缓慢,即梯度消失。

Relu激活函数:$$ y=\left{ \begin{aligned} x,x>0 \ 0,x<0 \end{aligned} \right. $$

输入为正数时,不存在梯度消失问题。且计算速度要快很多。ReLU函数只有线性关系,不管是前向传播还是反向传播,都比 sigmoid 和 tanh 要快很多。但x<0时,梯度为0,会产生梯度消失问题。

Leak Relu激活函数: $$ y=\left{ \begin{aligned} x,x>0 \ ax,x<0 \end{aligned} \right. $$

其中,0<a<1。

LeakReLU函数图像

LeakReLU激活函数解决了ReLU函数在输入为负的情况下产生的梯度消失问题。

SiLU激活函数:即 $f(x)=x*sigmoid(x)$

$y=\frac{x}{1+e^{-x}}$

SiLU函数图像

SiLU函数在接近零时具有更平滑的曲线,并且由于其使用了sigmoid函数,可以使网络的输出范围在0和1之间。这使得SiLU在一些应用中比ReLU表现更好。

激活函数有哪些特点:

  1. ⾮线性: 当激活函数是⾮线性的,⼀个两层的神经⽹络就可以基本上逼近所有的函数。但如果激活函数是恒等激活函数的时候,即f(x)=x,就不满⾜这个性质,⽽且如果 MLP 使⽤的是恒等激活函数,那么其实整个⽹络跟单层神经⽹络是等价的;

  2. 可微性:当优化⽅法是基于梯度的时候,就体现了可微性;

  3. 单调性:当激活函数是单调的时候,单层⽹络能够保证是凸函数;f(x)≈x :当激活函数满⾜这个性质的时候,如果参数的初始化是随机的较⼩值,那么神经⽹络的训练将会很⾼效;如果不满⾜这个性质,那么就需要详细地去设置初始值;

  4. 输出值的范围:当激活函数输出值是有限的时候,基于梯度的优化⽅法会更加稳定,因为特征的表⽰受有限权值的影响更显著;当激活函数的输出是⽆限的时候,模型的训练会更加⾼效,不过在这种情况⼩,⼀般需要更⼩的 Learning Rate。

如何选择激活函数:

​ 选择⼀个适合的激活函数需要考虑很多因素,通常的做法是,如果不确定哪⼀个激活函 数效果更好,可以把它们都试试,然后在验证集或者测试集上进⾏评价。然后看哪⼀种表现的更好,就去使⽤它。

​ 如果输出是 0、1 值,二分类问题,则输出层选择 sigmoid 函数,然后其它的所有单元都选择 Relu 函数。

​ 如果在隐藏层上不确定使⽤哪个激活函数,那么通常会使⽤ Relu 激活函数。有时,也会使⽤tanh 激活函数,但 Relu 的⼀个优点是:当是负值的时候,导数等于 0。

​ sigmoid 激活函数:除了输出层是⼀个⼆分类问题基本不会⽤它。

​ tanh 激活函数:tanh 是⾮常优秀的,⼏乎适合所有场合。

9.深度神经网络训练问题

  1. 梯度消失:指通过隐藏层从后向前看,梯度会变的越来越小,说明前层的学习会显著慢于后层的学习,所以学习会卡住,除非梯度变大。 梯度消失的原因受到多种因素影响,例如学习率的⼤小,⽹络参数的初始化,激活函数的边 缘效应等。

在深层神经⽹络中,每⼀个神经元计算得到的梯度都会传递给前⼀层,较浅层的神 经元接收到的梯度受到之前所有层梯度的影响。如果计算得到的梯度值⾮常小,随着层数增多,求出的梯度更新信息将会以指数形式衰减,就会发⽣梯度消失。

解决方法:选择特殊的激活函数,如ReLu函数;对网络权重进行正则化来限制过拟合;标准化操作Batch Normalization等

  1. 梯度爆炸:在深度⽹络或循环神经⽹络等⽹络结构中,梯度可在⽹络更新的过程中不断累积,变成⾮常⼤的梯度,导致⽹络权重值的⼤幅更新,使得⽹络不稳定;在极端情况下,权重值甚⾄会溢出,变为NaN值,再也⽆法更新。

  2. 权重矩阵的退化导致模型的有效⾃由度减少:参数空间中学习的退化速度减慢,导致减少了模型的有效维数,⽹络的可⽤⾃由度对学习中梯度范数的贡献不均衡,随着相乘矩阵的数量,即⽹络深度,的增加,矩阵的乘积变得越来越退化。在有硬饱和边界的⾮线性⽹络中比如 ReLU ⽹络,随着深度增加,退化过程会变得越来越快。

10.反向传播的过程以及链式法则

反向传播就是根据输出的结果与正确结果之间的之间的误差不断调整参数。

假如当我正在训练一个图片分类网络时,输入一张图片逐层向前计算之后,网络会给出它属于某一类事物的概率,由于每一个神经网络的初始参数是随机赋予的,大部分时间答案都不尽如人意,这时可以根据网络输出与正确答案之间的差距,从最后一层开始逐层向前调整神经网络的参数,如果误差值为负,就提升权重,反之就降低权重,调整的程度受一定的比率即学习率的制约,就像一个旋钮控制参数调整程度的高低,在一次次输入数据和返向调整中,网络就能逐渐给出不错的输出。

由于强大的调整能力,反向传播容易过拟合。我们可以采用提前停止策略,将数据划分为一定数量的训练集和验证集,用训练集调整参数,用验证集估算误差,如果训练集误差降低的同时验证集误差不断升高,即代表网络出现过拟合情况,此时应当结束训练。

神经网络的学习本质,就是找到网络中神经元之间的最佳连接权值。BP算法的反向传播部分充分利用了“链式求导”法则。事实上,每个网络层,隐含层和输出层,都可以视为一个拟合的函数,那么对于多层神经网络而言,它的数学本质,就等同于一个多层的复合函数: 它实现了从向量x到向量y的映射,这个复合函数的层数,就等于网络的“深度”。同一条路径上所有边相乘,然后将最终所有抵达的路径加和

11.卷积核大小选取

​ 在早期的卷积神经⽹络中,⽤到了⼀些较⼤的卷积核,受限于当时的计算能⼒和模型结构的设计,⽆法将⽹络叠加得很深,因此卷积⽹络中的卷积 层需要设置较⼤的卷积核以获取更⼤的感受域。但是这种⼤卷积核反⽽会导致计算量⼤幅增加,不利于训练更深层的模型,相应的计算性能也会降低。

​ 后来的卷积神经⽹络,比如GoogleNet,发现通过堆叠2个3*3 卷积核可以获得与 5*5卷积核相同的感受视野,同时参数量会更少( 3*3*2+1<5*5*1+1 ),3*3卷积核被⼴泛应⽤在许多卷积神经⽹络中。因此可以认为,在⼤多数情况下通过堆叠较⼩的卷积核⽐直接采⽤单个更⼤的卷积核会更加有效

​ 但是,这并不是表⽰更⼤的卷积核就没有作⽤,在某些领域应⽤卷积神经⽹络时仍然可以采⽤较⼤的卷积核。譬如在⾃然语⾔处理领域,由于⽂本内容不像图像数据可以对特征进⾏很深层的抽象,往往在该领域的特征提取只需要较浅层的神经⽹络即可。在将卷积神经⽹络应⽤在⾃然语⾔处理领域时,通常都是较为浅层的卷积层组成,但是⽂本特征有时⼜需要有较⼴的感受域让模型能够组合更多的特征(如词组和字符),此时直接采⽤较⼤的卷积核将是更好的选择。

​ 所以卷积核的⼤⼩并没有绝对的优劣,需要视具体的应⽤场景⽽定,但是极⼤和极⼩的卷积核都是不合适的单独的1*1的极⼩卷积核只能⽤作分离卷积⽽不能对输⼊的原始特征进⾏有效的组合,极⼤的卷积核通常会组合过多的⽆意义特征从⽽浪费了⼤量的计算资源。

​ 1*1卷积核的作用:卷积核的作用在于特征的抽取,越是大的卷积核尺寸就意味着更大的感受野,当然随之而来的是更多的参数。采用1*1卷积核来减少模型的参数量。在原始版本的Inception模块中,由于每⼀层⽹络采⽤了更多的卷积核,⼤⼤增加了模型的参数量。此时在每⼀个较⼤卷积核的卷积层前引⼊1*1卷积核,可以通过分离通道与宽⾼卷积来减少模型参数量。1*1卷积核的作⽤主要为以下两点: 实现信息的跨通道交互和整合; 对卷积核通道数进⾏降维和升维,减⼩参数量

12.batch_size的选取

batch_size太小:

  1. 耗时长,训练效率低。
    假设batch_size=1,每次用一个数据进行训练,如果数据总量很多时(假设有十万条数据),就需要向模型投十万次数据,完整训练完一遍数据需要很长的时问,训练效率很低;
  2. 训练数据就会非常难收敛,从而导致欠拟合。
    假设batch_size=1,每次用一个数据进行训练,则由于个体的差异性或者异常值的影响,模型的参数变化也会很大,每一层的梯度都具有很高的随机性,而且需要耗费了大量的时间,从而导致模型非常难收敛。

batch_size太大:

  1. 减少训练时间的同时所需内存容量增加

  2. 大的 batch_size 可提高稳定性,使得模型训练曲线会更加平滑。在微调的时候,大的 batch_size 可能会取得更好的结果。但同时可能导致模型泛化能力下降,每次更新参数都是相同的样本,下降方向基本确定,导致模型的泛化性能下降。

​ 应当选择一个适中的batch_size 。当适当增加batch_size值时,内存利用率提高了,跑完⼀次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进⼀步加快。 而且在⼀定范围内,⼀般来说 Batch_size 越大,其确定的下降方向越准,引起训练震荡越小。 但也不能盲目增大,否则虽然内存利用率提高了,但是内存容量可能撑不住了。跑完一次 epoch(全数据集)所需的迭代次数减少,要想达到相同的精度,其所花费的时间大大增加了,从而对参数的修正也就显得更加缓慢。

13.解决过拟合与欠拟合问题

(1) 解决欠拟合问题:

  1. 模型复杂化,为模型增加更多的特征,添加其他特征项:有时候特征项不够会导致模型欠拟合

  2. 添加多项式特征:模型添加二项式或者三项式可以使模型的泛化能力更强,比如说FM模型,就是线性模型增加了二阶多项式,保证了模型一定的拟合程度。

  3. 调整参数与超参数

  4. 减少正则化系数:正则化可以防止过拟合,因为现在模型欠拟合,所以可以采取减少正则化系数方法防止欠拟合。

(2) 解决过拟合问题:

过拟合有很多种解决方法,但是一般要跟据实际情况实际模型进行选择

  1. 有时候由于数据不纯可能会导致过拟合,所以当遇到这种情况时需要对数据进行重新清洗。

  2. 过拟合很多时候都是由于训练样本数量未达到一定数量。所以面对这种情况我们可以通过增加训练样本数量来解决过拟合问题。

  3. 也可以通过增加正则化系数解决过拟合问题。

  4. 调整参数和超参数

  5. dropout方法

  6. 在决策树结构中,也可以通过剪枝的方式解决过拟合问题

关于正则化系数:正则化通过降低模型的复杂性,缓解过拟合。过拟合发生的情况,拟合函数的系数往往非常大。

14.Batch Normalization

首先输入数值集合B,可训练参数γ,β。计算集合B的均值和方差,之后将B的均值和方差变换成0和1,最后将B中的元素乘γ再加β,输出结果。γ,β是可训练参数,参与整个网络的BP。

归一化可以将数据规整到统一区间,减少数据的发散程度,降低网络的学习难度。BN的精髓在于归一化之后,使用γ,β作为还原参数,在一定程度上保留原数据的分布。

15.梯度消失与梯度爆炸

在梯度下降中, 随着算法反向的反馈, 梯度会越来越小,最终没有变化,此时并没有收敛到比好的解

产生的原因有:一是在深层网络中,二是采用了不合适的损失函数

这就是梯度消失的问题。梯度消失,简单点来说,就是整个曲线太平了。曲线太平了就意味这求导后的值越来越接近0。由于梯度消失现象,会导致靠近输入层的隐藏层权值更新缓慢或者更新停滞。这就导致在训练时,只等价于后面几层的浅层网络的学习。

梯度爆炸一般出现在深层网络权值初始化值太大的情况下。在深层神经网络或循环神经网络中,误差的梯度可在更新中累积相乘。如果网络层之间的梯度值大于 1.0,那么重复相乘会导致梯度呈指数级增长,梯度变的非常大,然后导致网络权重的大幅更新,并因此使网络变得不稳定。

梯度爆炸会伴随一些细微的信号,如:①模型不稳定,导致更新过程中的损失出现显著变化;②训练过程中,在极端情况下,权重的值变得非常大,以至于溢出,导致模型损失变成 NaN等等。

梯度消失和梯度爆炸问题都是因为网络太深,网络权值更新不稳定造成的,本质上是因为梯度反向

解决梯度下降问题常见的方案:

1)权重正则化,通过对网络权重做正则来限制过拟合。常见的是L1正则化与L2正则化

2)更改激活函数,现在神经网络中,除了最后二分类问题的最后一层会用sigmoid之外,每一层的激活函数一般都是用ReLU。

3)Batch Normalization,通过对每一层的输出规范为均值和方差一致的方法,消除了权重参数带来的影响,进而解决梯度消失和爆炸的问题,或者可以理解为BN将输出从饱和区拉倒了非饱和区。

4)残差 shortcut,跨层连接结构,这样的结构在反向传播中具有很大的好处,可以避免梯度消失

16.各种优化器

SGD的基本思想是,通过梯度下降的方法,不断调整模型的参数,使模型的损失函数最小化。SGD的优点是实现简单、效率高,缺点是收敛速度慢、容易陷入局部最小值

在PyTorch中,可以使用torch.optim.SGD类实现SGD。

Adam是一种近似于随机梯度下降的优化器,用于优化模型的参数。Adam的基本思想是,通过维护模型的梯度和梯度平方的一阶动量和二阶动量,来调整模型的参数。Adam的优点是计算效率高,收敛速度快,缺点是需要调整超参数

超参数:Adam算法有几个需要手动设置的超参数,如学习率(learning rate)、β1和β2(用于计算梯度的一阶和二阶矩估计的衰减率)以及ϵ(用于数值稳定性的小值)。不恰当的超参数设置可能导致性能下降,例如过大的学习率可能导致震荡,而过小的学习率可能导致收敛缓慢。

比较:

对于某些数据集和模型,SGD的简单性和随机性可能表现得更好,而Adam的自适应学习率可能在这些情况下过于复杂,导致不稳定的训练过程。

Adam算法使用梯度的二阶矩估计,可能需要更多的内存来存储历史梯度信息。当训练数据集非常大时,这可能会导致内存限制或计算资源不足的问题。

过拟合:Adam算法的自适应学习率可能在训练初期过快地收敛,导致在某些情况下更容易过拟合训练数据。

17.正则化

正则化(regularization)用于控制模型的复杂度,防止模型在训练数据上过度拟合(overfitting)。当模型过拟合时,它会学习到训练数据中的噪声和细微变化,导致在新数据上的性能下降。

正则化通过在模型的损失函数中引入额外的惩罚项,来对模型的参数进行约束,从而降低模型的复杂度

常见正则化手段有如下几种:

1)L1正则化:在模型的损失函数中增加权重的 L1 范数作为惩罚项来控制模型复杂度的技术。L1 范数是向量中各个元素的绝对值之和。公式如下,其中$λ$是正则化参数,用于控制正则化项的强度。$|w_i|$ 表示模型权重的绝对值。
$$
L_{L1}=L_{data}+λ\sum_n^{i=1}|w_i|
$$
L1相较于L2易获得稀疏解

2)L2正则化:通过向模型的损失函数添加一个权重参数的 L2 范数的惩罚项来实现。公式如下,$||w||^2_2$是权重向量w的 L2 范数的平方,表示为权重向量中各个参数的平方和。
$$
L_{L2}=L_{data}+λ||w||^2_2
$$
使用 L2 正则化的损失函数时,优化算法在优化过程中会同时考虑数据损失和正则化项,从而在保持对训练数据的拟合能力的同时,尽可能减小模型参数的大小,降低模型的复杂度。

3)Dropout:一种在神经网络中常用的正则化技术,用于减少过拟合。

其原理是在网络的训练过程中,随机地将部分神经元的输出置为零(即失活),从而使得网络在每次迭代时都在不同的子网络上训练,以减少神经元之间的复杂依赖关系,从而增强模型的泛化能力。

在每次训练迭代时,Dropout 方法会以一定的概率(通常为 0.5)随机地将某些神经元的输出置为零,即使得这些神经元在此次迭代中不参与前向传播和反向传播。这样可以阻止网络过度依赖于某些特定的神经元,增强模型的泛化能力。

而在训练时,通过随机失活神经元来减少过拟合;在测试时,所有的神经元都保持活跃,但是输出值需要按照训练时的概率进行缩放,以保持期望输出的一致性。

18.AUC相关

机器学习常用评价指标:ACC、AUC、ROC曲线_acc auc-CSDN博客

0.ROC曲线

基于样本预测值和真实值是否相符,可得到4种结果:

  • TP (True Positive):样本预测值与真实值相符且均为正,即真阳性
  • FP (False Positive):样本预测值为正而真实值为负,即假阳性
  • FN (False Negative):样本预测值为负而真实值为正,即假阴性
  • TN (True Negative):样本预测值与真实值相符且均为负,即真阴性

$TPR = \frac{TP}{TP+FN}$

$FPR = \frac{FP}{FP+TN}$

ROC曲线的横坐标为 FPR (False Positive Rate),纵坐标为TPR (True Positive Rate)

通俗解释:FPR表示负样本分错的概率;TPR表示正样本分对的概率

1.AUC的定义及其取值范围

  • 定义:AUC(Area Under the Curve)是指ROC曲线(Receiver Operating Characteristic Curve)下的面积。ROC曲线是一个二维图,横轴为假正率(False Positive Rate, FPR),纵轴为真正率(True Positive Rate, TPR)。AUC衡量的是模型在不同阈值下区分正负样本的能力。
  • 取值范围:AUC的取值范围是 [0, 1]。AUC值越接近1,表示模型的分类性能越好;AUC值越接近0,表示模型的分类性能越差。AUC = 0.5,意味着模型没有区分能力。AUC = 1,意味着模型完美区分正负样本。

2.AUC的计算方法

AUC的计算基于正负样本对的比较,具体步骤如下:

  1. 排序样本:将测试集中的样本按照模型预测的“正类概率”从高到低排序。

  2. 统计正负样本对:对于所有可能的”正样本-负样本“对,若正样本的预测概率高于负样本,则记为1个正确对,若两者概率相等,则记为0.5个正确对。

  3. 计算AUC值:AUC = 正确对数量 / 总正负样本对数量

3.AUC值含义

  • AUC值为0.5
    • 表示模型的性能与随机猜测相当。在这种情况下,模型无法有效区分正负样本,其分类结果没有比随机猜测更好。
  • AUC值为1.0
    • 表示模型具有完美的分类能力。在这种情况下,模型能够完美地区分正负样本,没有任何误分类。

4. AUC适合用于类别不平衡的数据集的原因

  • 不受类别分布的影响
    • AUC衡量的是模型在不同阈值下区分正负样本的能力,而不是直接关注分类准确率。在类别不平衡的数据集中,少数类的样本数量可能远少于多数类,这会导致基于准确率的评估指标(如准确率、召回率等)失真。而AUC通过考虑不同阈值下的真正率和假正率,能够更公平地评估模型的性能。
  • 综合考虑真正率和假正率
    • AUC同时考虑了真正率(TPR)和假正率(FPR),能够全面反映模型在不同阈值下的分类能力。即使正负样本比例悬殊 (如1:99),只要模型能将少数正样本正确排在负样本之前,AUC仍能反映其性能。
  • 阈值无关性
    • AUC不依赖于特定的分类阈值,而是综合考虑所有可能的阈值。这使得AUC在评估模型性能时更加稳定,不受阈值选择的影响。
    • 对比其他指标,准确率 (Accuracy) 在类别不平衡时可能失效 (例如将所有样本预测为负类准确率仍很高) ,而AUC不受此影响。

19.Softmax操作:

Softmax函数将一个实数向量转换为一个概率分布,使得所有元素的和为1。

注意力机制中,我们通常计算每个位置的注意力分数,这些分数表示每个位置的重要性。

然而,这些原始分数通常是实数,不能直接用作权重,因为它们可能为负数,且总和不为1。通过Softmax操作,我们可以将原始注意力分数转换为概率分布,使得每个位置的权重在0到1之间,并且所有权重的和为1。

这样,这些权重就可以用于加权平均操作,以生成上下文向量。

  • 归一化:Softmax操作确保了所有权重的和为1,使得加权平均操作有意义。
  • 非负性:Softmax操作将分数转换为非负值,避免了负权重的问题。
  • 概率解释:Softmax操作后的权重可以被解释为每个位置的相对重要性,具有概率的意义。

这一步骤有两个主要作用:一是确保每个位置的注意力权重在[0, 1]范围内,便于加权计算;二是突出重要特征,放大较大分数并压缩较小分数,从而帮助模型关注关键部分。同时,SoftMax避免了数值过大或过小的问题,保障了反向传播中的梯度稳定。

20. 卷积层

常见的一系列卷积层:

卷积类型 作用 优点 缺点 应用
1×1 卷积 通道混合 降维、高效 无法提取空间信息 ResNet, MobileNet
3×3 卷积 局部特征提取 最优感受野 计算量较大 VGG, ResNet, DenseNet
DWConv 轻量级特征提取 计算量减少 8 倍 仅限局部特征 MobileNet, EfficientNet
分组卷积 提高计算效率 降低计算量 通道信息混合较少 ResNeXt, ShuffleNet
空洞卷积 扩大感受野 适用于高分辨率 可能造成栅格效应 DeepLabV3+, SwinIR
可变形卷积 适应形变 处理非刚性对象 计算量较大 目标检测, 超分辨率

21.batch size

GPU 对 2的幂次或8的倍数的 batch 可以发挥出更好的性能,因此,设置成16、32、64、128、256…,时,往往比设置成其他倍数展示出更优的表现。

Transformer相关

Transformer面试题(转) - 知乎 (zhihu.com)

万字秋招算法岗深度学习八股文大全 - 知乎 (zhihu.com)

(95 封私信 / 76 条消息) transformer的细节到底是怎么样的? - 知乎

Transformer结构图

手撕 Self-Attention

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class SelfAttention(nn.Module):
def __init__(self,hidden_dim,dropout_rate=None):
super().__init__()
self.hidden_dim = hidden_dim
self.query = nn.Linear(hidden_dim, hidden_dim)
self.key = nn.Linear(hidden_dim, hidden_dim)
self.value = nn.Linear(hidden_dim, hidden_dim)
if dropout_rate:
self.dropout = nn.Dropout(dropout_rate)

def forward(self,x,mask=None):
batch_size, seq_len, hidden_dim = x.shape
d_k = hidden_dim
q = self.query(x)
k = self.key(x)
v = self.value(x)

attention_score = q @ k.transpose(-1,-2)/math.sqrt(d_k)
if mask is not None : # mask 矩阵的维度 和 attention_score维度 相同
attention_score = attention_score.masked_fill(mask==0, -1e9) # 也可以写成 float("-inf")
attention_score = F.softmax(attention_score, dim=-1)
attention_score = self.dropout(attention_score)
output = attention_score @ v
return output

手撕 Multi-Head Attention (MHA)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import torch
import torch.nn as nn
import torch.nn.functional as F

class MultiHeadAttention(nn.Module):
def __init__(self, embed_size, heads):
super(MultiHeadAttention, self).__init__()
self.embed_size = embed_size # 嵌入维度大小
self.heads = heads # 头的数量
self.head_dim = embed_size // heads # 每个头的维度

# 确保嵌入维度可以被头的数量整除
assert (
self.head_dim * heads == embed_size
), "Embedding size needs to be divisible by heads"

# 定义线性变换层,用于将输入转换为查询、键和值
self.values = nn.Linear(self.head_dim, self.head_dim, bias=False)
self.keys = nn.Linear(self.head_dim, self.head_dim, bias=False)
self.queries = nn.Linear(self.head_dim, self.head_dim, bias=False)
# 最终输出的全连接层
self.fc_out = nn.Linear(heads * self.head_dim, embed_size)

def forward(self, values, keys, query, mask):
N = query.shape[0] # 批量大小
value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]

# 将嵌入向量分割成多个头
values = values.reshape(N, value_len, self.heads, self.head_dim)
keys = keys.reshape(N, key_len, self.heads, self.head_dim)
queries = query.reshape(N, query_len, self.heads, self.head_dim)

# 对每个头进行线性变换
values = self.values(values)
keys = self.keys(keys)
queries = self.queries(queries)

# 计算点积注意力分数
energy = torch.einsum("nqhd,nkhd->nhqk", [queries, keys])
# queries shape: (N, query_len, heads, head_dim)
# keys shape: (N, key_len, heads, head_dim)
# energy shape: (N, heads, query_len, key_len)

# 应用掩码(如果存在)
if mask is not None:
energy = energy.masked_fill(mask == 0, float("-1e20"))

# 对注意力分数应用softmax函数
attention = torch.softmax(energy / (self.embed_size ** (1 / 2)), dim=3)

# 计算加权求和后的输出
out = torch.einsum("nhql,nlhd->nqhd", [attention, values]).reshape(
N, query_len, self.heads * self.head_dim
)
# attention shape: (N, heads, query_len, key_len)
# values shape: (N, value_len, heads, heads_dim)
# out after matrix multiply: (N, query_len, heads, head_dim), then flatten last two dimensions

# 通过全连接层得到最终输出
out = self.fc_out(out)
return out

# 示例用法:
if __name__ == "__main__":
embed_size = 512 # 嵌入维度大小
heads = 8 # 头的数量
batch_size = 64 # 批量大小
seq_length = 10 # 序列长度

mha = MultiHeadAttention(embed_size, heads)
values = keys = query = torch.randn(batch_size, seq_length, embed_size)

print(mha.forward(values, keys, query, mask=None).shape)

手撕 Multi-Query Attention(MQA)

核心思想是共享键(Key)和值(Value)的投影参数。

显著减少了模型参数量和计算复杂度,同时保留了多头注意力的部分并行性优势。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import torch
import torch.nn as nn
from thop import profile

class MultiQueryAttention(nn.Module):
def __init__(self, hidden_size, num_heads, dropout=0.0):
"""
Multi-Query Attention 的实现。

Args:
hidden_size (int): 输入特征的维度,也即 hidden_state 的最后一维。
num_heads (int): 注意力头的数量。
dropout (float): dropout 的概率,默认为 0.0。
"""
super(MultiQueryAttention, self).__init__()
assert hidden_size % num_heads == 0, "hidden_size 必须能被 num_heads 整除"

self.hidden_size = hidden_size
self.num_heads = num_heads
self.head_dim = hidden_size // num_heads # 每个头的维度

# 定义线性变换层,用于生成 Q, K, V
self.query = nn.Linear(hidden_size, hidden_size) # 每个头独立的 Query
self.key = nn.Linear(hidden_size, self.head_dim) # 所有头共享的 Key
self.value = nn.Linear(hidden_size, self.head_dim) # 所有头共享的 Value

self.dropout = nn.Dropout(dropout)
self.out_projection = nn.Linear(hidden_size, hidden_size)

def forward(self, query, key, value, mask=None):
N = query.shape[0] # 批量大小
query_len = query.shape[1]
key_len = key.shape[1]
value_len = value.shape[1]

# 将嵌入向量分割成多个头
query = self.query(query).view(N, query_len, self.num_heads, self.head_dim)
key = self.key(key).view(N, key_len, self.num_heads, self.head_dim)
value = self.value(value).view(N, value_len, self.num_heads, self.head_dim)

# 调整形状以便进行点积操作
query = query.transpose(1, 2) # shape: (N, heads, query_len, head_dim)
key = key.transpose(1, 2) # shape: (N, heads, key_len, head_dim)
value = value.transpose(1, 2) # shape: (N, heads, value_len, head_dim)

# 计算点积注意力分数
scores = torch.matmul(query, key.transpose(-2, -1)) / torch.sqrt(torch.tensor(self.head_dim))
# scores shape: (N, heads, query_len, key_len)

# 应用掩码(如果存在)
if mask is not None:
scores = scores.masked_fill(mask == 0, float('-inf'))

# 对注意力分数应用softmax函数
attention_weights = torch.softmax(scores, dim=-1)
# attention_weights shape: (N, heads, query_len, key_len)

# 计算加权求和后的输出
context = torch.matmul(attention_weights, value)
# context shape: (N, heads, query_len, head_dim)

# 调整形状以便通过全连接层
context = context.transpose(1, 2).contiguous().view(N, query_len, self.hidden_size)
# context shape: (N, query_len, hidden_size)

# 通过全连接层得到最终输出
output = self.out_projection(context)
# output shape: (N, query_len, hidden_size)

return output

if __name__ == "__main__":
hidden_size = 512 # 嵌入维度大小
num_heads = 8 # 头的数量
batch_size = 64 # 批量大小
seq_length = 10 # 序列长度

mqa = MultiQueryAttention(hidden_size, num_heads)
query = key = value = torch.randn(batch_size, seq_length, hidden_size)

print(mqa.forward(query, key, value, mask=None).shape)

手撕 Grouped Query Attention(GQA)

核心思想是将查询头(Query Heads)划分为多个组(Group),每组内的查询头共享一组键(Key)和值(Value),从而在保留多头并行性的同时减少参数量和计算复杂度。在参数效率与模型性能之间取得了平衡,适用于大规模模型的高效部署。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import torch
import torch.nn as nn

class GroupedQueryAttention(nn.Module):
def __init__(self, hidden_size, num_heads, group_size=2, dropout=0.0):
"""
Grouped Query Attention 实现。

Args:
hidden_size (int): 输入特征的维度。
num_heads (int): 查询头的数量。
group_size (int): 每个组中包含的查询头数量。
dropout (float): dropout 的概率。
"""
super(GroupedQueryAttention, self).__init__()
assert hidden_size % num_heads == 0, "hidden_size 必须能被 num_heads 整除"
assert num_heads % group_size == 0, "num_heads 必须能被 group_size 整除"

self.hidden_size = hidden_size
self.num_heads = num_heads
self.group_size = group_size
self.group_num = num_heads // group_size
self.head_dim = hidden_size // num_heads # 每个头的维度

# 定义线性变换层,用于生成 Q, K, V
self.query = nn.Linear(hidden_size, hidden_size) # 每个头独立的 Query
self.key = nn.Linear(hidden_size, self.group_num * self.head_dim) # 分组共享的 Key
self.value = nn.Linear(hidden_size, self.group_num * self.head_dim) # 分组共享的 Value

self.dropout = nn.Dropout(dropout)
self.out_projection = nn.Linear(hidden_size, hidden_size)

def forward(self, query, key, value, mask=None):
N = query.shape[0] # 批量大小
query_len = query.shape[1]
key_len = key.shape[1]
value_len = value.shape[1]

# 将嵌入向量分割成多个头
query = self.query(query).view(N, query_len, self.num_heads, self.head_dim)
key = self.key(key).view(N, key_len, self.group_num, self.head_dim)
value = self.value(value).view(N, value_len, self.group_num, self.head_dim)

# 调整形状以便进行点积操作
query = query.transpose(1, 2) # shape: (N, heads, query_len, head_dim)
key = key.transpose(1, 2) # shape: (N, group_num, key_len, head_dim)
value = value.transpose(1, 2) # shape: (N, group_num, value_len, head_dim)

# 计算点积注意力分数
scores = torch.matmul(query, key.transpose(-2, -1)) / torch.sqrt(torch.tensor(self.head_dim))
# scores shape: (N, heads, query_len, key_len)

# 应用掩码(如果存在)
if mask is not None:
scores = scores.masked_fill(mask == 0, float('-inf'))

# 对注意力分数应用softmax函数
attention_weights = torch.softmax(scores, dim=-1)
# attention_weights shape: (N, heads, query_len, key_len)

# 计算加权求和后的输出
context = torch.matmul(attention_weights, value)
# context shape: (N, heads, query_len, head_dim)

# 合并组内的头
context = context.view(N, query_len, self.num_heads, self.head_dim)
context = context.permute(0, 2, 1, 3).contiguous().view(N, query_len, self.hidden_size)
# context shape: (N, query_len, hidden_size)

# 通过全连接层得到最终输出
output = self.out_projection(context)
# output shape: (N, query_len, hidden_size)

return output

if __name__ == "__main__":
hidden_size = 512 # 嵌入维度大小
num_heads = 8 # 头的数量
group_size = 2 # 每个组中包含的查询头数量
batch_size = 64 # 批量大小
seq_length = 10 # 序列长度

gqa = GroupedQueryAttention(hidden_size, num_heads, group_size)
query = key = value = torch.randn(batch_size, seq_length, hidden_size)

print(gqa.forward(query, key, value, mask=None).shape)

手撕 Multi-Head Latent Attention(MLA)

一种结合低秩参数化与旋转位置编码(RoPE)的高效注意力机制。

核心思想是通过低秩投影压缩查询(Q)、键(K)、值(V)的维度,并在注意力计算中解耦内容与位置信息,从而减少计算复杂度,同时保留长距离依赖建模能力。适用于大规模模型的部署,平衡了效率与性能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import torch
import torch.nn as nn
import math

class RotaryEmbedding(nn.Module):
def __init__(self, hidden_size, num_heads, base=10000, max_len=512):
"""
RoPE位置编码模块

Args:
hidden_size (int): 模型维度
num_heads (int): 注意力头数量
base (int): 频率基值
max_len (int): 最大序列长度
"""
super().__init__()
self.head_dim = hidden_size // num_heads
self.hidden_size = hidden_size
self.num_heads = num_heads
self.base = base
self.max_len = max_len
self.cos_pos_cache, self.sin_pos_cache = self._compute_pos_emb()

def _compute_pos_emb(self):
# 计算频率因子
theta_i = 1. / (self.base ** (torch.arange(0, self.head_dim, 2).float() / self.head_dim))
# 创建位置索引
positions = torch.arange(self.max_len)
# 计算位置编码
pos_emb = positions.unsqueeze(1) * theta_i.unsqueeze(0)
# 计算cos和sin的位置编码
cos_pos = pos_emb.sin().repeat_interleave(2, dim=-1)
sin_pos = pos_emb.cos().repeat_interleave(2, dim=-1)
return cos_pos, sin_pos

def forward(self, x, seq_len=None):
if seq_len is None:
seq_len = x.size(1)
# 获取缓存中的位置编码
cos_pos = self.cos_pos_cache[:seq_len].unsqueeze(1)
sin_pos = self.sin_pos_cache[:seq_len].unsqueeze(1)

# 分割x为奇数和偶数部分
x1, x2 = x.chunk(2, dim=-1)
# 应用旋转位置编码
rotated_x1 = x1 * cos_pos - x2 * sin_pos
rotated_x2 = x1 * sin_pos + x2 * cos_pos
# 合并结果
rotated_x = torch.cat([rotated_x1, rotated_x2], dim=-1)
return rotated_x

# 示例用法:
if __name__ == "__main__":
hidden_size = 512 # 模型维度
num_heads = 8 # 注意力头数量
batch_size = 64 # 批量大小
seq_length = 10 # 序列长度

rope = RotaryEmbedding(hidden_size, num_heads)
x = torch.randn(batch_size, seq_length, hidden_size)

print(rope(x).shape)

Transformer相比于RNN/LSTM的优势?

1). Transformer 不依赖于序列中的时间顺序,可以并行处理整个序列(Self-Attention机制)。在计算时,所有的位置都可以同时访问输入数据。这让它在大规模数据和训练时能够充分利用硬件资源,加快训练速度。而 RNN 和 LSTM 是顺序模型,它们按时间步长逐个处理输入,因此无法并行处理序列。这种顺序计算限制了其速度。

2). 由于其自注意力(Self-Attention)机制,Transformer 可以直接通过注意力权重在序列中的任意位置建立联系,不论序列长度。通过全局的注意力机制,可以有效捕捉长距离依赖关系,可以同等关注远近的依赖。

而虽然 LSTM 相较于普通 RNN 具有更好的处理长程依赖的能力,但它依然依赖于序列的时间步长。这意味着如果要捕捉长距离依赖关系,信息需要逐步传播,并可能会因为梯度消 失问题导致远程依赖信息衰减。

Transformer中为什么用LayerNorm而不是BatchNorm?

两种Norm对比

1). LayerNorm 是对 单个样本的每一层特征 进行归一化,而不是像 BatchNorm 那样需要对 同一批数据的多个样本 进行归一化。因此,LayerNorm 不依赖批量样本的大小,可以更好地处理 变长序列数据,如自然语言中的句子长度。在 Transformer 模型中,输入序列的长度可能会变化,LayerNorm 的计算对这种动态长度序列不敏感,因此在自然语言处理中更加适用。

2). LayerNorm 则是对每个输入序列的特征进行独立归一化,不需要小批次的均值和方差,因此它可以用于 单个样本的在线推理批次较小的任务

LayerNorm优点

(1)增加模型的鲁棒性。由于 LayerNorm 可以对输入进行归一化,使得每个神经元的输入具有相似的分布特征,从而有助于网络的训练和泛化性能。
此外,由于归一化的系数是可学习的,网络可以根据输入数据的特点自适应地学习到合适的归一化系数。

(2)加速模型的训练。由于输入已经被归一化,不同特征之间的尺度差异较小,因此优化过程更容易收敛,加快了模型的训练速度。

(3)减少模型的过拟合。由于 LayerNorm 可以使得每个神经元的输入具有相似的分布特征,从而减少了模型过拟合的风险,提高了模型的泛化能力。

Transformer的巨大优势?

Transformer是被很多公司、组织证明过的非常有用的东西。其它别的都没有得到过大规模的工业级的验证。

  • 被广泛证明过,从最早的 Bert 开始Transformer 的 Encoder 与 Decoder 架构就证明它在大算力下的优势:并行且可以有序列数据的相关性。但是很遗憾,最先发现并且不遗余力的推行“规模就是智能”这事的,结果大家看到了 ChatGPT 、 GPT4、 DALL-E 、 SORA、 Whipser这些都是指导思想下的产物。
  • 可扩展性,很多时候你只要找到了一个稳定的方式,你就可以简单的堆模型的单层并行变大,或者把模型加几层,那你的效果就会持续变好。而这个特性,CNN 、 RNN 好像没有那么容易,还记得 CNN 时代,从几层到十几层,到 100 多层它的架构基本上都不太一样,这是不太适合工作生产的。
  • 特别适合显卡算力,显卡本身是一个完全异于 CPU 计算的算力设备,它适合大规模的并行计算,但是不适合复杂运行。比如H100, 这里边你能看到的小单元都是并行 Core。如果我们常见的 CPU 有几十个核已经算是最优秀的版本,那 Nvidia 的显卡至少要有 16896 个FP32 核 才是个 H100 的标配。这样的东西运行起 Transformer 确实是绝配!
  • 结果是端到端的,从输入到输出的整个过程都是可以在一个统一的框架内完成,简化了模型设计与训练。特别受欢迎的一种工作方式!
  • 适应性广,过去的 CNN 、 RNN 都是针对单一数据的,而这次的 Transformer 架构,已经证明了在 自然语言/文本数据、序列数据、图像、语音、视频等各类数据,各种任务上都有了极其优异的表现,基本上都是 SOTA 级别的。

讲一讲Self-Attention

Q、K、V 就是Self-Attention机制的核心。

Q: Query,查询,查询其他元素与自己相关的程度。

K: Key,键,表示序列中的每个元素特征,用来判断是否与其他元素(即Query)有关。

V: Value,值,代表序列中每个元素的实际信息。当Query与某个Key的相似度较高时,这个Value就会对Query的输出产生更大的影响。

在 Self-Attention 机制中,输入的每个元素都会产生对应的Q、K、V,通过将查询 Q 与键 K 进行相关性计算,然后将这些相关性作为权重应用到值 V 上。

输入序列被用来计算查询 Q 、键 K 和值 V 。每个查询 Q 与所有键 K 计算得到相关性分数,然后通过 Softmax 函数将这些分数归一化为权重,最终这些权重被应用到相应的值 V 上,从而得到注意力表示。

Q、K 和 V 的作用可以简单概括如下:

  • Query(Q):确定关注的内容,是用来“提问”的向量。它表示每个元素希望从其他元素中提取的信息,即当前元素与其他元素的相关性。
  • Key(K):提供与查询相关的上下文,是用来“回答”的向量。它表示每个元素本身的特征,其他元素的Query会根据这些Key来判断它们是否相关。
  • Value(V):是序列中的信息内容。Self-Attention 的最终输出就是根据Query和Key的相似度对这些Value进行加权求和后的结果。

假设输入序列的维度是 $b×n×d$,其中 b 表示batch size,n 表示序列长度,d 表示每个元素的特征维度。

那么,Q K V 的维度均为 $b×n×d_k$。相关计算公式为 $\frac{QK^T}{\sqrt{d_k}}V$ ,$T$是转置操作,$d_k$是K的维度。

Q^K示意图。对于权重矩阵的第1行来说,0.7表示的就是“我”与“我”的注意力值;0.2表示的就是“我”与”是”的注意力值;0.1表示的就是“我”与“谁”的注意力值。

除以$d_k$:

在softmax之前除以$dk$ 可以将 $QK^T$ 的分布的方差纠正回接近1,这样一来,大部分数值都会分布在softmax梯度适当的位置,也就避免了梯度消失的问题。

大值的点积可能会导致 Softmax 进入梯度消失区域,因为极大的输入值会使 Softmax 函数的梯度较小,接近 0。而通过除以 $\sqrt{d_k}$,可以避免进入这种极端情况,保持梯度稳定。

多头注意力机制

从上面的计算结果还可以看到一点就是,模型在对当前位置的信息进行编码时,会过度的将注意力集中于自身的位置而可能忽略了其它位置。因此采取的一种解决方案就是采用多头注意力机制(Multi-Head-Attention)。同时,使用多头注意力机制还能够给予注意力层的输出包含有不同子空间中的编码表示信息,从而增强模型的表达能力。

一个比较经典的问题是,在相同维度下使用单头和多头的区别是什么?

以图 1-10 中示例为例,此时的自注意力中使用了两个头,每个头的维度为$d_q$,即采用了多头的方式。另外一种做法就是,只是用一个头,但是其维度为$2d_q$,即采用单头的方式。那么在这两种情况下有什么区别呢?

当模型的维度$d_m$确定时,一定程度上,h越大整个模型的表达能力越强,越能提高模型对于注意力权重的合理分配。

词嵌入问题

在 Transformer 模型中,首先第一步要做的同样是将文本以这样的方式进行向量化表示:将各个词(或者字)通过一个Embedding层映射到低维稠密的向量空间,并且将其称之为Token Embedding,也就是深度学习中常说的词嵌入(Word Embedding)

词嵌入

但是,仅仅只使用自注意力机制会丢失文本原有的序列信息。序列在交换位置前和交换位置后计算得到的结果在本质上并没有任何区别,仅仅只是交换了对应的位置。因此,基于这样的原因,Transformer在原始输入文本进行Token Embedding后,又额外的加入了一个Positional Embedding来刻画数据在时序上的特征。

Transformer 模型本身是基于自注意力机制(Self-Attention)的,它不像循环神经网络(RNN)那样自然地包含序列顺序信息。因此,为了使模型能够理解输入序列中各个元素的相对位置或绝对位置,需要引入位置编码(Position Embedding)。

为什么需要 Position Embedding?

  1. 自注意力机制的特性:自注意力机制在计算注意力权重时,会考虑序列中所有元素之间的关系,但它本身并不区分元素的顺序。换句话说,自注意力机制对输入序列的排列是不变的。
  2. 序列顺序的重要性:在很多任务中,序列的顺序是非常重要的,例如在自然语言处理任务中,词语的顺序决定了句子的语义。

Bert为什么三个embedding可以相加?

这里的三个embedding是指token embedding,segment embedding,position embedding。虽然在深度神经网络里变得非常复杂,本质上神经网络中每个神经元收到的信号也是“权重”相加得来。

介绍一下transformer的位置编码,以及你知道哪些关于位置编码的改进方法?

1. 标准位置编码(固定位置编码)

Transformer模型最初使用的是基于正弦和余弦函数的固定位置编码(Fixed Positional Encoding)。其计算公式如下:

  • 对于每个位置 pos 和维度 2i

    $PE(pos,2i)=sin(\frac{pos}{10000^{2i/d_{model}}})$

  • 对于每个位置 pos 和维度 2i+1:

    $PE(pos,2i+1)=cos(\frac{pos}{10000^{2i/d_{model}}})$

其中,$d_{model}$ 是嵌入的维度。

这种编码方式的优点是简单且能够捕捉到相对位置信息,因为不同位置的编码可以通过线性组合来表示相对位置关系,能够捕捉序列中的顺序关系。

然而,缺点在于长度外推能力有限,即在训练时使用的序列长度之外的序列上表现不佳。无法直接表示相对位置。

2. 旋转位置编码(RoPE)(必考)

旋转位置编码(Rotary Position Embedding, RoPE)是近年来被广泛采用的一种改进方法。它通过引入复数和旋转矩阵来编码位置信息,使得在自注意力机制中能够更好地保留相对位置信息。

RoPE的核心思想是将每个位置的嵌入表示为复数形式,并通过旋转操作来实现位置编码。具体来说,RoPE通过以下方式实现:

  • 将嵌入向量分成实部和虚部。
  • 在自注意力计算中,wei通过旋转操作来调整嵌入向量,从而保留相对位置信息。

RoPE的优点在于它能够更好地处理长序列,并且具有更好的长度外推能力。

ROPE通过旋转变换为模型提供相对位置编码,增强了对长序列依赖关系的建模能力,特别适用于长序列和复杂任务

3. 相对位置编码(RPE)

相对位置编码(Relative Position Embedding, RPE)关注的是序列中元素之间的相对位置关系,而不是绝对位置。RPE通过为每个位置对分配一个位置编码向量来实现。

RPE的计算方式如下:

  • 在自注意力机制中,为每个位置对 (m,n) 添加一个相对位置编码向量 $R_{m,n}$。
  • 这些相对位置编码向量可以通过学习得到,或者通过预定义的函数生成。

相对位置编码的优点在于它能够更好地处理序列中的相对位置关系,从而在长序列建模中表现更好。

4. 双层位置编码(BiPE)

双层位置编码(Bi-layer Position Encoding, BiPE)是一种新型的位置编码方法,它将位置编码分为段内编码和段间编码。BiPE的主要思想是:

  • 使用绝对位置编码作为段内编码,以捕捉局部位置信息。
  • 使用相对位置编码(如RoPE或ALiBi)作为段间编码,以捕捉长距离的相对位置信息。

BiPE在实验中表现出色,尤其是在长序列建模和长度外推任务中,其性能优于传统的单层位置编码方法

RMSNorm

RMSNorm(Root Mean Square Normalization)是一种归一化方法,主要用于深度学习中的神经网络,尤其是在处理长序列数据时表现出色。它通过计算输入向量的均方根(RMS)值来进行归一化,而不像LayerNorm那样计算均值和方差。

手撕 RMSNorm:

1
2
3
4
5
6
7
8
9
10
11
import torch.nn as nn
class RMSNorm(nn.Module):   
def __init__(self, dim: int, eps: float = 1e-8):       
super().__init__()       
self.eps = eps       
self.gamma = nn.Parameter(torch.ones(dim))  # 可学习缩放参数
    def forward(self, x: torch.Tensor) -> torch.Tensor:       
# 计算输入x的均方根(沿最后一个维度)       
rms = x.pow(2).mean(dim=-1, keepdim=True).sqrt().add(self.eps)       
# 归一化并应用缩放       
return x / rms * self.gamma

RMSNorm 与 LayerNorm的区别:

特性 RMSNorm LayerNorm
归一化公式 仅用均方根,无均值中心化 先中心化(减均值),再除以标准差
参数数量 仅缩放参数 gamma 缩放参数 gamma 和偏移参数 beta
计算复杂度 更低(省去均值计算) 更高(需计算均值和标准差)
适用场景 输入分布接近零中心时效果更好 对任意输入分布鲁棒性更强
实现细节 x / sqrt(mean(x²) + ε) * gamma (x - μ) / sqrt(σ² + ε) * gamma + beta
典型应用 LLaMA、T5等模型 Transformer原始架构、BERT等

参数与计算效率

  • RMSNorm减少了一个参数(无 beta)和一次均值计算,适合对计算资源敏感的场景。
  • LayerNorm通过 beta 保留偏移能力,对输入分布变化更鲁棒,但计算代价略高。

适用性

  • 当输入近似零中心(如激活函数后)时,RMSNorm效果与LayerNorm相当且更高效。
  • 若输入分布偏移较大,LayerNorm的均值中心化可能更稳定。

Mask相关

Bert中有哪些地方用到了mask?

预训练任务Masked Language Model (MLM)、self-attention的计算、下游任务的decoder

预训练阶段的mask有什么用?

主要的思想是,把输入的其中一部分词汇随机掩盖,模型的目标是预测这些掩盖词汇。这种训练方式使得每个位置的BERT都能学习到其上下文的信息。

attention中的mask有什么用?

这是nlp任务很重要的问题,就是不同样本的seq_len不一样。但是由于输出的seq_len需要一致,所以需要通过补padding来对齐。而在attention中我们不希望一个token去注意到这些padding的部分,因为实际场景下它们是不存在的,所以attention中的mask就是来处理掉这些无效的信息的。

具体来说就是在softmax前每个都设为-inf(或者实际的场景一个很小的数就可以),然后过完softmax后”padding”部分的权重就会接近于零,query token就不会分配注意力权重了。

decoder中的mask有什么用?

遮盖掉sequence中当前位置之后信息,以防止模型利用未来信息,也就是信息泄露。mask掉后模型的注意力只会集中在此前的序列上。

Bert的具体网络结构

Bert,Bidirectional Encoder Representations from Transformers,是一种基于 Transformer 结构的语言模型,用来生成文本的深层双向表示。它彻底改变了自然语言处理(NLP)领域的研究方式。

BERT 的核心创新之一是双向编码器。在传统的语言模型 LSTM 或 RNN中,模型会顺序从左到右或从右到左预测下一个词。而 BERT 是通过同时考虑句子的左右上下文来学习词汇的含义。这种双向性使得 BERT 能够理解一个词或子词在句子中的更深层次的语义关系。

Transformer架构:BERT 基于 Transformer 编码器,依赖于注意力机制(Self-Attention)来捕捉句子中不同词之间的关系。BERT 只使用 Transformer 的 Encoder 部分,它并不生成文本,而是通过理解现有文本进行分类或问答等任务。

传统语言模型中,单向上下文(仅前向或后向)导致了信息丢失。而BERT 的成功归功于两种新的预训练任务:

1). Masked Language Model (MLM): 传统的语言模型通过预测下一个词来学习,而 BERT 使用了一种称为 Masked Language Model 的技术。在 MLM 中,输入的句子会随机遮盖(mask)一些词(通常是 15%),要求模型预测这些掩盖单词的原始值来实现。模型的目标是在训练过程中预测出这些被遮盖的词

由于模型在训练时看不到某些词,它被迫通过句子的上下文来推测缺失的词,这有助于模型更好地理解词汇的语义和上下文关系。

例如: 输入句子:[CLS] The cat sits on the [MASK]. [SEP] 模型的任务是预测 [MASK] 的正确词(如 “mat”)。

这种训练方式使得BERT能够有效地学习单词的上下文关系和语义信息,从而更好地理解语言。

2). Next Sentence Prediction (NSP): 除了预测遮盖的词,BERT 还引入了 Next Sentence Prediction 任务。这种任务的目标是使模型能够理解句子之间的关系预测给定的两句话是否是连续的。通过这个任务,BERT 可以学会句子间的逻辑关系,从而在处理句子对相关的任务(如问答、自然语言推理等)时表现得更好。

具体来说,BERT 会接收两个句子,模型需要判断第二句话是否是第一句话的连续句。例如:

  • 输入:[CLS] The cat is on the mat. [SEP] It is sleeping. [SEP]
  • 输出:True(句子连贯)

通过这种方式,BERT学习理解句子之间的逻辑和关系,增强对文本的整体理解能力。

为什么LayerNormalization比BatchNormalization更适合NLP任务?

  1. 对批量大小的依赖性

Batch Normalization依赖于每个mini-batch的数据来计算均值和方差,因此其效果高度依赖于批量大小。当批量大小较小时(例如在NLP任务中常见的小批量或单样本情况),BN的统计信息(均值和方差)可能不够稳定,从而影响模型的训练和泛化能力。

而Layer Normalization是针对单个样本在特征维度上进行归一化,不依赖于批量大小,因此在小批量或单样本场景下表现更加稳定。

  1. 对序列长度的适应性

NLP 任务通常涉及变长序列,例如句子或文档的长度可能不同。

Batch Normalization需要对整个batch中的数据进行统一归一化,而不同序列长度会导致统计信息计算复杂且不稳定,这种情况下难以适应。

Layer Normalization则对序列长度的变化不敏感,因为它只关注单个样本内部的特征维度。

  1. 计算效率和内存占用

在处理大规模数据或深层网络时,Layer Normalization的内存效率更高。由于LN的计算只依赖于单个样本的特征维度,而BN需要存储整个batch的统计信息,LN在内存占用和计算复杂度上更具优势。

  1. 训练稳定性

Layer Normalization在训练过程中表现出更好的稳定性,尤其是在处理长序列或深层网络时。

例如,在Transformer架构中,LN能够有效缓解梯度消失或爆炸的问题,从而加速模型收敛。此外,LN在训练和推理阶段执行完全相同的计算,而BN在训练和推理阶段的计算方式不同,这可能导致模型在推理时的表现与训练时存在差异。

  1. 与NLP模型架构的兼容性

在NLP中常用的模型架构(如RNN、Transformer)中,Layer Normalization可以更自然地集成。例如,在Transformer模型中,LN被广泛应用于多头自注意力机制和前馈网络中,以稳定训练过程。而对于RNN,BN难以直接应用,因为RNN需要在每个时间步上动态更新状态,而LN可以独立于时间步进行归一化。

BERT模型在处理文本时,会在输入序列的开头添加一个特殊的[CLS]标记。这个标记是做什么的?具体怎么使用?

用途

  1. 文本分类任务:[CLS] 标记的主要作用之一是用于文本分类任务。在这类任务中,BERT模型需要对整个文本输入进行分类,例如判断一段新闻文本属于政治、经济、文化等哪个类别。由于BERT模型在处理输入序列时,会为每个词生成一个对应的向量表示,而**[CLS]标记对应的向量会综合考虑整个输入文本的语义信息,从而作为整个文本的特征表示用于后续的分类任务**。比如在情感分析中,模型可以通过[CLS]标记对应的向量来判断文本表达的是积极、消极还是中性情感。
  2. 聚合上下文信息:[CLS]标记位置经过自注意力机制等运算后,能够融合整个输入序列各个位置的信息,聚合了整个文本的上下文语义,这样模型可以从这个单一的向量中获取到关于整个文本的综合理解。例如在阅读理解任务中,关于整个篇章的总体推断类问题,就可以依赖[CLS]标记对应的向量来提供关键信息。

使用方式

  1. 模型输入将文本输入到BERT模型时,会在文本序列的开头添加[CLS]标记。例如,对于文本“我喜欢自然语言处理”,实际输入到模型中的序列可能是“[CLS]我喜欢自然语言处理”。然后这个序列会经过词嵌入(Token Embedding)、位置嵌入(Position Embedding)和片段嵌入(Segment Embedding,在处理两个句子的任务如问答任务时会用到)等操作,将每个标记转化为对应的向量表示
  2. 获取特征向量:经过BERT模型的多层Transformer编码器的计算后,会得到每个标记位置对应的输出向量。其中,**[CLS]标记对应的输出向量就被作为整个输入文本的特征向量**。例如,BERT模型有12层Transformer编码器,最后一层输出的[CLS]标记对应的向量 就包含了整个文本的综合语义信息。
  3. 下游任务使用:在下游任务中,如文本分类,会将**[CLS]标记对应的向量输入到一个全连接层(通常还会接一个Softmax层)进行分类**。假设分类任务是K个类别,全连接层的权重矩阵为$W∈R^{k×d}$,偏置为$b∈R^k$,其中d是[CLS]向量的维度。则分类得分$s=Wh_{cls}+b$,通过Softmax函数得到每个类别的概率分布,从而确定文本所属类别。

大模型相关

‬‌‌‍⁠⁠⁠⁠‍‌‬‬‌‬‍‌‬DeepSeek速通:从V1到V3再到R1 - 飞书云文档

DeepSeek Paper Note

(71 封私信 / 54 条消息) 大模型LLM知识整理 - 知乎

(71 封私信 / 54 条消息) 图解大模型计算加速系列:FlashAttention V1,从硬件到计算逻辑 - 知乎

对比BERT和GPT的架构差异,并说明它们在预训练任务上的不同

架构差异

  • BERT
    • BERT采用的是双向Transformer编码器架构,能够同时利用上下文信息。其输入经过WordPiece分词后,会添加特殊标记[CLS][SEP],并使用Segment Embeddings区分不同句子。
    • BERT的架构有多个版本,如BERT-BASE(12层编码器,768个隐藏单元,12个注意力头,110M参数)和BERT-LARGE(24层编码器,1024个隐藏单元,16个注意力头,340M参数)。
  • GPT
    • GPT采用的是单向Transformer解码器Decoder架构,仅使用前文信息进行预测。这种单向结构使其适合生成任务,但无法直接利用后续信息。
    • GPT系列不断扩展模型规模,从GPT-1到GPT-3,参数量从数亿增加到1750亿,GPT-4进一步增强了多模态能力。

预训练任务的差异

  • BERT
    • 掩码语言模型(Masked Language Model, MLM):BERT的预训练任务之一是MLM,随机遮盖输入文本中的一部分单词(通常15%),然后预测这些被遮盖的单词。这种双向预测任务使BERT能够学习到丰富的上下文信息,适合理解类任务。
    • 下一句预测(Next Sentence Prediction, NSP):BERT还会预测两个句子是否是连续的文本,这有助于学习句子之间的关系。
  • GPT
    • 语言模型(Language Model, LM):GPT的预训练任务是标准的语言模型任务,即根据前文预测下一个单词。这种单向预测任务使GPT在文本生成任务中表现出色,能够生成连贯的文本。

总结

BERT和GPT在架构和预训练任务上的差异导致了它们在应用场景上的不同:

  • BERT适合需要深入理解上下文的任务,如文本分类、命名实体识别和问答。
  • GPT则更适合文本生成任务,如创意写作、对话系统和文本摘要。

为什么在进行多头注意力的时候需要对每个head进行降维?

1.降低计算复杂度

  • 在多头注意力中,输入的特征向量通常会被分成多个头(heads),每个头负责处理输入的不同子空间。如果不进行降维,每个头的维度将与原始输入维度相同,这会导致计算量大幅增加。通过降维,每个头的维度被缩小,从而降低了计算复杂度。
  • 例如,假设原始输入维度为 $d_{model}$,分成 h 个头,每个头的维度为 $d_{head}=\frac{d_{model}}{h}$,这样每个头的计算量显著减少。
  1. 提高模型的灵活性和表达能力
  • 降维后的每个头可以专注于输入的不同方面,从而捕捉到更丰富的语义信息。通过这种方式,模型可以从不同角度理解输入序列,例如语法结构、语义角色等。
  • 多头注意力机制允许模型并行地学习多种注意力模式,每个头通过独立的线性变换学习不同的特征关联。
  1. 避免过拟合
  • 降维可以减少每个头的参数量,从而降低模型的复杂度,有助于避免过拟合。通过减少每个头的维度,模型在训练时更容易收敛,同时在测试集上的泛化能力也更强。
  1. 内存优化
  • 在处理长序列时,降维可以显著减少内存占用。例如,传统多头注意力机制中,每个头独立生成键(Key)和值(Value),内存占用会随着头的数量线性增长。通过降维,每个头的维度缩小,从而减少了内存需求。
  1. 保持信息多样性
  • 尽管每个头的维度被缩小,但通过将多个头的输出拼接(concatenate)在一起,模型仍然可以保持丰富的信息。最终,这些拼接后的输出会通过一个线性层进行融合,从而生成最终的注意力输出。

总结

在多头注意力机制中,对每个头进行降维是为了降低计算复杂度、提高模型的灵活性和表达能力、避免过拟合、优化内存占用,同时保持信息多样性。

o1和o3分别指的是什么?区别有哪些?

O1O3 是 OpenAI 推出的两个不同阶段的模型,它们在能力、技术特点和应用场景上存在显著差异。目前没有公开提到“O2”模型,可能是因为 OpenAI 在命名时跳过了该名称。

O1

  • 特点:O1 是 OpenAI 推出的一个专注于推理能力的模型,其核心在于通过强化学习和特定的训练方式,提升模型在复杂任务中的推理和解决问题的能力。
  • 技术改进:O1 使用了专注于数学和科学的自定义数据集,并应用了大规模强化学习,这使得它能够处理需要多个步骤才能解决的任务。
  • 应用场景:O1 主要用于需要高水平推理能力的任务,例如复杂的数学问题、逻辑推理等。

O3

  • 特点:O3 是 O1 的继任者,代表了 AI 推理能力的进一步提升。它在多个复杂任务中的表现显著优于 O1,特别是在编程、数学和一般智能领域。
  • 技术改进
    • 多路推理:O3 可能采用了多路推理机制,允许模型在解决问题时探索多种可能的路径。
    • 强化学习与测试时推理:O3 在推理过程中使用了强化学习,并且在测试时会进行更复杂的推理过程,这使得它能够处理更复杂的任务。
    • 内置质量检查:O3 具备检查答案准确性的能力,这使得它在处理需要高精度的任务时更加可靠。
  • 应用场景:O3 适用于需要极高推理能力和精度的任务,例如编程竞赛、复杂的数学问题解决等。

O1 与 O3 的区别

  • 推理能力:O3 在推理能力上显著优于 O1,能够处理更复杂的任务。
  • 训练方式:O3 在训练过程中可能采用了更复杂的多路推理机制和强化学习策略。
  • 应用场景:O3 适用于需要更高推理能力和精度的任务,而 O1 已经在推理任务上表现出色。
  • 成本与效率:O3 的推理过程需要更高的计算资源和时间,这使得它的使用成本更高。

解释多卡并行训练中的Zero1、Zero2、Zero3策略

Zero1、Zero2、Zero3是DeepSpeed框架中用于优化大规模模型训练的三种策略,它们通过不同的方式减少内存占用,提高训练效率。

Zero1

  • 优化内容:Zero1主要对优化器状态进行拆分。在模型训练中,正向传播和反向传播并不需要优化器状态,只有在梯度更新时才需要。因此,Zero1将优化器状态分成多个小块,每个进程只存储和更新自己负责的部分。
  • 内存优化:通过这种方式,Zero1可以将显存消耗减少到原来的1/4。
  • 通信开销:通信量与数据并行相同。
  • 优点:实现相对简单,适合对内存优化有一定需求但不想引入过多复杂性的场景。
  • 缺点:相比更高级的Zero策略,内存优化程度有限。

Zero2

  • 优化内容:Zero2在Zero1的基础上,进一步对梯度进行拆分。在计算梯度时,每个进程只计算和存储自己负责的部分,然后通过通信机制进行聚合。
  • 内存优化:Zero2可以将显存消耗进一步减少到原来的1/8。
  • 通信开销:通信量仍然与数据并行相同。
  • 优点:相比Zero1,进一步减少了内存占用,适合训练更大规模的模型。
  • 缺点:实现复杂度比Zero1更高,需要更精细的通信机制。

Zero3

  • 优化内容:Zero3在Zero2的基础上,进一步对模型参数进行拆分。每个进程只存储和计算自己负责的参数子集。
  • 内存优化:Zero3的内存减少幅度与数据并行度成线性关系。例如,在64个GPU的情况下,内存消耗可以降低64倍。
  • 通信开销:相比前两个阶段,Zero3的通信量会有所增加。
  • 优点:极大地减少了每个GPU所需的显存,能够训练比显存容量大很多的模型,同时保持计算效率。
  • 缺点:实现最为复杂,需要更多的通信开销,可能会增加训练时间。

在进行监督微调操作时,选择Chat版本还是Base版本作为baseline模型?有何区别?

1. 训练方式

  • Base版本
    • 训练方式:Base模型是通过无监督的预训练(Pre-train)得到的,主要在大量未标注的文本数据上进行训练,学习语言的通用统计规律。
    • 特点具有强大的语言生成能力,但没有针对特定任务进行优化。
  • Chat版本
    • 训练方式:Chat模型是在Base模型的基础上,通过监督微调(SFT)和强化学习(RLHF)进一步优化得到的。其训练数据包括标注好的对话数据集和用户反馈。
    • 特点专注于对话和人机交互,能够生成连贯且符合人类偏好的回复。
  1. 应用场景
  • Base版本
    • 适用场景:适合需要进一步微调以适应特定任务的场景,如文本生成、语义理解、翻译等。
    • 优势:具有较强的泛化能力,适合多种NLP任务
  • Chat版本
    • 适用场景:特别适用于构建聊天机器人、虚拟助理等对话系统,需要进行多轮对话并保持上下文连贯的场合。
    • 优势:对话能力强,能够生成符合人类偏好的回复,并具备情感和礼貌控制。
  1. 任务处理能力
  • Base版本
    • 任务处理能力:没有预定义的指令任务或对话优化,需要通过监督微调来适应特定任务。
  • Chat版本
    • 任务处理能力:经过对话数据的监督微调和强化学习,能够更好地理解上下文并生成合适的回应

选择建议

  • 选择Base版本
    • 如果你的任务需要高度定制化,且需要从头开始微调以适应特定的领域或任务,Base版本是一个较好的选择。
    • Base版本保留了更纯粹的知识表征,适合学术研究或企业自建垂直模型。
  • 选择Chat版本
    • 如果你的任务主要集中在对话交互,如聊天机器人或客服系统,Chat版本更适合,因为它已经经过了对话优化,能够生成更自然、更连贯的回复。
    • Chat版本在多轮对话中表现更佳,适合需要与用户进行多轮交互的场景。

RAG中的切片处理策略

在RAG(Retrieval-Augmented Generation)模型中,切片处理(Chunking)是提高模型效率和效果的关键步骤。以下是几种常见的切片处理技巧及其优化方法:

1. 切片策略的选择

切片策略的选择直接影响到检索和生成的效果。常见的切片策略包括:

  • 按固定大小切片(Chunk by Size):将文档按固定长度切分成多个片段,适用于格式规整的文本。
  • 按段落切片(Chunk by Paragraph):根据文档的段落结构进行切分,保留段落的完整性。
  • 按标题切片(Chunk by Markdown Header):对于Markdown或HTML格式的文档,按标题层级进行切分。
  • 按自定义分隔符切片(Chunk by Separator):根据特定的分隔符(如换行符)进行切分。

2. 保持上下文完整性和相关性

切片时应尽量保持上下文的完整性和相关性,这直接影响到模型的生成效果:

  • 避免硬切分:尽量避免将句子或段落硬性切分,以免破坏上下文连贯性。
  • 保留元数据:在切片时,将图片、表格等非文本内容单独抽取为Chunk,并保留其标题或描述作为元数据。
  • 重叠切片:设置一定的重叠部分(Overlap),以确保上下文信息的连续性。

3. 多元化信息抽取

除了对文档进行Embedding向量抽取外,还可以进行其他多元化的信息抽取,以增强文档的语义信息:

  • 知识图谱:构建知识图谱,将文档中的实体和关系进行结构化表示。
  • 表格信息抽取:提取文档中的表格信息,并将其转化为结构化数据。

4. 分块的艺术

分块不仅是为了提高检索效率,还能提升生成内容的质量:

  • 固定字符大小:简单粗暴地按固定字符数切分,适用于格式规整的文本。
  • 递归字符文本分割:根据标点符号和空格进行切分,使切分后的块更有上下文意义。
  • 语义分割:使用语言模型进行语义分割,按意思切块,虽然计算资源消耗较大,但效果更好。

5. 查询分解与优化

查询分解技术可以提高检索的准确性和效率:

  • DSP框架:将复杂查询分解为简单的子查询,逐步解决后再整合答案。
  • 自我询问:通过识别合并答案时的难点来分解查询,逐步整合答案。

6. 实际案例中的优化

在实际项目中,通过以下优化方法可以显著提高检索准确率:

  • 数据预处理:将文本字段合并为一个内容字段,并为向量搜索创建embeddings。
  • 索引优化:在Azure AI Search等平台上构建高效的搜索索引。

KV Cache相关问题

1. 什么是KV Cache?它在自注意力机制中如何应用?

KV Cache(Key-Value Cache)是一种优化技术,用于加速Transformer模型中的自注意力机制,特别是在自回归生成任务(如文本生成、对话系统等)中。

在Transformer模型的自注意力机制中,每次生成一个新token时,模型需要计算当前token的**Query (Q)向量,并与之前所有token的Key (K)Value (V)**向量进行交互,以生成注意力权重并合成输出。然而,随着生成序列的增长,重复计算这些K和V向量会带来巨大的计算开销。

KV Cache的作用

  • 缓存历史K和V向量:在推理过程中,模型将每个token的K和V向量存储到KV Cache中。
  • 仅计算新增的Q向量:当生成新token时,模型只需计算当前token的Q向量,并与缓存中的K和V向量进行注意力计算。

这种机制显著减少了重复计算,提高了推理效率。

2. 使用KV Cache的主要优势是什么?如何通过它减少计算开销?

使用KV Cache的主要优势包括:

  • 降低计算复杂度:通过缓存K和V向量,避免了重复计算,将计算复杂度从O(n2⋅d)降低到O(nd),其中n是序列长度,d是向量维度。
  • 加快推理速度:直接使用缓存的K和V向量进行注意力计算,显著提高了推理速度。
  • 优化内存占用:虽然KV Cache会占用一定内存,但相比重复计算,总体内存占用是可控的。

减少计算开销的方式

  • 缓存机制:在生成新token时,模型从KV Cache中读取之前token的K和V向量,而不是重新计算。
  • 逐步更新:每次生成新token后,将新计算的K和V向量追加到KV Cache中,供后续生成使用。

3. KV Cache在长文本生成时可能带来什么问题?如何优化?

可能的问题

  • 内存占用:随着生成序列的增长,KV Cache会占用大量显存,尤其在处理长文本时更为明显。
  • 实现复杂性:在分布式推理或多模型并行场景下,KV Cache的管理和更新可能会增加系统复杂性。

优化方法

  • KV Cache量化:通过将浮点数参数转换为离散的、有限精度的数值,减少存储空间的占用,同时加快数据访问速度。
  • 分页技术:如PagedAttention,通过将KV Cache分页管理,提高内存利用率,减少内存碎片。
  • 动态调整缓存大小:根据实际需求动态调整KV Cache的大小,避免显存溢出。

通过这些优化方法,KV Cache可以在保持高效推理的同时,更好地管理内存资源,适用于长文本生成等复杂任务。

DPO与PPO

DPO(Direct Preference Optimization,直接偏好优化)作为一种无奖励的RLHF方法,核心思想是直接基于偏好数据优化策略,而无需显式构建奖励函数。DPO的出现主要是为了简化训练流程,避免奖励建模过程中可能出现的偏差和过拟合问题。

在原理部分,DPO将奖励函数表示为策略的对数形式,通过最大化策略在偏好数据上的似然性来优化模型。DPO通过比较不同响应的偏好关系,直接调整策略参数,使模型更倾向于生成符合人类偏好的响应。这种方法在数学上避免了奖励建模的复杂性,同时能够直接利用偏好数据进行优化。

DPO的优势在于其简化了训练流程,减少了奖励建模带来的潜在问题。它能够直接从偏好数据中学习,避免了奖励函数设计的主观性和复杂性。此外,DPO在某些学术基准测试中表现出色,例如在代码生成任务中能够取得优异成绩。

与DPO的原理不同,PPO(Proximal Policy Optimization)是一种基于奖励的RLHF方法,通过构建奖励模型来量化人类偏好,然后利用强化学习算法优化模型策略。PPO的出现是为了在优化过程中保持策略更新的稳定性,避免策略更新过大使模型性能下降。

PPO首先需要构建一个奖励模型,该模型通过对人类标注的偏好数据进行学习,将人类偏好转化为可量化的奖励信号。然后,利用演员-评论家架构,PPO通过最大化累积奖励来优化策略。具体来说,PPO通过计算策略的优势函数,评估策略在不同状态下的表现,并根据优势函数更新策略参数。

相比于DPO,PPO的优势在于其能够有效利用奖励信号进行策略优化,通过奖励模型捕捉复杂的偏好模式。它在实际应用中表现出色,例如ChatGPT的成功应用。此外,PPO通过引入截断参数和KL散度正则化,确保了策略更新的稳定性,避免了策略更新过大使模型性能下降的问题。

除了PPO和DPO,其他研究如RRHF、PRO等也尝试通过不同的方式优化LLMs的对齐性能。例如,RRHF通过排名响应来对齐语言模型与人类反馈,无需显式奖励函数;PRO则通过偏好排序优化实现模型对齐。这些方法从不同角度出发,为提高LLMs对齐性能提供了多样化的解决方案。

对于DPO,该论文通过理论分析揭示了DPO可能存在的根本问题。具体而言,DPO可能会找到有偏的解,这些解可能会利用分布外(out-of-distribution,OOD)的响应,导致模型行为不可预测。具体来说,DPO的优化目标可能使模型倾向于生成不在偏好数据集分布中的响应,而这些响应的质量无法得到保证。例如,在一个简单的无状态场景中,DPO可能生成一个策略,该策略对某些动作赋予较高概率,而这些动作并未在偏好数据集中得到充分覆盖。

RLHF中PPO存在哪些问题,为什么大家都设计很多方法去替代它。有哪些PPO的改进方案?

PPO在RLHF中的问题

  1. 复杂度高
    • PPO在RLHF中需要维护多个模型,包括策略模型(Actor)、奖励模型(Reward Model)、参考模型(Reference Model)和评价模型(Critic),这使得整个训练过程复杂且内存占用大。
    • PPO的训练过程对超参数非常敏感,需要大量试错来调整。
  2. 训练效率低
    • PPO的更新过程较为保守,导致收敛速度慢,尤其是在复杂环境中需要大量样本才能收敛。
    • 在大规模语言模型中,PPO的训练成本高,难以扩展。
  3. 稳定性问题
    • PPO的策略更新机制可能导致模型在复杂环境中收敛到局部最优解,或者在某些情况下难以收敛。

PPO的替代方案及改进方法

  1. 直接偏好优化(DPO)
    • 原理:DPO跳过了奖励模型的训练,直接通过优化一个反映人类偏好的损失函数来更新策略模型。
    • 优点:简化了训练过程,减少了内存占用,训练效率更高。
    • 变种
      • Iterative-DPO:通过分阶段采样和更新策略,逐步优化模型。
      • β-DPO:通过动态调整超参数β来优化训练过程。
      • SimPO:进一步简化DPO,无需参考策略,直接优化生成结果。
  2. REINFORCE Leave-One-Out(RLOO)
    • 原理:RLOO是一种在线强化学习方法,通过留一法(Leave-One-Out)优化策略,减少了GPU内存占用,并显著提高了训练速度。
    • 优点:相比PPO,RLOO在GPU内存使用上减少50%-70%,训练速度提升2-3倍,同时保持了与PPO相当的性能。
  3. 其他改进方法
    • SliC-HF:通过序列似然校准结合人类反馈,优化生成结果。
    • IPO(Identity Preference Optimization):通过身份偏好优化,直接对齐人类偏好。
    • R-DPO和SimPO:针对生成长度控制和无参考策略优化,进一步改进了DPO的性能。

总结

PPO在RLHF中虽然有效,但存在复杂度高、训练效率低和稳定性问题。为了克服这些挑战,研究者们提出了多种替代方案和改进方法,如DPO及其变种、RLOO等。这些方法通过简化训练过程、减少内存占用和提高训练效率,为大规模语言模型的对齐提供了更高效和稳定的解决方案

常见大语言模型架构与原理

以下是常见开源大模型的架构与原理:

一、基于Transformer架构的通用模型

1. BERT(Bidirectional Encoder Representations from Transformers)

  • 架构
    纯编码器结构,由多层Transformer编码器堆叠而成(通常为12-24层)。每层包含自注意力机制和前馈神经网络。自注意力机制采用双向上下文建模,即每个词可同时关注左右两侧的上下文信息110。
  • 原理
    • 预训练任务
      1. 掩码语言模型(MLM):随机遮盖输入中15%的词汇,模型需预测被遮盖的词(例如输入“I [MASK] a student”,预测“am”)。
      2. 下一句预测(NSP):判断两个句子是否为连续段落,增强模型对句子间关系的理解110。
    • 应用限制:因编码器无法生成序列,BERT在文本生成任务中表现较弱,主要用于NLU任务(如文本分类、实体识别)110。

2. GPT(Generative Pre-trained Transformer)

  • 架构
    纯解码器结构,使用单向自注意力(仅上文可见),层数随版本增加(GPT-3达96层)。采用自回归生成机制,逐词生成输出110。
  • 原理
    • 预训练任务:通过最大化序列概率预测下一个词(如输入“The cat sat”,预测“on”)。
    • 关键技术
      1. 位置编码:通过可学习参数或正弦函数嵌入词序信息,弥补Transformer的非时序性。
      2. 缩放点积注意力:引入多头注意力(如GPT-3每层96头),增强对不同语义子空间的学习12。
    • 优势与局限:生成连贯性强,但无法利用下文信息;GPT-3通过1750亿参数实现零样本学习,但对算力需求极高110。

3. T5(Text-to-Text Transfer Transformer)

  • 架构
    编码器-解码器全尺寸Transformer,编码器处理输入,解码器生成输出。采用相对位置编码,支持长序列处理110。
  • 原理
    • 统一任务框架:将各类NLP任务转换为文本到文本格式(如翻译任务输入“translate English to German: Hello”,输出“Hallo”)。
    • 预训练策略:使用“填空式”任务(Span Corruption),随机遮盖连续文本片段,模型需重构完整文本。例如输入“Thank you me to your party week”,需预测“ for inviting last”110。

4. GLM(General Language Model)

  • 架构
    混合自编码与自回归机制,支持双向注意力(编码阶段)和单向生成(解码阶段)。采用2D位置编码,区分被遮盖词的位置和生成顺序110。
  • 原理
    • 自回归填空任务:随机遮盖文本片段(如“123_56”遮盖“4”),将遮盖内容移至末尾,按顺序生成(如输入“12356 [MASK]”,生成“[START]4[END]”)。
    • 优势:兼具上下文理解(类似BERT)和生成能力(类似GPT),在长文本问答和生成任务中表现突出110。

二、国产开源大模型

1. DeepSeek系列

  • 架构
    基于Transformer改进,引入稀疏注意力机制(如局部窗口注意力),支持超长上下文(最高40万汉字)。参数规模覆盖1.3B至33B,训练数据包含87%代码和13%自然语言310。
  • 原理
    • 强化学习优化:在代码生成任务中,使用人类反馈强化学习(RLHF)优化输出逻辑性。
    • 开源策略:全栈开源(数据生成代码、训练框架、模型权重),支持消费级显卡部署310。

2. 通义千问(Qwen系列)

  • 架构
    多模态Transformer,集成文本、图像、音频编码器。Qwen-72B采用分组查询注意力(GQA),减少显存占用310。
  • 原理
    • 混合模态预训练:使用对齐的图文对和语音文本对,学习跨模态表示。
    • 轻量化设计:通过知识蒸馏(如Qwen-1.8B由Qwen-72B蒸馏而来),在低资源设备上实现高效推理310。

3. CodeGeeX

  • 架构
    基于GPT架构的代码专用模型,支持20+编程语言。采用代码语法树嵌入,增强代码结构理解17。
  • 原理
    • 多任务训练:联合训练代码补全、代码翻译(如Python转Java)、文档生成任务。
    • IDE集成:通过“Ask CodeGeeX”功能,开发者可在编码时实时问答,结合上下文生成代码片段17。

三、国际主流开源模型

1. LLaMA系列(Meta)

  • 架构
    类GPT的解码器结构,采用RMSNorm替代LayerNorm,使用SwiGLU激活函数提升非线性能力。LLaMA-2-70B参数量达700亿,训练数据2T tokens109。
  • 原理
    • 高效训练:使用因果掩码(Causal Mask)确保自回归生成,结合旋转位置编码(RoPE)增强长程依赖捕捉。
    • 开源策略:开放模型权重但限制商用,通过社区微调(如Alpaca、Vicuna)扩展应用场景109。

2. Falcon

  • 架构
    解码器结构,采用并行注意力层(Parallel Attention)减少计算延迟。Falcon-180B参数量达1800亿,训练数据3.5T tokens10。
  • 原理
    • 数据优化:使用RefinedWeb数据集,去重并过滤低质量网页内容,提升训练效率。
    • 多查询注意力(MQA):共享键值投影矩阵,降低显存占用30%10。

3. BLOOM

  • 架构
    解码器结构,参数量176B,训练数据涵盖46种语言。采用ALiBi位置编码(Attention with Linear Biases),无需显式位置嵌入10。
  • 原理
    • 多语言支持:通过词表扩展(25万token)覆盖罕见语言字符,平衡语种分布避免英语主导。
    • 可持续训练:使用绿色算力(核能供电数据中心),减少碳足迹10。

四、技术原理共性

  1. 自注意力机制:通过计算词间关联权重动态捕捉上下文依赖,替代RNN的序列处理,实现并行计算12。
  2. 位置编码
    • 绝对编码:BERT使用可学习参数,GPT-3使用正弦函数。
    • 相对编码:T5采用偏移量编码,增强长文本处理能力110。
  3. 模型缩放定律(Scaling Laws)
    性能随参数规模、数据量、算力呈幂律提升,如GPT-3验证了“大模型涌现能力”12。
  4. 分布式训练技术
    • 数据并行:分割数据至多GPU。
    • 模型并行:如Megatron-LM将层内矩阵分块计算。
    • 混合精度训练:FP16存储权重,FP32更新梯度,兼顾速度与精度210。

LLaMA在Transformer的Decoder上做了哪些改进?

1. 归一化层改进

  • 使用RMSNorm将传统的LayerNorm改为RMSNorm(Root Mean Square Layer Normalization)。RMSNorm不需要计算均值和方差,减少了计算量,并且在面对可能存在的异常值导致的均值剧烈变化时,能够使表示不那么容易受到影响,从而避免生成损坏的输出和内部协变量偏移。
  • 位置前置:将归一化层从输出层移到输入层,在将嵌入送入注意力机制和前馈神经网络之前进行归一化,有助于更快地训练收敛,使模型更好地处理输入数据,减少内部协变量偏移问题。

2. 激活函数改进采用SwiGLU激活函数代替传统的GLU或ReLU等激活函数。SwiGLU能为模型提供更丰富的非线性表达能力,有助于模型更好地学习语言中的复杂模式和语义信息,提高模型的性能和泛化能力。

3. 位置编码改进采用旋转位置编码(RoPE)。RoPE能更好地处理文本中的长序列依赖关系,使模型在处理长文本时能更准确地捕捉不同位置之间的语义关联,相比传统的正弦和余弦位置编码,在长序列场景下表现更优。

4. 上下文长度扩展LLaMA2将上下文长度由LLaMA1的2048升级到4096,LLaMA3进一步增加到8192,使模型能够理解和生成更长的文本,更好地处理长对话、长篇文章等复杂文本任务,提升了模型对长序列信息的处理能力。

5. 注意力机制改进LLaMA2的34B和70B模型以及LLaMA3所有模型采用了分组查询注意力(GQA)。通过将查询向量分组,并行计算注意力,在不降低模型性能的前提下,减少了计算量和内存占用,提高了模型的推理效率。

6. 增加KV Cache机制在计算注意力时引入了KV Cache机制,缓存之前计算过的键值对,避免重复计算,加速了生成过程,特别是在生成较长文本时,能显著提高生成速度和效率。

DDPM:

简述DDPM的算法流程:

初始化:从带噪声的图像开始。

正向扩散:逐步向数据添加高斯噪声,直到数据完全转化为无结构的噪声。

反向去噪:通过模型预测并逐渐去掉每一步加入的噪声,还原得到无噪声的图像。

训练:使用反向传播算法更新模型参数,以最小化正向和反向过程之间的差异。

测试:对新的高噪声图像应用训练好的模型进行去噪。

实现DDPM需要什么条件:

马尔可夫链:DDPM使用马尔可夫链来描述数据的扩散过程。

马尔可夫链是一个随机过程,具有无记忆性,即在给定当前状态的情况下,未来的状态只依赖于当前状态

微小变化:DDPM通过逐步添加微小的高斯噪声来扩散数据。这些微小的变化是在数据中引入随机性的关键步骤。
高斯噪声变化:DDPM使用高斯噪声来模拟数据的扩散过程。高斯噪声是一种常见的随机噪声,也称为正态分布噪声。

为什么DDPM加噪声的幅度是不⼀致的?

前期加噪少是为了保持数据结构的完整性,后期加噪多是为了加速扩散过程,使得模型能够更快地从噪声中恢复出清晰的数据。

DDPM预测噪声还是预测当前分布?

预测噪声,预测分布只是中间过程

DDIM算法原理部分:

DDIM是怎么实现加速采样的?

DDIM通过保证DDPM的三项前向条件不变:前向⾼斯噪声+⻢尔可夫链,实现逆向递推公式优化,减少逆向推理步骤

DDIM是不是确定性⽣成,为什么

是确定性⽣成。因为在逆向去噪声过程中,DDIM的逆推公式,将随机噪声的部分置为0

img

Score-Based-diffusion-model

提供了⼀种解释扩散模型的等价⽅式,其中降噪过程可以看作是沿着分数(梯度)前进

⾼阶采样⽅案:
是否了解DPM++等加速采样⽅案

通过ODE对扩散模型进⾏建模,通过解析解的形式解构扩散模型求解步骤

特征编码:

介绍⼀下CLIP编码:

CLIP(Contrastive Language-Image Pretraining) 是由 OpenAI 提出的一种多模态预训练模型,旨在将图像和文本对齐,从而实现跨模态的表示学习。CLIP 的核心思想是通过对比学习(Contrastive Learning)来学习图像和文本的联合表示,使得模型能够在零样本(zero-shot)任务中表现出色。


1. CLIP 的核心思想

(1) 对比学习(Contrastive Learning)

  • 目标:通过对比学习,使得模型能够将匹配的图像-文本对(正样本)的表示拉近,而不匹配的图像-文本对(负样本)的表示推远。
  • 方法
    • 给定一个图像-文本对,模型分别对图像和文本进行编码,得到它们的嵌入向量。
    • 通过计算嵌入向量之间的相似度(如余弦相似度),模型可以判断这对图像-文本是否匹配。
    • 训练过程中,模型会最大化正样本对的相似度,同时最小化负样本对的相似度。

(2) 联合表示学习

  • 目标:学习一个共享的嵌入空间,使得图像和文本可以在这个空间中进行比较。
  • 方法
    • 使用两个独立的编码器:一个用于图像(如 ResNet 或 Vision Transformer),一个用于文本(如 Transformer)。
    • 将图像和文本编码到同一个嵌入空间中,使得它们的表示可以直接进行对比。

2. CLIP 的训练过程

(1) 数据集

  • 训练数据:CLIP 使用了大规模的图像-文本对数据集,例如从互联网上抓取的 4 亿对图像-文本对。
  • 数据特点:数据集包含丰富的图像和对应的描述文本,涵盖了多种场景和任务。

(2) 模型架构

  • 图像编码器
    • 使用 ResNet 或 Vision Transformer(ViT)作为图像编码器。
    • 将图像编码为一个固定维度的嵌入向量。
  • 文本编码器
    • 使用 Transformer 作为文本编码器。
    • 将文本编码为一个固定维度的嵌入向量。

(3) 损失函数

  • 对比损失(Contrastive Loss)
    • 对于每个图像-文本对,计算其嵌入向量之间的相似度。
    • 使用对比损失函数(如 InfoNCE 损失)来优化模型,使得正样本对的相似度最大化,负样本对的相似度最小化。

(4) 训练目标

  • 目标:通过对比学习,使得模型能够学习到图像和文本的联合表示,从而在零样本任务中表现出色。

3. CLIP 的应用场景

(1) 零样本分类(Zero-Shot Classification)

  • 任务:在不使用任何特定任务的标签数据的情况下,直接对图像进行分类。
  • 方法
    • 使用 CLIP 的文本编码器生成类别标签的嵌入向量。
    • 使用 CLIP 的图像编码器生成图像的嵌入向量。
    • 通过计算图像嵌入向量与类别标签嵌入向量之间的相似度,选择最相似的类别作为预测结果。

(2) 图像检索(Image Retrieval)

  • 任务:根据输入的文本描述,检索与之最匹配的图像。
  • 方法
    • 使用 CLIP 的文本编码器生成文本描述的嵌入向量。
    • 使用 CLIP 的图像编码器生成图像的嵌入向量。
    • 通过计算文本嵌入向量与图像嵌入向量之间的相似度,选择最相似的图像。

(3) 文本生成图像(Text-to-Image Generation)

  • 任务:根据输入的文本描述,生成与之匹配的图像。
  • 方法
    • 使用 CLIP 的文本编码器生成文本描述的嵌入向量。
    • 使用生成模型(如 DALL·E 或 Stable Diffusion)生成图像,并使用 CLIP 的图像编码器对生成的图像进行评估。

4. CLIP 的优缺点

(1) 优点

  1. 零样本学习能力
    • CLIP 能够在没有特定任务标签数据的情况下,直接对图像进行分类。
    • 这使得 CLIP 在处理新任务时非常灵活,无需重新训练模型。
  2. 跨模态对齐能力
    • CLIP 能够将图像和文本对齐到同一个嵌入空间中,使得它们可以直接进行比较。
    • 这使得 CLIP 在图像检索、文本生成图像等任务中表现出色。
  3. 大规模预训练
    • CLIP 使用了大规模的图像-文本对数据集进行预训练,使得模型具有很强的泛化能力。
    • 这使得 CLIP 在多种任务中都能取得很好的效果。
  4. 灵活性
    • CLIP 可以与多种下游任务结合,如分类、检索、生成等。
    • 这使得 CLIP 成为一个通用的多模态工具。

(2) 缺点

  1. 数据需求高
    • CLIP 需要大规模的图像-文本对数据集进行预训练,数据获取和处理成本较高。
    • 对于某些特定领域,可能难以获取足够的高质量数据。
  2. 计算资源消耗大
    • CLIP 的预训练过程需要大量的计算资源,尤其是在使用大规模数据集时。
    • 这使得 CLIP 的训练成本较高。
  3. 对噪声敏感
    • CLIP 的预训练数据集可能包含噪声(如错误的图像-文本对),这可能会影响模型的性能。
    • 需要对数据进行严格的清洗和筛选。
  4. 零样本性能有限
    • 尽管 CLIP 在零样本任务中表现出色,但在某些特定任务中,其性能可能不如专门训练的模型。
    • 对于某些复杂的任务,可能需要额外的微调或数据增强。

5. 总结

  • CLIP 是一种基于对比学习的多模态预训练模型,能够将图像和文本对齐到同一个嵌入空间中,从而实现跨模态的表示学习。
  • 优点
    • 零样本学习能力强,跨模态对齐能力出色,适用于多种任务。
  • 缺点
    • 数据需求高,计算资源消耗大,对噪声敏感,零样本性能有限。

CLIP 的出现为多模态学习和跨模态任务提供了一种强大的工具,尤其在零样本分类和图像检索等任务中表现出色。然而,其高昂的训练成本和数据需求也限制了其在某些场景中的应用。

Stable Diffusion篇:

Stable Diffusion 的核⼼优化?

通过VAE将特征映射到Latent Space,⼤幅减少运算量的同时还能保证⽣成质量。

通过Unet实现对⽣成内容的引导

Stable Diffusion 怎么训练的?

从训练集中选取一张加噪的图片和噪声强度,让unet预测噪声图,并计算和真正的噪声图之间的误差,并通过反向传播更新unet的参数

VAE为什么会导致图像变模糊

VAE 编解码整体是⼀个有损过程,可以选择减少损失,⽐如优化模型结构,提升采样效率等。

介绍⼀下SD,Dall-E2两者的异同

Dalle2通过自回归的方式逐个预测像素点,最终生成符合描述的图像。

SD加⼊了Latent-Space(⼤幅降低特征维度),以及交叉注意⼒机制+Unet的步骤,更精细更可控

Noise Scheduler了解吗

Noise Scheduler定义了⼀个⾼斯分布,其均值和⽅差随着时间步的变化⽽变化,以控制噪声的添加量

Stable Diffusion核⼼模块

VAE:将图像特征/⽂本特征,映射到Latent Space。

LDM相关:Diffusion Model +Unet,去噪声核⼼步骤

Conditioning:作⽤于Unet的 Cross-Attention位置,实现对输出结果的控制

大模型名词:

大模型训练过程

AI大模型的训练是一个复杂的过程,涉及多个阶段和优化技巧。以下是详细的训练过程:

1. 数据准备:

  • 数据收集: 首先需要收集大规模的训练数据,通常包括文本、图像、音频等多种模态的数据。
  • 数据清洗: 对数据进行清洗,去除噪声、重复数据和无效数据。
  • 数据标注: 对于监督学习任务,需要对数据进行标注,例如文本分类任务中的标签。
  • 数据增强: 通过数据增强技术(如文本数据中的同义词替换、图像数据中的旋转和裁剪)来增加数据的多样性。

2. 模型架构:

  • Transformer架构: 大多数AI大模型采用Transformer架构,包括多头自注意力机制和前馈神经网络。
  • 层数和参数规模: 大模型通常具有数十亿甚至数千亿个参数,层数可以达到上百层。
  • 多模态融合: 对于多模态任务,模型需要融合不同模态的数据,例如文本和图像的联合表示。

3. 训练策略:

  • 预训练: 首先在大规模无监督数据上进行预训练,目标是学习通用的语言或视觉表示。预训练任务通常是自回归语言建模(如GPT)或掩码语言建模(如BERT)。
  • 微调: 在预训练完成后,模型会在特定任务上进行微调,例如文本分类、图像分类或对话生成。微调时,使用较小的学习率和特定任务的数据集。
  • 多任务学习: 在某些情况下,模型会在多个任务上同时进行训练,以提高泛化能力。

4. 优化技巧:

  • 混合精度训练: 使用FP16(半精度浮点数)进行计算,以加速训练并减少显存占用。
  • 梯度累积: 通过累积多个小批量的梯度,模拟更大的批量大小,从而提高训练稳定性。
  • 分布式训练: 使用多台机器和多个GPU进行分布式训练,以加速训练过程。常见的分布式训练策略包括数据并行和模型并行。
  • 正则化: 使用Dropout、权重衰减等正则化技术,防止模型过拟合。

5. 评估与调优:

  • 验证集评估: 在训练过程中,使用验证集评估模型的性能,调整超参数(如学习率、批量大小)。
  • 早停: 当验证集性能不再提升时,提前停止训练,防止过拟合。
  • 模型剪枝和量化: 在训练完成后,可以对模型进行剪枝和量化,以减少模型的大小和推理时间。

Lora:

LoRA(Low-Rank Adaptation)是一种用于大模型微调的技术,旨在减少微调过程中需要更新的参数量,从而降低计算资源和存储成本。其核心思想是将模型的权重更新分解为低秩矩阵的乘积。

原理:

  • 在大模型的全参数微调中,通常需要更新整个模型的权重,这会导致存储和计算成本非常高。LoRA通过引入低秩分解的思想,将权重更新分解为两个低秩矩阵的乘积,即:

    ΔW=A×BΔW=A×B

    其中,ΔWΔW 是权重更新矩阵,AA 和 BB 是低秩矩阵,秩通常远小于原始权重矩阵的维度。

  • 在微调过程中,只需要训练 AA 和 BB 这两个低秩矩阵,而原始模型的权重保持不变。这样,微调所需的参数量大幅减少,计算效率显著提高。

应用场景:

  • LoRA广泛应用于大模型的微调任务,尤其是在资源受限的情况下。例如,在自然语言处理任务中,可以使用LoRA对GPT或BERT等大模型进行微调,而无需更新整个模型的权重。
  • 此外,LoRA还可以用于多任务学习,通过为每个任务训练不同的低秩矩阵,实现任务间的参数共享。

实现细节:

  • 在实现上,LoRA通常通过在模型的全连接层或注意力机制中插入低秩矩阵来实现。具体来说,可以在Transformer的注意力头或前馈神经网络中应用LoRA。
  • 训练时,只更新低秩矩阵 AA 和 BB,而原始模型的权重保持冻结。
  • 在推理时,将低秩矩阵的乘积加到原始权重上,生成最终的权重矩阵。

ChatGLM

ChatGLM是一个基于Transformer架构的中文对话生成模型,专门针对中文语言进行了优化。其核心原理和结构与GPT类似,但在训练过程中引入了一些针对中文的改进。

原理:

  • ChatGLM基于自注意力机制(Self-Attention)和Transformer架构,能够捕捉输入序列中的长距离依赖关系。
  • 与GPT类似,ChatGLM是一个自回归模型,通过预测下一个词来生成文本。

模型结构:

  • 编码器-解码器结构: ChatGLM采用了类似GPT的单向Transformer结构,但也可以扩展为编码器-解码器结构,用于生成对话回复。
  • 多头自注意力机制: 每个Transformer层包含多头自注意力机制,能够并行处理输入序列中的不同部分。
  • 前馈神经网络: 在每个注意力层之后,会接一个前馈神经网络,用于进一步处理特征。
  • 位置编码: 使用位置编码来捕捉输入序列中的位置信息,确保模型能够理解序列的顺序。

训练过程:

  • 预训练阶段:

    • ChatGLM首先在大规模中文语料上进行预训练,目标是学习语言的通用表示。
    • 预训练任务通常是自回归语言建模,即根据前面的词预测下一个词。
    • 训练过程中,使用大量的中文文本数据,包括书籍、新闻、对话等。
  • 微调阶段:

    • 在预训练完成后,ChatGLM会在特定任务上进行微调,例如对话生成任务。
    • 微调时,使用对话数据集,目标是让模型学会生成自然流畅的对话回复。
    • 微调过程中,通常会使用较小的学习率,以避免破坏预训练阶段学到的知识。
  • 优化技巧:

    • 在训练过程中,ChatGLM可能会使用混合精度训练(Mixed Precision Training)来加速训练并减少显存占用。
    • 此外,可能会使用梯度累积(Gradient Accumulation)来模拟更大的批量大小,从而提高训练稳定性。

P-tuning

P-Tuning是一种用于大模型微调的技术,旨在通过插入可训练的“提示”(Prompt)来引导模型生成特定任务的输出,而无需更新整个模型的权重。

原理:

  • P-Tuning的核心思想是通过在输入序列中插入可训练的提示向量(Prompt Vectors),来引导模型生成特定任务的输出。
  • 这些提示向量是可训练的参数,而模型的原始权重保持冻结。通过优化提示向量,模型可以在不更新大量参数的情况下,适应新的任务。

应用场景:

  • P-Tuning广泛应用于自然语言处理任务中,例如文本分类、问答系统、对话生成等。
  • 它特别适合资源受限的场景,因为只需要训练少量的提示向量,而不需要更新整个模型的权重。

实现细节:

  • 提示插入: 在输入序列中,P-Tuning会在特定位置插入提示向量。例如,在文本分类任务中,可以在输入文本的开头插入提示向量。
  • 提示训练: 提示向量是可训练的参数,通常通过梯度下降法进行优化。训练过程中,只更新提示向量,而模型的原始权重保持不变。
  • 提示设计: 提示向量的设计可以非常灵活,可以是固定的模板(如“这个句子是关于[MASK]的”),也可以是可学习的向量。
  • 推理阶段: 在推理阶段,提示向量会被固定,模型根据提示向量生成输出。

SFT

SFT(Supervised Fine-Tuning)是一种在大模型预训练完成后,使用标注数据进行微调的技术。其目标是让模型在特定任务上表现更好。

原理:

  • SFT的核心思想是利用标注数据对预训练模型进行微调,使其适应特定任务。
  • 与无监督预训练不同,SFT使用的是有监督数据,即每个样本都有明确的标签。

应用场景:

  • 文本分类: 例如情感分析、垃圾邮件检测等任务,模型需要根据输入文本预测类别标签。
  • 问答系统: 模型需要根据问题生成答案,通常使用问答数据集进行微调。
  • 对话生成: 在对话系统中,模型需要根据上下文生成自然的对话回复。
  • 机器翻译: 模型需要将一种语言的文本翻译成另一种语言。

实现细节:

  • 数据准备: 首先需要准备特定任务的标注数据集,例如文本分类任务中的文本和标签。
  • 模型初始化: 使用预训练模型的权重作为初始权重,避免从头开始训练。
  • 微调策略:
    • 学习率调整: 通常使用较小的学习率,以避免破坏预训练阶段学到的知识。
    • 冻结部分层: 在某些情况下,可以冻结模型的前几层,只微调最后几层,以减少计算量。
    • 批量大小: 根据硬件资源调整批量大小,通常较大的批量大小可以提高训练稳定性。
  • 损失函数: 根据任务类型选择合适的损失函数,例如交叉熵损失用于分类任务,均方误差损失用于回归任务。
  • 评估与调优: 在微调过程中,使用验证集评估模型的性能,调整超参数以获得最佳效果。

优势:

  • 高效性: SFT可以在较短的时间内使模型适应特定任务,而不需要重新训练整个模型。
  • 灵活性: SFT可以应用于多种任务,只需准备相应的标注数据集。
  • 性能提升: 通过SFT,模型在特定任务上的性能通常会显著提升。

RAG

RAG(Retrieval-Augmented Generation,检索增强生成) 是一种结合了信息检索技术和语言生成模型的人工智能技术。它通过从外部知识库中检索相关信息,并将其作为提示(Prompt)输入给大型语言模型(LLM),以增强模型处理知识密集型任务的能力。

RAG的工作原理

RAG的工作流程主要包括三个步骤:

  1. 检索(Retrieval):根据用户的查询内容,从外部知识库中检索出与查询最相关的文档或信息。
  2. 增强(Augmentation):将检索到的相关信息与用户的查询内容结合,形成增强后的上下文。
  3. 生成(Generation):将增强后的上下文输入到大型语言模型中,生成所需的输出。

RAG的优势

  • 提高准确性:通过检索外部知识库,RAG能够提供更准确、更相关的回答。
  • 减少幻觉:RAG通过检索真实信息,减少了大语言模型生成幻觉的可能性。
  • 即时更新:无需重新训练模型,即可通过更新知识库来获取最新信息。
  • 可解释性:RAG的生成结果基于检索到的信息,具有更强的可解释性。
  • 数据安全:RAG可以使用私有知识库,避免了将敏感数据上传到第三方平台进行训练。

1. 原理

  • 检索与生成的结合:
    • RAG的核心是将检索模块和生成模块结合在一起。检索模块负责从外部知识库(如文档、数据库或网页)中检索与输入相关的信息,生成模块则利用这些检索到的信息生成最终的输出。
    • 检索模块通常是一个基于向量搜索的系统,能够快速找到与输入最相关的文档或片段。
    • 生成模块通常是一个预训练的语言模型(如GPT、T5或BERT),负责根据输入和检索到的信息生成输出。
  • 外部知识的引入:
    • 传统的生成模型(如GPT)依赖于模型内部的知识,而RAG通过引入外部知识库,能够更好地处理需要外部知识支持的任务(如问答、对话生成等)。
    • 检索到的信息可以作为生成模型的额外输入,帮助模型生成更准确、更丰富的输出。

2. 架构

RAG的架构通常包括以下几个核心组件:

(1) 检索模块

  • 输入处理: 输入(如问题或查询)首先被编码为一个向量,通常使用预训练的编码器(如BERT或Sentence-BERT)。
  • 向量搜索: 编码后的向量被用于在知识库中进行相似度搜索,找到与输入最相关的文档或片段。
  • 知识库: 知识库通常是一个大规模的文档集合,可以是结构化数据(如数据库)或非结构化数据(如网页、书籍)。

(2) 生成模块

  • 预训练语言模型: 生成模块通常是一个预训练的语言模型(如GPT、T5),负责根据输入和检索到的信息生成输出。
  • 输入融合: 检索到的信息被融合到生成模型的输入中,通常以文本片段的形式附加到输入序列中。
  • 输出生成: 生成模型根据融合后的输入生成最终的输出。

(3) 端到端训练

  • 联合优化: RAG的检索模块和生成模块可以进行联合训练。生成模块的损失函数(如交叉熵损失)不仅依赖于生成输出,还依赖于检索模块的输出。
  • 检索模块的优化: 检索模块可以通过生成模块的反馈进行优化,例如通过强化学习或梯度传播来调整检索策略。

3. 训练过程

(1) 数据准备

  • 训练数据: 训练数据通常包括输入(如问题或查询)和对应的输出(如答案或回复)。此外,还需要一个知识库,包含与输入相关的文档或片段。
  • 标注数据: 在某些情况下,训练数据可能需要标注检索到的信息是否与输入相关。

(2) 检索模块训练

  • 预训练检索模块: 检索模块通常使用预训练的编码器(如BERT)进行初始化,并通过对比学习或排序任务进行训练。
  • 向量索引构建: 知识库中的文档被编码为向量,并存储在向量数据库中,以便进行快速检索。

(3) 生成模块训练

  • 预训练生成模块: 生成模块通常是一个预训练的语言模型(如GPT或T5),在RAG中可以直接使用,也可以进行微调。
  • 联合训练: 检索模块和生成模块可以进行联合训练。生成模块的损失函数不仅依赖于生成输出,还依赖于检索模块的输出。

(4) 推理阶段

  • 检索: 在推理阶段,输入被编码为向量,并在知识库中进行检索,找到与输入最相关的文档或片段。
  • 生成: 检索到的信息被融合到生成模型的输入中,生成模型根据融合后的输入生成最终的输出。

4. 应用场景

RAG的应用场景非常广泛,尤其是在需要外部知识支持的任务中表现出色。以下是一些典型的应用场景:

(1) 问答系统

  • 开放域问答: RAG可以用于开放域问答任务,例如从维基百科或文档集合中检索相关信息,并生成准确的答案。
  • 知识密集型问答: 对于需要外部知识支持的问题(如科学问题、历史问题),RAG能够通过检索相关文档生成更准确的答案。

(2) 对话系统

  • 知识增强对话: 在对话系统中,RAG可以通过检索相关信息(如产品信息、新闻)来生成更丰富和准确的回复。
  • 多轮对话: RAG可以处理多轮对话,通过检索上下文相关的信息来生成连贯的回复。

(3) 文本生成

  • 文档摘要: RAG可以用于文档摘要任务,通过检索文档中的关键信息生成简洁的摘要。
  • 内容创作: RAG可以用于生成高质量的内容,例如新闻报道、产品描述等。

(4) 信息检索

  • 语义搜索: RAG可以用于语义搜索任务,通过检索与查询最相关的文档或片段,提供更精准的搜索结果。
  • 知识图谱补全: RAG可以用于知识图谱的补全任务,通过检索相关信息生成缺失的实体或关系。

5. 优缺点

优点:

  • 知识增强: RAG通过引入外部知识库,能够生成更准确和丰富的输出,尤其适用于需要外部知识支持的任务。
  • 灵活性: RAG可以与不同的检索模块和生成模块结合,适用于多种任务和场景。
  • 可解释性: 由于检索模块的存在,RAG的输出通常具有一定的可解释性,用户可以查看检索到的信息。

缺点:

  • 计算成本高: RAG的检索和生成过程通常需要较多的计算资源,尤其是在处理大规模知识库时。
  • 检索效率: 检索模块的效率可能成为瓶颈,尤其是在实时应用中(如对话系统)。
  • 知识库维护: 知识库的维护和更新是一个挑战,需要定期更新以确保检索到的信息是最新的。

总结

RAG 是一种结合检索和生成的模型架构,通过引入外部知识库来增强生成模型的能力。它在问答、对话生成、文本生成等任务中表现出色,尤其适用于需要外部知识支持的场景。

RAG的训练过程包括检索模块和生成模块的联合训练,推理阶段通过检索相关信息并融合到生成模型中,生成最终的输出。尽管RAG在知识增强和灵活性方面具有显著优势,但其计算成本和检索效率仍是需要解决的问题。

搜广推

推荐算法常用评价指标:NDCG、MAP、MRR、HR、ILS、ROC、AUC、F1等_推荐算法常用指标-CSDN博客

img

解释一下多任务学习(Multi-task Learning)的概念,并讨论其在广告推荐系统中的应用

多任务学习(Multi-task Learning, MTL)的概念

1. 定义

多任务学习是一种机器学习方法,旨在同时学习多个相关任务,通过共享表示(shared representation)或模型参数,使得模型能够从多个任务中相互学习,从而提高每个任务的性能

多任务学习的核心思想是利用任务之间的相关性,使得模型能够更好地泛化,并减少过拟合

2. 关键特点

  • 任务相关性:多任务学习中的任务通常是相关的,例如,一个任务的特征可能对另一个任务也有帮助。通过同时学习多个任务,模型可以利用这些相关性来提升性能。
  • 共享表示:模型通过共享隐藏层或参数,使得不同任务能够从彼此的经验中受益。这种共享可以是硬共享(hard sharing),即所有任务共享相同的模型参数;也可以是软共享(soft sharing),即任务之间通过某种机制共享信息。
  • 联合优化:多任务学习通常通过联合优化多个任务的损失函数来训练模型。损失函数通常是多个任务损失的加权和,权重可以根据任务的重要性进行调整。

多任务学习在广告推荐系统中的应用

1. 广告推荐系统中的多任务学习场景

在广告推荐系统中,多任务学习可以应用于多个相关任务,例如:

  • 点击率预测(CTR Prediction):预测用户是否会点击某个广告。
  • 转化率预测(CVR Prediction):预测用户点击广告后是否会进行购买或其他转化行为。
  • 曝光时长预测(Impression Duration Prediction):预测用户对广告的关注时间。
  • 用户兴趣建模:建模用户的长期和短期兴趣,以更好地推荐符合用户兴趣的广告。

2. 多任务学习的优势

  • 提升模型性能:通过同时学习多个任务,模型可以利用不同任务之间的相关性,提升每个任务的性能。例如,点击率和转化率之间存在相关性,联合学习可以更好地捕捉这种关系。
  • 减少过拟合:多任务学习通过引入多个任务的约束,使得模型更加健壮,减少过拟合的风险。
  • 提高资源利用效率:在资源有限的情况下,多任务学习可以更高效地利用数据和计算资源,同时优化多个任务。

3. 多任务学习的实现方式

  • 共享特征表示:在广告推荐系统中,用户和广告的特征通常可以共享。例如,用户的历史行为数据、广告的属性等特征可以同时用于点击率预测和转化率预测。
  • 联合优化:通过联合优化多个任务的损失函数,模型可以同时学习多个任务。例如,损失函数可以是点击率预测损失和转化率预测损失的加权和。
  • 任务特定的层:在模型架构中,可以为每个任务设计特定的层,以捕捉任务特定的信息。同时,通过共享隐藏层,模型可以利用任务之间的相关性。

4. 实际应用案例

  • 联合预测点击率和转化率:在广告推荐系统中,同时预测点击率和转化率可以提高广告投放的效率。通过多任务学习,模型可以更好地捕捉用户的行为模式,从而更准确地预测用户的点击和转化行为。
  • 多目标优化:在广告推荐中,除了点击率和转化率,还可以考虑其他目标,如曝光时长、用户满意度等。通过多任务学习,模型可以同时优化多个目标,从而实现更全面的推荐效果。

总结

多任务学习通过同时学习多个相关任务,利用任务之间的相关性,提升模型的性能和泛化能力。在广告推荐系统中,多任务学习可以应用于点击率预测、转化率预测等多个任务,通过共享特征表示和联合优化,提高推荐系统的准确性和效率。

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码

请我喝杯咖啡吧~

支付宝
微信