参考:全面解析:从AI原理到模型演进及代码实践-CSDN博客
初探神经网络(原理)
上图就是一个人脑的神经元,由多个树突、轴突和细胞核构成,其中树突用来接收电信号、经细胞核加工(激活)信号、最后由轴突输出电信号,人脑大概860亿个神经元细胞,突触相互连接,形成拓扑结构。
每个神经元大约有1163~11628个突触,突触总量在14~15个数量级,放电频繁大约在400~500Hz,每秒最高计算量大约40万亿次,换算成当前流行词汇,大脑大概等价于100T参数模型(140B逊爆了),而且有别当前大模型中ReLU激活函数,大脑惰性计算是不用算0值的,效率更高。
ReLU(Rectified Linear Unit,修正线性单元)激活函数是神经网络中一种常用的非线性激活函数。它的定义非常简单:
这意味着对于输入的任何值,如果该值大于0,则ReLU函数输出该值;如果该值小于或等于0,则输出0。
ReLU函数因其计算效率高、能够帮助缓解梯度消失问题而在深度学习领域得到了广泛应用。与sigmoid和tanh等传统激活函数相比,ReLU在正数区域不会导致信息的大幅度衰减,从而允许更深的网络训练。不过,ReLU也有其缺点,比如可能导致某些神经元永远不会被激活的问题(即"死亡ReLU"问题),这是因为当输入为负时,ReLU会输出0,并且在反向传播过程中,梯度也会变为0,这样就可能阻碍了这部分网络的学习过程。为了克服这个问题,一些ReLU的变体如Leaky ReLU、Parametric ReLU等也被提出。
惰性计算(Lazy Evaluation) :这是编程语言理论中的一个概念,指的是推迟表达式的求值直到真正需要其结果的时候。这种方式可以提高程序效率,避免不必要的计算,并允许处理理论上无限的数据结构。如果将此概念类比到大脑工作方式上,可以说大脑也倾向于只在必要时才处理特定信息,而不是预先处理所有可能遇到的信息。
神经网络就是借鉴了人脑神经元输入、计算、输出架构和拓扑设计,下面以一个求解数学问题的例子,看神经网络的实现原理:
当X为
Y为
通过训练神经网络,以求得X和Y的隐含关系
并给出X为
时,Y的值。
f(x)=x1*w1+x2*w2+b,其中w1=w2=1, b=6.6260693,实际上是可以任意 f(x)
训练过程如下:
-
对输入的X,分解成n个向量(举例方便,实际是直接矩阵计算,实现batch),对每个向量的X1和X2元素,假定一个函数 f(x)=x1*w1+x2*w2+b 进行计算(其中w1、w2和b用随机值初始化)。
-
用假定的 f(x) 计算X,得到结果和样本Y进行比照,如果有差异,调整w1、w2和b的值,重复计算。
-
直到差异收敛到某个程度后(比如小于1),训练结束
从训练过程看,经过99轮重复计算和调整W/B值后(训练),在100轮通过瞎猜求得 f(x)=x1*0.9991+x2*0.9853+6.3004 ,用最后一个组数据 X 计算得到的已经很接近样本数据,说明这些参数(模型)在这个场景已经对 *f(x)*求得最优解了。
Inference 在统计学和机器学习中,推理是指使用模型从数据中得出结论的过程。这包括但不限于:
- 参数估计:基于观测数据估计模型的参数。
- 预测:使用训练好的模型对新数据进行预测。
- 假设检验:评估某个假设是否合理。
对X (-6.8579 7.6980)进行预测Y为 7.0334,和最初假定(w1=w2=1,b=6.6260693)参数计算得到的结果仅相差0.2左右,预测结束。
损失函数&梯度下降
在训练过程中,会不断的通过调整W和B参数进行模型构建,进行目标拟合,得出参数过程需要解决两个问题:
-
如何判断收敛状态
-
如何参数调整方向和值
判断参数在每轮的收敛状态是通过一个叫损失函数(Loss Function)来完成的。即,判断 f(x)=w*x+b 的w和b是否最优解,只需要衡量真实值(训练样本值)g(x) 和测量值(训练结算值)*f(x)*的均方误差
是否是最小值(显然趋于0为最小时)。
上面代码中的loss_fn = nn.MSELoss(),这里的MSELoss就是指均方误差损失函数:
参数的调整(加多少,减多少)是通过梯度下降方式实现的,也就是通过求一阶导数,来看函数单调性(一阶导数>0,函数单调递增,函数值随自变量的增大而增大)。
一阶导数是微积分中的一个基本概念,它描述了一个函数在某一点上的瞬时变化率或斜率。具体来说,如果有一个函数 y=f(x)y=f(x),那么这个函数在 xx 点的一阶导数记作 f′(x)f′(x) 或 dydxdxdy,表示当输入值 xx 发生微小变化时,输出值 yy 的相应变化率。
几何意义
从几何角度来看,一阶导数代表了函数图像上某一点处切线的斜率。如果导数为正,则函数在该点附近是增加的;如果导数为负,则函数在该点附近是减少的;如果导数为零,则说明该点是一个局部极值点(可能是极大值点或极小值点)。
计算方法
对于一些常见的函数形式,可以直接应用导数的基本公式来计算其一阶导数。例如:
当w初始值为1.8时,L'=11.417163316>0,在局部单调递减下,w值的调整方向应该是左,也就是w=1.8-s(比如1.5)。
方向确定后,每次迭代调整的值,就变成在w轴上无限趋近极值的导数值,在曲率大的地方大幅快速,小的地方小幅趋近。
无法同时得出w1、w2和b的最优解,也就是全局最优解是无法得出的,最理想的情况就是假定w2和b为最优解的情况下,求w1最优解,然后再已w1最优解和假定b为最优解的情况下,求w2最优解,这样求出来的是局部最优解。
W 和 B
上面的例子是最简单的单层(浅层)神经网络,其中神经元是神经网络中最基本的单元,最小设定就是 f(x)=x*w+b ,通过拓扑设计来满足不同输入输出矩阵形状和拟合度(对可能的任意f(x)拟合)。
拟合度(Goodness of Fit)是统计学中的一个概念,用于衡量一个模型或一组预测值与实际观测值之间的吻合程度。简单来说,它评估的是你的数据模型在解释数据变异方面做得有多好。
常用的衡量拟合度的方法包括:
-
R平方(R²):也称为确定系数,R²表示模型解释的变异量占总变异量的比例。R²的值介于0和1之间,值越接近1表示模型的拟合度越好。
-
卡方检验(Chi-Square Test):常用于分类数据,用来判断观察到的频数分布与期望的频数分布之间的差异是否显著。
-
均方误差(Mean Squared Error, MSE):衡量观测值与真实值偏差的平方的平均值。MSE越小,表示预测值与实际值之间的差距越小,即拟合度越高。
-
残差图(Residual Plot):通过绘制预测值与实际值之差(即残差)来直观地展示模型的拟合情况。一个好的模型应该有随机分散的残差。
-
对数似然比检验(Log-Likelihood Ratio Test):比较两个模型的拟合优度,通常用于嵌套模型之间的比较。
这个模型对问题求可能的解、接近最优解的解以及最优解,不是函数在数学意义的上解。模型中W代表着权重(weight),B代表着阈值(threshold),当一或者多个input经过一个神经元最终输出一个output过程中,通过W调整不同input做加权,最后通过B控制输出的偏移完成整个计算的抽象。
激活函数
训练多层网络,不断迭代微调W和B时,只返回0和1是无法实现0到1之间的状态决策逻辑
为了让输出能够平滑0到1的中间态,需要对结果进行连续性,对y进行改造成
改造后,原先[0,1]被转换成(0,1),形成一个连续性结果。
Sigmoid激活函数,优点输出空间在(0, 1),缺点是左右两侧导数趋0,会出现梯度消失(下文讲),不利于训练,其他的主流的激活函数还有ReLU f(x)= max(0, x) ,tanh、ELU等函数。
Sigmoid激活函数是深度学习和神经网络中常用的非线性激活函数之一。它的数学表达式如下:
这个函数将输入的实数值映射到(0, 1)区间内,这使得它在某些情况下可以被解释为概率得分。Sigmoid函数具有以下特点:
- 输出范围:Sigmoid函数的输出值域在(0, 1)之间,适合用于二分类问题中的概率预测。
- 平滑可导:该函数在整个定义域上都是连续且可微的,其导数可以用原函数的形式表示,即 f′(x)=f(x)(1−f(x)),这对于使用梯度下降方法进行权重更新非常有用。
- 非线性变换:引入非线性因素,使神经网络能够学习数据中的复杂模式。
然而,Sigmoid函数也有一定的局限性:
- 梯度消失问题:当输入值很大或很小时,Sigmoid函数的梯度接近于0,这会导致在反向传播过程中权重更新缓慢,特别是在深层网络中可能会导致"梯度消失"问题,从而阻碍网络的学习。
- 计算效率:由于Sigmoid函数涉及指数运算,相比一些其他激活函数(如ReLU),计算上可能更耗时
激活函数主要是讲结果非线性化,放大参数对特征识别的灵敏和多样性,不同的激活函数除了非线性转换外,主要的区别是计算效率,解决梯度消失,中心值偏移这些问题。
当输入是多维信息,例如一个人身高、年龄、工作、发量等等的时候,期望输出也是多维,例如感兴趣科目、愿意购买商品等等时,就需要讲神经元重新规划拓扑结构,实现线性变化,形成类似下面复杂的网状结构。
当为了更好的拟合,以及引入运行时中间计算,也会调整拓扑,所以实际上整个网络会变得异常庞大(深层神经网络),例如ChatGPT4有1.8万亿的参数,这里的参数就是指训练后W和B的总和(红线部分),一共1.8万亿。这些训练后(包括fine-tuning)的参数被全部持久化后,大概代表已经吸收多少知识储备和推理潜力。
在此gpt之前,图片识别、NLP等场景已经有成熟的CNN、RNN等神经网络模型,但这两种神经网络存在的两个问题限制了模型应用的突破。
CNN和RNN已经具备通过神经网络实现分类、预测能力,但是存在两个典型问题:
-
CNN聚焦局部信息,丢失全局信息。
-
RNN无法并行计算(串行模式理论上确实也可以做到窗口无限大,然后从左到右把全部信息带过来,效率太差)。
在2017年的时候,Google的翻译团队发布了一篇 Attention Is All You Need 论文,提出了Transformer模型
相比CNN和RNN,Transformer在复杂度是最低的,效率极高,他的核心就是 Attention Mechanism(机制), 相比RNN,可以从整文视角看每个词以及这个词在上下文的意义是什么。
transformer也是通过训练(瞎猜)构建f(x),实现包括文本分类(mode1)、生成下个句子预测(mode2)、翻译任务(mode3)。
输入的处理(Embedding)
在计算之前需要对输入进行处理来解决几个问题:
-
输入可被用于数学计算
-
编码信息"足够稠密",能够承载训练过程中,学习的知识图谱
例如对"半"、"臧"、"真"、"帅"这4个词编码形成字典表(也可以"半"=1,"臧"=2,序列编码,one-hot只是为了计算简单)可以解决计算问题,但基于5个维度编码,并且每个元素只有0/1是不够支持训练过程中产生的内容,eg."半"和"臧"连起可以表示一个人名,"真"是形容词等,最简单的解决方法是把维度扩充,再增加词性、关联性维度,当训练内容复杂后,会指数级增加计算量。
所以最适中的方式是控制维度,稠密元素,也就是把[1 0 0 0]降维成[0.39847],也就是"低维稠密"向量化了(实际上降低1维是不够的,gpt2默认时768维)。
当输入被向量化,可以承载的内容也就变得很多,比如说向量的空间特性,cosine两个向量,可以从空间上判断其相似性,值接近1表示相似,反之依然,0为相交或不相关。
在数学中,余弦(Cosine)是一个三角函数,用于描述直角三角形中两个边长之间的比例关系。
当我们把每个字/词,都向量化后,比如"半",按照名词、动作、是否王室、阿里4个维度向量化后形成一个[-0.1596, 0.3930, 0.6364, 0.2324]词向量,同样完成"臧"字的词向量,就可以在判断"半"和"臧"之间的在表述一个事物、是否王室成员上存不存在联系。
用斯坦福的GloVe模型embedding后的英文单词编码,用一些可视化方法可以看到:
-
所有这些单词都有一条直的红色列,它们在这个维度上是相似的(名词维度)
-
"woman"和"girl"在很多地方是相似的,"man"和"boy"也是一样(性别维度)
-
"boy"和"girl"也有彼此相似的地方,但这些地方却与"woman"或"man"不同。(年龄维度)
当我们有了这样一份词向量表后,再去训练模型时,已经包含了词与词之前的某种联系,可以更好的达到训练目标
先把所有中文进行名字维度、动词维度、名词维度向量化后训练,然后再给予样本进行监督训练,将更准确
实际上,在tranformer中,虽然不是一定需要这些已经训练好(Pre-training)的向量表,但思路是一样的。
Tranfromer本身就可以训练这样的词向量表,已满足下一个词的预测目标,当我们有明确的训练目标,也不需要这样按照预定目标训练的词向量表,比如说我们自己训练一个类似BERT的模型,通过周围的词来预测完形填空试卷,____是法国的首都,通过一个模型训练词的上下文联系性之后,形成特定的词向量表。
Embedding用一个低维稠密的向量"表示"一个对象
以翻译"LLM with banzang"为例, 在gpt2中,整个Embedding过程如下:
对输入X(LLM with banzang)进行分词:"LL","M","with","ban","z","ang";
查询分词在gpt词库中的索引列表:3069, 44, 351, 3958, 89, 648;
对索引列表向量化:经过一个全连接层(后面讲,可以理解经过 x*w+b ),形成6*768的矩阵。
Embedding过程代码如下:
实际上更底层,索引被向量化的过程,还包含两个细节:
索引到向量过程,并没有按论文算法实现,而是直接随机初始了w参数,然后起了一层前馈层训练出768维度的最终值(暴力美学)
出了词向量外,还叠加了词位置向量(position embedding),来解决相同词在不同位置的语意不同.
在自然语言处理(NLP)中用于生成位置编码的方法,这种编码方式主要用于Transformer模型等需要理解句子中单词顺序的架构。让我们逐步解析这段话的关键点:
-
位置编码的生成 :对于每个词的位置
pos
和词向量维度i
,根据i
是奇数还是偶数分别使用正弦或余弦函数来生成位置编码。具体来说,对于奇数维度(如i
为奇),使用正弦函数: 对于偶数维度(如i
为偶),使用余弦函数:其中,
d
是词向量的维度(例如768),pos
是词语在句子中的位置。 -
固定长度的表示:无论输入句子的长度如何,通过这种方法生成的位置编码都具有固定的维度,这使得它可以与词嵌入直接相加,从而保持了整个模型输入的一致性。
-
缩放至[-1, 1]:由于正弦和余弦函数的值域都是[-1, 1],这意味着所有位置编码都被限制在这个范围内,有助于模型训练时的数值稳定性和效率。
-
周期性和相对位置信息 :正弦和余弦函数的周期性意味着即使位置偏移了一个固定量
k
,新的位置编码PE(pos+k)
可以表示为原位置编码PE(pos)
的线性组合。这使得模型能够学习到词语之间的相对位置关系,而不是仅仅依赖于它们的绝对位置。这对于捕捉句子中词语间的依赖关系非常有用。 -
直接相加得到最终嵌入:最后,生成的位置编码直接与词嵌入相加以获得最终的嵌入表示。这样做的好处是它允许模型在不增加额外复杂度的情况下考虑词语的位置信息。
这种方法巧妙地利用了正弦和余弦函数的特性来编码位置信息,使模型不仅能够理解词语的绝对位置,还能有效地捕捉词语间的相对位置关系,这对于提高诸如机器翻译、文本生成等任务的效果至关重要。
上面是transform论文内容,但实际上gpt2没有按照sin和cos去计算,而是直接通过一个前馈层直接训练得出的,然后和词向量直接相加,最终训练过程也不再还原位置信息,而是以这种隐含的方式将位置信息参与后续训练,提高参数拟合度。
最后把整个embedding过程的工程图贴一下:
在自然语言处理(NLP)中,将文本数据转换为模型可以理解的形式是关键步骤之一。这个过程通常包括分词和映射分词到索引两个主要步骤。下面详细介绍这两个步骤的具体过程:
1. 分词
分词是指将一段连续的文本分割成有意义的单元(如单词、标点符号等)的过程。具体的分词方法会根据使用的语言和具体的应用场景有所不同。
-
基于空格的分词:对于英语等使用空格分隔单词的语言来说,最简单的分词方式就是按照空格来切分句子。然而,这种方法无法处理标点符号和一些特殊情况。
-
基于规则的分词:对于一些有明确语法规则的语言(如中文),可能需要使用基于规则的方法进行分词。例如,在中文中,"我爱北京天安门"这句话就需要被分割成"我"、"爱"、"北京"、"天安门"。
-
使用分词工具:现代NLP任务中,通常会使用专门的分词工具或库来进行更精确的分词。例如,对于英文可以使用NLTK、spaCy等;对于中文,则有jieba、THULAC等工具。这些工具不仅能正确地识别单词边界,还能处理复杂数字、日期、缩写等特殊情况。
2. 映射分词表索引
一旦完成了分词,接下来的步骤是将每个词汇映射到一个唯一的整数标识符,这个过程称为词汇表(Vocabulary)构建与映射。
-
构建词汇表:首先,需要确定你的模型将会遇到的所有词汇。这通常涉及到遍历整个训练集,并记录出现的所有独特词语。然后,给每个独特的词语分配一个唯一的整数ID。注意,为了处理未知词汇(OOV, Out-Of-Vocabulary),通常会在词汇表中预留一个特殊的ID。
-
映射过程:有了词汇表之后,就可以将文本中的每个词替换为其对应的整数ID。这个过程就是将分词结果转化为模型输入的过程。例如,假设词汇表中"我"的ID是1,"爱"的ID是2,"北京"的ID是3,"天安门"的ID是4,那么句子"我爱北京天安门"经过分词和映射后的结果就是一个整数序列[1, 2, 3, 4]。
总结
分词和映射分词表索引是将文本信息转化为机器可处理形式的关键步骤。分词负责将文本切割成适合模型处理的基本单位,而映射过程则是为这些单位赋予数值标识符,以便于后续的计算和模型训练。通过这两步,文本信息就能够以一种结构化的方式输入到深度学习模型中,为各种NLP任务提供支持。
在自然语言处理(NLP)中,构建词汇表(Vocabulary)和进行映射是将文本数据转换为模型可理解的形式的重要步骤。特别是在使用如Transformer这样的深度学习模型时,这一过程尤为关键。以下是构建词汇表及映射的具体步骤:
1. 构建词汇表
数据收集
首先,需要一个大规模的文本数据集,这个数据集应该尽可能覆盖你希望模型能够理解和生成的所有类型的文本。
分词
对收集到的数据进行分词。分词方法依据所使用的语言而定:
- 对于英语等以空格分隔单词的语言,可以简单地通过空格分割。
- 对于中文等没有明显词边界标记的语言,则可能需要用到专门的分词工具,比如jieba、THULAC等。
统计词频
对分词后的结果进行统计,计算每个词出现的频率。这一步骤有助于识别数据集中最常用的词语,并决定哪些词语应包含在最终的词汇表中。
确定词汇表大小
基于你的模型需求和资源限制,选择一个合适的词汇表大小。通常,只保留最常见的n个词作为词汇表的一部分,其余的视为"未知词"(OOV, Out-Of-Vocabulary),并用一个特殊的<unk>
标记来表示它们。
添加特殊符号
除了从文本数据中提取的词外,还需要添加一些特殊符号到词汇表中,例如:
<pad>
:用于填充较短序列,使得所有输入序列具有相同的长度。<sos>
(Start of Sentence)和<eos>
(End of Sentence):分别标记句子的开始和结束。<unk>
:代表词汇表之外的所有词。
2. 映射
一旦词汇表构建完成,接下来就是将文本中的每个词映射到其对应的整数ID。这个过程包括:
- 词到索引:为词汇表中的每一个词分配一个唯一的整数ID。例如,"cat"的ID可能是5,"dog"的ID可能是6。
- 索引到词:同时维护一个反向查找表,以便可以根据ID快速找到对应的词。
实现示例
假设我们有一个简单的词汇表如下:
深色版本
{'<pad>': 0, '<unk>': 1, 'hello': 2, 'world': 3}
对于输入句子:"hello world",经过分词后,将其映射为对应的整数ID序列:
深色版本
[2, 3]
如果遇到不在词汇表中的词,比如"python",则会被映射为<unk>
的ID,即1。
在Transformer模型中的应用
在Transformer架构中,这种词汇表构建和映射机制用于将输入文本转换为嵌入向量。具体来说,输入文本首先通过上述过程转换为整数ID序列,然后这些ID被用来查找相应的词嵌入或位置编码,从而形成模型的实际输入。
这种方法不仅简化了文本信息的处理,还允许模型有效地捕捉语义信息,为进一步的文本分类、翻译、生成等任务奠定了基础。
注意力和多头注意力机制(Attention Mechanism&Multi-Head Attention)
Attention不是Transformer提出的,在2017年以前的时候,各种Attention方式被广泛应用在NLP任务上。
Attention的大概原理 注意力机制 大脑在短时间内处理信息时,主要将图片中最吸引人注意力的部分读出来了
Attention的核心实现就是论文中的公式:
Q为查询意图、K为检索内容、V为被查询全部信息
Q为"好奇看看照片是个啥"、K为"招牌的几个字",V为"整个图片",通过计算Q和Key的Attention Score,也就是最吸引人注意力的招牌,解析出招牌对应的值。
"LLM with banzang"经过embedding后,形成以下的6*768(seq.len, embed.dim)矩阵,分别代表着LL、M、with、ban、z、ang这5个token的768维度的向量:
然后分别乘以3个768*768(embed.dim, embed.dim)的Wq、Wk、Wv矩阵,得到的还是3个6*768的矩阵,分别是Q、K、V
然后将Q和相乘(可以简单理解成 矩阵X乘以矩阵X的倒置),得到一个6*6的矩阵Z(seq.len,seq.len),Z代表着 [LL、M、with、ban、z、ang] 每个token之间的向量距离
把输入和输入的倒置矩阵相乘代表着LL、MM、with、ban、zang的token之间两两所有维度叠加后的"相似度",这个是Attention最核心部分 。
两个矩阵点积表达相似度的数学原理,假设LL、M和with三个向量分别是[1 2] [3 3] [-2 1]映射到象限表后,相似度看夹角度数
数学定义是向量A和B的顶点距离
因为cos结果区间是[-1, 1],所以两个矩阵的相似度也就相当于 两个矩阵的点积通过模长和cos给归一成[-1, 1]的值,等价于LL和M两个矩阵相似度,先算点积再归一,比如简化下上面的Q、K、Z矩阵。
其中缩放目的是:
-
避免数值过大,再最后归一的时候会导致梯度消失(vanishing gradients)回归效果差。
-
归一函数的输入如果太大会导致梯度非常的小,训练会很难。
在深度学习和数学领域中,梯度是一个核心概念,它用于描述一个函数的输出相对于其输入的变化率。更具体地说,在多变量函数的情况下,梯度是一个向量,其中包含了函数关于每个输入变量的偏导数。梯度指向的方向是函数值增长最快的方向,而其相反方向则是函数值下降最快的方向。这使得梯度成为优化算法(如梯度下降)中的关键元素,用于最小化或最大化目标函数。
梯度的基本概念
-
定义:对于一个多元函数 f(x1,x2,...,xn)f(x1,x2,...,xn),其在某点 (x1,x2,...,xn)(x1,x2,...,xn) 的梯度是一个向量,记作 ∇f 或 grad(f),定义为:
-
几何解释:在二维或三维空间中,梯度向量垂直于等值线(二维)或等值面(三维),并指向函数值增加最快的方向。
在深度学习中的应用
在神经网络训练过程中,梯度用于更新模型参数以最小化损失函数。这个过程通常通过以下步骤实现:
- 前向传播:计算输入数据经过神经网络后的预测值。
- 计算损失:基于预测值与真实标签之间的差异来计算损失函数的值。
- 反向传播:使用链式法则计算损失函数相对于每个权重的梯度。
- 参数更新:根据计算出的梯度调整模型参数,通常采用如下公式: wnew=wold−η⋅∇L(w) 其中,w 表示模型参数,η是学习率,∇L(w)是损失函数关于参数 ww 的梯度。
面临的问题及解决方案
- 梯度消失/爆炸:深层网络中,由于连乘效应,可能导致梯度变得非常小(梯度消失)或非常大(梯度爆炸)。解决方法包括使用合适的激活函数(如ReLU)、批归一化、残差连接等。
- 局部极小值和平坦区域:优化过程中可能会陷入局部极小值或长时间停留在平坦区域。高级优化算法(如Adam、RMSprop)可以帮助缓解这些问题。
理解梯度及其在模型训练中的作用对设计高效的学习算法至关重要。通过合理地利用梯度信息,可以显著提高模型训练的效率和效果。
最后得到的矩阵Z(6*768)如果降维到Z'(6,),第一行代表LL在"LLM with banzang"整句中和每个词的关联度,比如下图中ll和m紧密度高于with,第二行是M如此类推,实际上如果把6*1的矩阵在softmax后,取某个概率阈值,可以得到"LLM with banzang"这句中,最重要的两个单词是什么(当然是训练后)
回顾下Attention机制,,整个过程如下:
matmul
是"矩阵乘法"(Matrix Multiplication)的缩写,指的是两个矩阵相乘的过程。
"scale"(缩放)是一个重要的概念,它指的是对数据进行调整以改善模型的性能或训练效率。数据缩放可以影响模型的学习速度、最终的准确性和泛化能力。
数据归一化 (Normalization)
目的 :将数据缩放到一个特定的范围,如[0, 1]或[-1, 1],这在处理具有不同量级的数据时特别有用。
在深度学习领域,尤其是在处理序列数据时,"mask"(掩码)是一个非常重要的概念。掩码通常用于忽略某些不需要考虑的输入部分,例如在自然语言处理(NLP)中处理变长序列时忽略填充部分,或者在注意力机制中屏蔽未来的信息。
自注意力机制中的掩码
在Transformer架构中,为了防止位置i的关注头注意到位置i之后的元素(即避免"看到未来"),在计算注意力分数之前会对未来的元素应用掩码。这在解码器阶段尤为重要,以确保生成过程是从左到右逐步完成的。
Softmax函数是机器学习和深度学习中常用的激活函数之一,特别是在多分类问题中。它能够将一个含任意实数的K维向量转化为另一个K维向量,这个输出向量的每个元素都位于(0, 1)区间内,并且所有元素之和等于1。因此,Softmax函数的输出可以被解释为概率分布,指示输入属于各个类别的概率。
这部分独立的流程的实现被称为Encoder module。
实际上transformer论文中,一次查询可以是并行的,也就是第一维是batch,然后第二维seq.len,第三维是把embed.dim拆成了n份(论文中是12份,任意份都可以,但我怀疑12是一个经验值),然后第四维是n份后的token维度,还是按照上面例子从(6, 768)最终变换成(4, 12, 6, 64),再加上一个linear后,拼接成最终的(4, 12, 6, 768),这里的12就是多头(Multi-Head)概念。
- 在线性代数、数学分析等领域中,"linear"指的是具有加法和乘法性质的关系或函数。例如,线性方程表示变量之间的关系可以用一条直线表示(在二维平面上)。线性函数的形式通常是 f(x)=ax+bf(x)=ax+b,其中 aa 和 bb 是常数。
多头在工程上的意义在于:
-
比起单头,多头可以在不同维度空间聚焦信息处理,也可以降低单头在聚合多维度时的不稳定。
-
拟合度更好,
残差网络(Residual Network,ResNet)& 前馈网络(FeedForward Neural Network, FFNN)
前面输入的X从embedding开始,到多头QKV,再还原Z,经过了多层的网络,每经过一层就会增加训练的性能要求,梯度下降的特别多,会剑走偏锋,第一部里Loss Function中梯度下降中,和LR类似,会跳过最优值,或者在最优值附近震荡,反复消耗资源
2015年微软亚洲研究院提出了基于CNN架构的ResNet,在transformer中可以借鉴来解决这个"退化"问题,核心是引入了"跳跃连接"或"捷径连接"(训练场景,梯度直接反向传播最原始层),将输入除了做为X给每层外,还跳过这层网络直接和这层输出Y叠加,让后面的层可以学习到这层处理和原始输入的差异,而不是直接上层处理结果Y,这种设计允许网络学习到恒等映射(identity mapping),即输出与输入相同,从而使得网络可以通过更简单的路径来学习到正确的映射关系。
小结一下第一阶段的所有流程,见下图,这个流程在tranformer里被独立出一个模块,叫encoder,至此tranformer具备识别一个句子中每个词和整句的关联性,也就是每次token都包含了全部token信息以及关联度 。