《从函数到大模型速通》

一、从函数到神经网络

所有一切的前提是,你要相信这个世界上的所有逻辑和知识,都可以用一个函数来表示。Functions describe the world !

比如输入物体的质量和加速度,根据牛顿第二定律,就可以得到物体施加的力,这就是人工智能早期的思路:符号主义。

但这条路走到头了,很多问题人类实在是想不出怎么写成一个明确的函数。比如说一个简简单单的识别,一张图片是否是猫对人类来说可能简单到爆炸,但是要让计算机运行一段程序来识别,一下子就变成了一个史诗级难题,就连有着明确语法规则和词典的翻译函数尚且没有办法做到足够丝滑,更别说复杂多变的人类智能了。

既然不知道这个函数长什么样,怎么办呢?换个思路:

假如我们一开始没有找到这个规律,我们先把这个x、y放到坐标轴上,先随便猜一下。比如说函数关系就是y等于x,也就是这里的w和b分别是1和0,然后我们一点点调整这个w和b,使得这条直线越来越贴近真实数据。

刚刚我们举的例子比较简单,只用直线方程就可以表示了。但假如数据稍稍变化一下,就会发现,不论怎么调整都无法接近真实的数据,这个时候就需要从原来的线性函数进化到非线性函数了,我们就来研究一下,怎么把原来这个原本线性的函数变成非线性的呢?

很简单,在这个函数最外层再套一个非线性的运算就可以了。比如平方、比如sin(wx+b)、比如e^wx+b,这就是激活函数。 它的目的就是把原本死气沉沉的线性关系给盘活了,变成了变化能力更强的非线性关系。

回到这个新的函数形式,我们之前仅仅有一个输入的变量就是x,但实际上可能有很多输入。所以这里的每一个x都要对应一个w,像这样:

再者,有的时候只套一层激活函数,还是没有办法达到很好的效果。也就是说这个曲线弯的还不够灵活,这要怎么办?

我们在此基础之上再进行一次线性变换,然后再套上一个激活函数,这样就可以无限的套娃下去了。通过这样的方式,我们就可以构造出非常非常复杂的线性关系,而且理论上可以逼近任意的连续函数。当然了,这样写下去实在是太让人头大了,普通人看个两层,估计脑子就炸了,所以我们得换一种更傻瓜的、更直观的形式,我们把这样一个线性变换套一个激活函数 画成下面这样:

左边是输入层,只有输入x,右边是输出层,只有一个输出y。我们把这里的每一个小圈圈叫做一个神经元。

每套一层就相当于神经元水平方向又扩展了一个。当然扩展之后,中间这一层就不再是最终的输出了,而是包裹在了一个很复杂的函数变换之中看不到,我们管它叫做隐藏层 ,而整个神经元互相连接形成的网络结构,就叫做神经网络

好,接下来我们看一下函数和神经网络的对应关系。首先有两个输入变量,一个是x1,另一个是x2,它们构成了输入层,然后x1、x2进行一次线性变换,再进行一次激活函数就得到了隐藏层a,这个a对应的就是上面这一大坨表达式(灰色部分),我们把它当做一个整体,继续进行一次线性变换和一次激活函数,这就计算出了最终的输出层y。

从神经网络的这个图来看的话,似乎就像是一个信号,从左到右传播了过去,这个过程就叫做神经网络的前向传播。实际上就是一点点分步骤,把一个函数的值计算出来了而已。

神经网络的每一层神经元都可以无限增加。同时,隐藏层的层数也可以无限增加,进而就可以构成一个非常非常复杂的非线性函数了。

虽然这个函数可能非常复杂,但是我们的目标却非常简单和明确,就是根据已知的一组x和y的值,猜出所有w和b各是多少。

二、如何计算神经网络参数

上面解释了神经网络的本质,其实就是线性变换,套上一个非线性激活函数,不断组合,对应就是一个非常复杂的非线性函数,计算出这里的w和b。

那么到底如何求得最佳的w和b呢?答:预测数据与真实数据拟合的好的函数就是好函数,也就对应最佳的w和b!

那么在数学上如何去表示函数是否你和的好呢?答:求损失函数

先从最简单的线性函数入手, 每个点上的数据是真实数据,落在直线上的点表示预测数据,那么这条线段的长度就是真实值与预测值的误差,即|y - y^|

为了评估整体的拟合效果,我们可以将所有这些线段的长度相加,得到真实数据与预测数据的总误差,这个函数就叫损失函数

然而,这个绝对值在数学优化时不太友好,那么改造下用平方来代替,既解决了绝对值不平滑的问题,也放大了误差较大的值的影响。然后我们再根据样本的数量平均一下,消除样本数量大小的影响,最终得到的公式即均方误差

前面我们为了找到一组w和b来拟合真实数据,定义了损失函数。下面要做的就是制定让损失函数最小这个目标来计算w和b的值。

求解的方法,要用到的就是初中学过的知识,让其导数等于0,求极值点的过程。

举个简单的例子,线性模型只保留一个w:

代入损失函数:

化简后就是一个简单的关于w的二次函数,接下来对w求导,让其导数等于0,就可以求出w=1。

刚刚的步骤其实就在寻找这条抛物线的最低点。

如果再加上b,损失函数图像就是1个三维图像。而多元函数求最小值的问题就不再是导数了,而是要让每个参数的偏导数等于0来求解。

在三维图像中,就是对应w和b两个切面上的二维函数来求导。这里不再展开。 通过寻找一个线性函数来拟合x和y的关系,就是机器学习中的最基本分析方法--线性回归

具体的,每次调整一点w或b数值,使得损失函数会变化多少,这其实就是损失函数L(w,b)对w或b的偏导数。

我们要做的就是不断往偏导数的反方向去变化,具体变化的快慢,用一个系数来控制,叫做学习率 ,这些偏导数构成的向量叫做梯度 。调整w或b数值,让损失函数逐渐减小,最终得到w和b值的过程,就叫做梯度下降 。通过减小预测值与实际值之间的误差,进行反向传播来不断调整模型参数与权重。

梯度下降法有两个缺点:

1.对学习率太敏感。学习率太大会反复横跳,找不到最低点;学习率太小,会浪费很多计算量。

2.除了效率极低的BGD外,你无法保证找到全局最低点,可能会陷入局部最低点。

为了解决以上问题,人们提出了一种叫AdaGrad动态学习率 的方法,经常更新的参数学习率就小一些,不经常更新的参数学习率就大一些。当然这种方法的一个缺点就是,频繁更新参数的学习率可能会过小,以致逐渐消失。因此就出现了解决这一问题的RMSProp算法(优化动态学习率) ,以及更高级的不需要设置学习率的AdaDelta算法

那么现在关键就在于这个偏导数怎么求。之前的线性回归问题中,偏导数就是一个一元二次函数求导,非常简单。但是在神经网络中,层数较多,函数本身就是一个及其复杂的非线性函数,更别说损失函数了,直接求偏导数非常困难。

虽然神经网络整体代表的函数很复杂,但是层与层之间的关系还是很简单的,现在关键问题就是求出L对它们的偏导数。

我们可以逐层求导,比如w1变化一个单位,看a变化多少,再看a变化一个单位,y^变化多少,再看y^变化一个单位,L变化多少,每一个都是一个简单的偏导数,那把三者乘起来,就可以得到w变化一个单位,会使L变化多少了。

这种偏导数的计算方式,就是链式法则 。其实就是微积分中的复合函数求导

由于我们可以通过链式法则从右往左依次求导,逐步更新每一层的参数,直到把所有神经网络的参数都更新一遍,在计算前一层时,用到的一些偏导数的值,后面也会用到,并不用全部计算,而是让这些值从右往左一点点传播过来就好了,这个过程就叫做反向传播

总结前面的知识,我们通过前向传播,根据输入x计算输出y,然后再通过反向传播,计算出损失函数关于每个参数的梯度,每个参数都向着梯度的反方向变化一点点。不断地前向传播、反向传播,这就构成了神经网络的训练过程。

三、如何调优神经网络参数

现在我们知道,神经网络的本质就是线性变换套上一个激活函数不断组合而成的一个非常复杂的非线性函数,并且巧妙的通过梯度下降,一点点计算出神经网络中的一组合适的参数。这样看起来只要神经网络足够大,是不是什么问题都能解决?

看下面一组图,你认为是左边好还是右边好?纯从预测值与真实值误差来看,也就是损失值最小化这个目标来看的话,显然右边这个更好,但直觉似乎告诉我们,右边这个好像有点好的太过了。结果可能是只适合训练数据,对新数据的预测,反而不如左边的准。

这种在训练数据上表现的很完美,但是在没见过的数据上表现的很糟糕的现象,就叫做过拟合(Over Fitting) 。而在没见过的数据上的表现能力,我们叫它泛化能力。为什么会过拟合呢?看看刚刚这个图其实就是训练数据本身是个很简单的规律,但模型太复杂了,把那些噪声和随机波动也给学会了。

因此这个案例中,用一个非常复杂的神经网络模型来训练效果,甚至不如一个线性模型,这就告诉我们神经网络不是越大越好。

简化模型复杂度 有效果,与之相对的就是增加训练数据的量,数据量足够充足,原本复杂的模型也就相对变得简单了。

但有的时候我们确实无法收集或者懒得收集更多的数据怎么办呢?那就在原有的数据中创造更多的数据,比如说在图像处理中,我们可以对图像进行旋转、翻转、裁剪夹、噪声等操作,创造出更多新的训练样本,这就叫做数据增强

这样不仅仅能够产生更多的数据,还刚好训练了一个让模型不因输入的一点点小的变化,而对结果产生很大的波动,这就是增强了模型的鲁棒性

刚刚是从数据和模型本身入手来防止过拟合,有没有可能从训练过程入手阻止过拟合的发生?

其实训练过程就是不断调整各种参数的过程,只要不让参数继续过分的向着过拟合的方向发展就可以了。有一个简单的方法就是:提前终止模型训练过程(早停策略),但这种方法还是太粗糙,有没有什么方法也已直接抑制参数的野蛮增长呢?

回想一下参数的训练过程:通过让参数往让损失函数变小的方向不断调整,也就是梯度下降。我们可以在损失函数中把参数本身的值加上去,这样在参数往大的调整时,如果让损失函数减小的没有那么多,导致新的损失函数反而是变大的。那么此时调整就是不合适的,因此一定程度上就抑制了参数的野蛮增长。

除了可以用参数的绝对值之和之外,我们还可以用参数的平方和。这样参数大的时候,抑制的效果就更强了。我们把这一项叫做惩罚项 ,把通过这种损失函数中添加权重惩罚项,抑制其野蛮增长的方法叫做正则化

上面这个参数绝对值相加的叫L1正则化 ,这个平方项相加的叫L2正则化 (因为绝对值之和叫做L1范数 ,而平方和的平方根叫做L2范数 ,这是向量空间中范数的概念),然后和之前梯度下降时增加学习率控制下降粒度一样,我们也增加一个参数来控制惩罚项的力度,我们叫它正则化系数 。而这些控制参数的参数,我们以后统称为超参数。总之这个公式就只是为了抑制参数的野蛮增长。

除了这种方式外,还有一种令人简单到发指,但是就是效果显著的办法。那就是可以在训练过程中每次都随机丢弃一部分参数,这样模型就避免了在某些关键参数上过渡依赖的风险。虽然听起来有点玄学,但确实十分有效,这种方法叫dropout,其翻译过来就是丢弃,而且这个方法是大名鼎鼎的深度学习之父辛顿提出来的。

好了,上面我们了解了在对抗过拟合 这条路上,我们搅尽脑汁想了各种办法,包括增加数据量减少模型复杂度提前终止训练L1正则化L2正则化dropout等等。除此之外,模型还会遇到其他问题,比如:

  • 梯度消失:也就是网络越深,梯度反向传播时会越来越小,导致参数更新困难。

  • 梯度爆炸:梯度数值越来越大,参数的调整幅度失去了控制。

  • 收敛速度过慢,比如可能陷入局部最优,或者来回震荡。

  • 计算开销过大,每次完整的前向传播和反向传播都非常耗时。

每个问题人们都想了各种办法来解决,比如:

  • 用梯度裁剪来防止梯度的更新过大。

  • 用合理的网络结构,比如残差网络来防止深层网络的梯度衰减。

  • 用合理的权重初始化,和将输入数据归一化,让梯度分布更平滑。

  • 用动量法、RMSProp、 Adam等自适应优化器来加速收敛,减少震荡。

  • 用mini batch,把巨量的训练数据分割成几个小批次来降低单次的计算开销。

这里的每个概念展开都是一个全新的世界,鉴于我们这个系列是抓大放小解决主要思想的特点,这里就不一一展开了,但它们和我们今天着重讲的内容一样,都是为了让训练过程更好罢了。

所以并不是神经网络越大越复杂就越好,随着神经网络越复杂出现的问题就会越多,针对千奇百怪的问题人们才会想出五花八门的应对策略,深度学习的确相似一门玄学,无穷无尽彷佛研究不到头,强大魔力令人着迷!

随着研究的不断深入,更多令人惊艳的技巧层出不穷,比如:

卷积网络CNN:如何利用卷积层、池化层处理图片数据。

循环网络RNN:如何利用上下文处理序列数据。

以及后来的注意力机制的引入催生了Transformer,并衍生出了现在众多的大语言模型,让人工智能不仅仅可以识别和判断,还可以创造和决策。

四、全连接层

回顾前面学过的知识: 一个最简单的神经网络,就是y=wx+b (线性函数)套上一个激活函数(非线性函数),即f(x) = g(wx+b) 如果有多个输入,那就是多个w和x 如果有多个输出,那就再来一行公式,多一组w和b

要是神经元多了的话,公式密密麻麻的,没有数学的简洁之美,这怎么办呢?其实就是把加减乘除替换成了矩阵运算的写法(这里先忽略一下激活函数)。

然后我们现在把这些矩阵都替换成新的字母,那么整个公式就化简成了这个样子:

不过现在还有个问题,就是神经元的层并没有体现在公式中。假如神经元再多几层怎么办?我们此时抽象一下也别分什么x、y和隐藏层了,就通通用字母a来表示。输入层就当做第0层,用a中括号零来表示,以此类推。 例如第1层的公式如下:

第2层的公式如下:

每一层的神经元的值都是上一层的函数。我们用L表示在第几层,那么最终的通用公式就是:

到这里,公式变得更简单了,但是也更抽象了;麻烦的加减乘除就替换成了矩阵运算,可以充分利用GPU的并行计算的特性,加速神经网络的训练和推理过程。这就不仅仅是秀写法上的一个操作了。

回到这个公式和神经网络结构,可以看到这里的每个神经元都与前一层的所有神经元相连。但它其实只是神经网络结构中的一种,叫做全连接层

五、卷积神经网络CNN

卷积神经网络 CNN(Convolutional Neural Network)

下面先看一下全连接层的问题:

假如我们现在要做个图像识别的模型,假如输入是个30×30的灰度图像。那么平铺展开后喂给输入层的就是900个神经元。假如下一层的神经元的数量是1000个,那么这个全连接层的总参数量就达到了900000,这太大了。

另外,这里仅仅是把输入的图片平铺展开,无法保留像素之间的空间关系。图片稍稍动一下,可能所有神经元都和原来完全不同。但从图片整体上看,可能仅仅是平移或者变暗,这就是不能很好的理解图像的局部模式

为了更好的理解图像的局部模式,我们随便在这个图像中取一个3×3的矩阵,这里面的数值就是颜色的灰度值。然后我们再来一个固定的矩阵,把每个对应位置数的值相乘并求和,最终得到一个值是250。

然后我们再选取一个地方,再次进行这样的运算。最终我们把这种运算方式遍历划过原图像的每个地方,得出的数值形成一个新的图像。这种方式叫做卷积运算 。而刚刚我们这个固定的矩阵叫做卷积核。 卷积核不是一个新的概念,在传统的图像处理领域,卷积核是已知的,可以达到一定的图像处理效果,比如模糊效果、浮雕效果、轮廓效果以及锐化效果等等,就是PS的常规操作。

在深度学习领域,卷积核的值就是未知的,和神经网络中的其他参数一样,是被训练出来的一组值。

回到刚刚的经典神经网络结构,其实就是把其中一个全连接层替换成了卷积层,这就大大的减少了权重参数的数量,同时还能更有效的捕捉到图片中的一些局部特征,可谓是一举两得。而从公式上看,其实就是把原来的矩阵的标准乘法即叉乘替换成了卷积运算。

那么接下来,我们的神经网络就可以用更抽象、更简洁的图来表示。在图像识别的神经网络结构中,除了卷积层外,通常还有池化层,作用是对卷积层后的特征图像进行降维,减少计算量,同时保留主要特征。

这里的卷积层、池化层、全连接层都可以有多个。而这种适用于图像识别领域的神经网络结构,就叫做卷积神经网络 CNN(Convolutional Neural Network)。

使用卷积神经网络非常方便可视化,我们可以看到训练过程中所训练出的卷积核,从原始图像中提取了什么样的特征,虽然这些都是中间隐藏层的事情,但是却能神奇的观察出一些实际意义,这也是卷积神经网络让人着迷的地方。

总结: 我们把之前一个个加减乘除很麻烦的写法,写成了矩阵的形式。一是为了方便讨论,比如刚刚介绍CNN的时候,就从公式直接看出,就是差乘变成了卷积运算而已。二是可以更好的利用GPU的并行计算,提高效率。

接下来我们把之前默认的那种所有神经元都连起来的形式叫做全连接,进而通过图像识别这个任务意识到了全连接的局限性。接下来我们通过卷积运算代替了全连接层的标准矩阵乘法,一方面使得训练参数大大的减少,另外一方面也更有利于提取图像的局部特征,这就解决了我们一开始说的问题。

最后我们把神经网络结构再次抽象一个层次,原来我们画的各种小圈圈在更高的视角下,其实就是个全连接层而已。那么这些全连接层、卷积层、池化层的组合就构成了卷积神经网络 CNN。

当然卷积神经网络CNN也只是神经网络结构中的一种,而且它有一个致命的局限性,就是它主要用于静态数据,比如说图片。那么如果我们要处理的是时间序列、文本、语音、视频等动态数据,就需要引入另外一种神经网络结构了------RNN

复制代码
附视频中用到的一些工具类网站:
卷积操作图示:https://setosa.io/ev/image-kernels/ 
GPU 对比页面用 AI 工具生成的代码:https://www.blackbox.ai/ 
手写数字识别过程演示:https://felixzhang00.github.io/DL/mnist/ 
3D CNN 网络可视化:https://adamharley.com/nn_vis/cnn/3d.html

六、循环神经网络RNN

我们来看这么一个需求,输入一句话,输出每个单词的褒贬性。

要想把这些文字作为输入参数,首先得把这些文字变成计算机能够识别的数字,这个过程就叫做编码。具体怎么编码呢?有两种极端的方式。一种是只用一个数字标识来代表每个词。这样的缺点非常明显,就是维度太低了,相当于一个一维的向量,而且数字标识本身对语言理解没有任何意义,无法灵活地衡量词和词之间的相关性。

另一种极端的方式是准备一个超级超级大的向量,每个词只有向量中一个位置是1,剩下的都是0。这种方式叫做One hot ,即独热编码。这种编码方式维度太高了,而且每个向量之间都是正交的,所以词和词之间仍然无法找到相关性。

所以另一种更有效的方式叫做词嵌入(Word Embedding),通过词嵌入的方式所得到的词向量维度不高也不低,每个位置数依然可以理解为某一个特征。只不过这是训练出来的,不是我们人定的。不过特征是什么可能我们人类完全无法理解。

为什么这种方式可以表示词和词之间语义上的相关性?我们可以用两个向量的点积或余弦相似度来表示向量之间的相关性,进而表示两个词语之间的相关性,这就将自然语言之间的联系转化为了可以用数学公式计算出来的方式。

同时,一些数学上的计算结果,也能反映出一些现实中很神奇的解释。比如:一个训练好的词嵌入矩阵,可能会使得桌子-椅子 = 鼠标 - 键盘,这种有趣的深意。

把所有词向量组成的一个大矩阵,这个大的矩阵就叫做嵌入矩阵 。这里的每一列就表示一个词向量

像刚刚说的这个矩阵,不是我们人类手动给每个词赋值而形成的,是通过深度学习的方法训练出来的。比如比较经典的方式,就是Word2Vec ,这里就不展开讲解了,你就当做已经有了一个这样的嵌入矩阵,每一个可能的词语都可以从这里找到对应的词向量,这些词向量的维度非常高。所以它所在的空间的维度也非常高,这个空间就叫做潜空间

那么这些词在高维潜空间中的相对位置关系,虽然可以通过点积或余弦相速度算出来,但最好有一种直观的方式能让我们亲眼可视化的看到,哪怕不那么准确也行。于是便有了一些方法,将这个潜空间降维投影到二维或三维的坐标系中,来直观的可视化不同词语之间的距离,还是非常有趣的。

好了,有关词嵌入和嵌入矩阵,我们就先聊到这里。这时每个词都可以编码成向量,然后送到神经网络输入端的神经元中了。

我们再来看看最初的需求:输入一句话,输出每个单词的褒贬性。

这里有5个词,通过词嵌入,把每个词变成一个300维的词向量,那么输入端就要一共有1500个神经元。但是有两个问题,一个是输入层太大了,而且会随着一句话中词语数量多少而变化,是变长的不确定的。另一个是无法体现词语的先后顺序,仅仅是把它们非常生硬的平铺展开成了一个非常大的向量,一股脑的送入了输入层。

在CNN中,我们是通过卷积操作提取了图像的特征。那么在自然语言处理领域,我们可以通过什么办法,既能解决词语之间的先后顺序问题,又能降低输入层的参数量呢?

首先我们还是用经典的神经网络,但不要输入一句话,而是输入一个词,输出就是这个词是褒义还是贬义,当然这里的字母都表示矩阵。这时假设第二个词来了,也是经过一样的神经网络。我们用尖括号<>来表示第几个词,这样就有了顺序关系。现在的问题是,第二个词的计算过程,完全没有让第一个词的任何信息参与进来,这该如何解决?

可以这样,我们让第一个词经过非线性变换后,先输出到一个隐藏状态H1,然后再经过一次非线性变换得到输出Y1,接下来这个隐藏状态H1的值和第二个词X2一起参与运算。同理,对第二个词的流程也是一样继续往下传递。这样的话,前面词的信息就这样不断的往下传递,直到传到最后一句话的最后一个词那里,这样就把一句话中所有的词的信息都囊括进来了。

当然,这里的W要有所区分,有专门针对词向量的Wxh矩阵 ,有专门针对隐藏状态的Whh矩阵 ,以及最终计算输出结果的Why矩阵 。同样对于偏置项b也是如此,把这个图简化一下,这就是循环神经网络RNN

还会有图这样画:

这个抽象的RNN模型,就具备了理解词和词之间先后顺序的能力,这就解决了:判断一句话中各个单词的褒贬词性、给出一句话不断生成下一个字、以及翻译等多种自然语言处理的工作了。

进一步我们把矩阵展开来看就是这样:

首先第一个词,X1和权重矩阵Wxh相乘得到第一个词的隐藏状态h1,h1和权重矩阵Why相乘得到第一个词的输出结果y1。这时候同样向后传递计算第2个词,同样要和权重矩阵Wxh相乘,但是注意:此时会把第一个词的隐藏状态h1拼接到输入向量X2中;同时权重矩阵也增加了一个Whh,最终计算出第二个词的隐藏状态h2。h2会继续往后传,后面的流程就是重复的了。

最后看一下公式,其实非常简单,和经典的神经网络相比,就是多了一个前一时刻的隐藏状态而已:

当然RNN还有两个非常严重的问题:

  • 信息会随着时间步的增多而逐渐丢失,无法捕捉长期依赖。而有的语句恰恰是距离很远的地方起到了关键性的作用。

  • RNN必须按顺序处理,每个时间步依赖上一个时间步的隐藏状态的计算结果。

为了解决这些问题,人们使用GRU和LSTM改进了传统的RNN,但是这些仍然是建立在让信息一点点按照时间不传递的思路来,只能缓解而无法根治。

我们是否有一种可以彻底抛弃这种顺序计算,直接一眼把全部信息尽收眼里的新方案呢?那就是transformer!

七、Transformer简单而强大

用神经网络进行翻译任务,例如"i love you baby"译为"我爱你宝贝"。

首先,通过词嵌入将每个词转换为一个词向量,假设维度为六。若直接将每个词输入全连接神经网络,会缺乏上下文信息,且句子长度受限,效果不佳。

若使用循环神经网络RNN,则面临串行计算问题,句子过长时会导致长期依赖困难。因此,需要一种全新的方案------Transformar。

首先,为每个词赋予一个位置编码,表示其在句子中的位置。将位置编码加到原来的词向量中,使每个词获得位置信息,但此时仍未包含其他词的上下文信息,也就是注意不到其他词的存在。

接着,使用一个Wq矩阵与第一个词向量相乘,得到维度不变的q1向量。这里的Wq矩阵是可以通过训练过程学习的一组权重值。同理,使用Wk矩阵与第一个词向量相乘,得到k1向量;再使用Wv矩阵与第一个词向量相乘,得到V1向量。

对其他词向量也进行相同操作,分别得到对应的q、k、v向量。在实际GPU运算中,通过拼接形成大矩阵进行乘法运算,而非如上述逐步计算。得到的是直接包含所有词向量的q、k、v矩阵。不过为便于理解,解释时仍拆分为单个词向量。

现在,原来的词向量已通过线性变换映射成q、k、v向量,维度与原来相同。接下来,让q1与k2做点积,这表示:在第一个词的视角里,第一个词与第二个词的相似度是多少。同理,q1分别与k3、k4点积,分别表示与第三个词、第四个词的相似度。最后,q1与自己点积,表示与自己的相似度。

得到这些相似度系数后,将它们分别与V向量相乘再相加,得到a1。此时,a1就表示在第一个词的视角下,按相似度大小加权组合所有词的词向量,从而包含全部上下文信息,而且是从第一个词的视角来看的。

同理,其他词也按此方式处理。最终,每个词都包含其他词的词向量,按与自己的相似度加权。这里的q、k、v是中间计算过程。从全局视角看,最初的输入的词向量经过一些计算处理变成一组新的词向量,不同的是:每个新的词向量都包含位置信息其他词的上下文信息 的一组新词向量,这就是注意力机制attention做的事情。

为进一步优化,有时一个词与另一个词的关系可能因视角不同而异。对于注意力机制而言,若只通过一种方式计算一次相关性,灵活性会大大降低。

在做出改进之前,我们为每个词计算一组Q、K、V。现在,我们在Q、K、V基础上,再经过两个权重矩阵,得到两组Q、K、V,为每个词提供两个学习机会,以学习不同的用于计算相似度的Q、K、V,以增加语言的灵活性。

这里的每组KQV构成一个头,接下来,每个头内的KQV仍经过注意力层的运算,得到a向量,然后将两个a向量拼接起来,得到与之前相同的结构。这种注意力机制被称为多头注意力,我们刚才举的例子就是两个头的情况。

现在,恭喜你已掌握Transformer架构的核心逻辑。我们对照Transformer的经典论文架构图来看。

首先,第一步是将输入内容通过词嵌入转换为词向量矩阵,这对应的是这里。

第二步,加入位置信息,并添加一个形状相同的矩阵,这对应的是这里。

第三步,经过多头注意力处理,输出矩阵的维度与输入相同,为每个词向量增加了上下文信息,这对应的是这里。

此外,还有一步添加了残差网络归一化处理,这是为了缓解梯度消失并使分布更加稳定而做的优化,我们刚才未详细展开,这对应的是这里。

同时,我们也可以看到,在整个Transformer的标准架构中,最主要的是多头注意力处理,相当于我们已搞明白这些部分的逻辑。

下面,我们深入到多头注意力机制的细节部分:

如果是单头注意力,先让Q和K相乘得到一个相似度系数矩阵,然后再和V相乘,最终得到包含上下文信息的词向量矩阵。当然,我们刚才的讲解过程中省略了中间的缩放、掩码和一层Softmax处理。

再看右边的多头注意力情况,首先QKV分别经过线性变换拆分成多组,相当于给了多次机会学习到不同的相似度关系。依次经过注意力机制运算后,将运算结果拼接起来。不过,我们讲解的时候还省略了一次线性变换。即多头结果并不是简单地拼接起来,还需要再次经过一层权重矩阵的乘法。

这时,再看两个核心公式就很好理解了,如下:

所谓注意力运算,就是QK矩阵相乘,经过缩放,再经过Softmax层处理,最后和V相乘。

对于多头情况,就是先将QKV矩阵经过多个权重矩阵拆分到多个头中,分别经过注意力机制的运算;最后合并起来,再经过一次矩阵运算得到输出。

再回过头来看这个全局图,左边的部分叫做编码器、右边的部分叫做解码器。你实在不愿意叫也没关系。

假设这是用于翻译的任务,我们训练这个神经网络的过程如下所示。

先看左边编码器部分:

1.首先输入要翻译的文本"I love you baby",

2.然后经过词嵌入,引入位置编码。

3.通过多头注意力、残差和归一化处理。

4.再送入一个全连接神经网络,将结果经过残差和归一化处理后,送入解码器的多头注意力机制的两个输入中,作为k、v矩阵。

再看右边解码器部分,解码器的部分输出是翻译后的文本"我爱你宝贝",同样经过词嵌入、引入位置编码;经过多头注意力;然后加入残差和归一化处理;然后送入多头注意力的一个输入中,作为q矩阵,与刚刚从编码器中送入的k、v矩阵一起,再经过多头注意力、残差+归一化、全连接神经网络、残差+归一化,最后经过一层线性变换的神经网络投射到词表向量中,再用softmax层转化为概率,代表预测的下一个词在词表中的概率分布,取概率最高的词作为下一个词。

注意这里不同的是:解码器下面的多头注意力部分有个掩码Masked,其作用是真正推理翻译时,是一个词一个词翻译的。比如此时翻译到"我",下一个词应该是"爱",所以输出"我"的时候,是看不到后面的词的,这就需要掩码来遮挡后面的词,以便训练时模拟真实推理场景。比如输入"i love you baby",输出只有一个词"我",经过神经网络后,最后输出词表的概率分布,我们想要的结果就是"爱"字的概率值最大。

如果训练时有偏差,就计算损失函数,在反向传播中调整transformer结构中的各种权重矩阵,直到学习好为止。

总的来说,transformer确实是个特别简单的架构,尤其是有了基础的神经网络知识之后,如果看了这个系列之前的视频,那就只有多头注意力这一层是陌生的。但它其实拆解之后也是各种矩阵相乘相加的操作,其余的词嵌入、位置编码、残差归一化、经典神经网络、softmax层等都是我们之前视频中已经了解过的概念。把这些老东西拼凑起来,就诞生了我们现在大模型技术的鼻祖------transformer。

gpt的底层transform的一半,即只有解码器的部分,也不翻译,只管看前面的词猜下一个词。别看它来回猜词,猜着猜着就变成了聊天、写代码、解数学题的全能选手了。

Transformer的架构来源于经典的论文"attention is all you need"。本期视频内容理解之后再去看这篇论文,就会发现非常容易理解,因为它本身就是一个很简单的架构。也正因为简单粗暴,但效果却出奇的好,所以才会广为流传,并成为现在大模型的基础。

八、速通大模型100词

万物皆函数Function ,早期人们用符号主义Symbolism 思想找到精确函数Function,试图解释一切原理,但遇到瓶颈。后来人们转用联结主义Connection思想,先构建非常复杂函数,根据计算出的预测值与真实值的误差,不断调整里面的未知参数。

这个函数叫做模型Model ,模型里的参数叫做权重Weight

如果模型中的参数量特别大,就叫做大模型large Model ,用于自然语言处理的大模型就叫做大语言模型Large Language Model

调整参数的过程,即模型的训练Training ,事先训练好一个基础模型的方式叫做预训练Pretraining

基于预训练的模型继续训练,让模型学会具体任务的方式,叫做微调Fine-tuning

参数调整好后,根据函数的输入计算输出结果,这个过程叫做推理Inference

这些概念在大模型时代到来之后,逐渐火热起来。当模型参数量足够大时,对话能力有了质的提升,产生了一定程度的推理能力,这种量变引起质变,而突然出现的之前没有的能力,叫做涌现Emergence

大语言模型爆火的产品是2023年的ChatGPT,它是一款用于聊天的产品。

而它背后使用的大语言模型是GPT(Generativate Pre-trained Trasformer),这是个系列。

开发这个模型的公司是OpenAI 。由于这家公司推出的产品一直保持不开放源代码,即闭源,所以也正式更名为CloseAI(开个玩笑)。

一个模型需要训练需要代码,有了代码就可以训练出一组权重,有了权重就可以进行推理,也可以对外提供服务。不开放源代码,也不开放权重,只对外提供服务的模型叫做闭源模型Closed-source Model,如ChatGPT、Claud、Gemini等

开放模型权重Open-weight Model可以直接下载到自己电脑上部署的模型叫做开源模型,但实际上大部分现在说的开源模型只是开放了权重而没有开放训练代码和训练数据,所以准确说叫开放权重模型。比如最近爆火的DeepSeek以及划时代的LLaMA等

不但开放了模型结构和权重,还开放了训练代码的模型,可以叫完全开源模型Fully Open-source Model

当然了,有了模型权重就可以下载到本地进行部署,并且很少有人需要重新训练它,它不依赖于他人的服务,而是把模型下载到本地进行使用的过程,叫做私有化部署Private deployment

私有化部署依赖很多复杂的环境配置,需要装很多依赖的软件和工具包,而且需要性能较为强劲的GPU支持。对于仅仅想尝鲜的个人,专门为此去买一台电脑不太合适,因此就有了云桌面Cloud Desktop 的概念。比如青椒云就是一款高性能的云桌面,你只需要一台能上网的电脑就可以用几秒钟的时间花几毛钱体验众多需要极高电脑配置的大模型应用。下载一个应用程序,根据配置购买一款云电脑,可以看到这里有很多别人打包好的环境和软件,免去了自己配置的麻烦。这个打包好的东西叫做镜像,青椒云内置多种AIGC镜像,即开即用,省去了很多模型部署的时间。接下来选择一个合适的计费方式,如果只想偶尔体验一下就选择按量计费,开机后按分钟计算,不开机不要钱。如果自己的电脑大部分时间都在关机,这种方式和真正拥有一台电脑的区别就不大了。除了能体验私有化大模型外,青椒云用来办公或打游戏也非常方便,支持Windows、Mac、安卓、iOS四大系统,同一个账号的数据是打通的,可以在家、在公司、在上班的路上操作同一台云主机。感兴趣的朋友快下载一个试试吧。

回到ChatGPT大语言模型的本质,就是个大函数,根据前面的一句话持续不断地计算下一个词是什么。这种基于输入内容自动生成新内容的人工智能系统,叫做生成式AI(Generativate AI)

当然除了文本,也包含图像、声音、视频等等,这里的每一个分割成最小粒度的词叫做token ,对话时所有给到大模型的信息叫做上下文Context,不同的模型有不同的上下文长度限制,越大就越能记住前面的信息。

上下文从另一个角度理解,也可以叫提示词Prompt。可以知道模型的回答流程和风格,但其实就是个上下文而已。

早期出现很多提示词工程师Prompt Engineer和提示词教程,本质就是教你怎么跟大模型说话而已。现在AI的对话越来越贴近人的方式了,所以你和人沟通起来有啥毛病?那么跟AI沟通也有啥毛病?你真正缺的是怎么表达清楚自己的意思,而不是prompt技巧。

刚刚说了大模型就是个大函数,函数是死的,所以根据前面的词输出的下一个词是固定的,但是我们可以一定程度的调整模型输出的随机性Randomness ,让下一个词的生成并不总是取前面概率最高的那个词,控制输出的随机性的参数,叫做温度Temperature 。控制范围从概率最高的k个词中选择,叫做top-k

随机性太高,模型容易胡说八道,太低又会过于保守,也可能说错。这种在语言上说得通,但是在事实上狗屁不通,甚至虚假信息的现象,叫做大模型的幻觉问题Hallucination

为了解决幻觉问题,大模型或者一些套壳产品提供了联网能力Browsing

其实呢,在大模型回答问题前,先去互联网上查找一些相关信息,然后把这些信息和你的问题拼接在一起,共同先发给大模型进行回答,相当于带着答案回答问题了。之前很多自媒体的震惊体、炸裂体、天塌体的文章说,大模型拥有联网能力,是有了重大突破,人类就要完蛋了。那实际上呢,就是这么个玩意。

有些数据网络上可能查不到,或者企业的数据不方便公开地放在互联网上,希望大模型去这些私有的数据库中查找答案。这种方式叫做检索增强生成RAG(Retrieval-Augmentted Generation)

与联网思路相同,先查资料再回答问题,但查询内容不在互联网,而在私有数据库,即知识库KB(Knowledge Base)

为使模型与知识库语义匹配,知识通常以向量形式存储,在向量数据库(Vector Database) 中,将文字转换为词向量这个过程叫词嵌入(Embedding) ,对比词向量间的相似度,在知识库中找到相关问题的答案,此过程称为向量检索Vector Search

解决大模型的幻觉问题后,AI即可真正介入生产和生活中。在内容创作领域,传统由专业机构如影视公司、媒体机构、权威专家等创作的内容称为PGC(Professionally Generated Content)

随着移动互联网和自媒体时代的到来,由普通用户创作的内容称为UGC(User Generated Content)

在AI时代,由AI创作或辅助创作的内容称为AIGC(AI Generated Content)

正向案例是内容公司通过AI加快产出速度、提升内容质量。反面案例是很多人用AI洗稿并疯狂产出内容,污染互联网内容生态。

此处易混淆的词是通用人工智能AGI(Artificial General Intelligence),它是对人工智能最终形态的畅想,即通用人工智能大模型逐渐发展。

AI不仅能处理文本内容,也能处理图片、声音、视频等多种形式的内容,这种处理多种模式内容的能力称为多模态Multimodal

有时需多次使用大模型能力,如第一步将口播稿分段,第二步给每个段落写成文生图的提示词,第三步生成一张合适的图片。这种将多个步骤编排成流程的能力称为工作流Workflow

包括在页面上进行傻瓜操作编排工作流的工具,如扣子Coze ,以及用代码方式编排工作流的框架,如LongChain

按照工作流封装大模型和一整套工具集,用于自动完成某一类复杂任务的程序称为一个智能体Agent

多个智能体互相协作完成更复杂任务的程序称为多智能体Multi-Agent

ChatGPT的插件系统、早期昙花一现的Auto GPT 以及最近又昙花一现的Manus都属于智能体。

智能体需操作各种应用,如打开浏览器、上网、打开计算器进行算术或操作手机上的微信发送一条信息等,实现托管。为方便操作,外部数据源和工具,ASRobin公司于2024年底为AI系统提供了一个标准化的接口或协议,称为MCP(Model Context Protocal),给了AI一个操作外部世界的统一标准。

而谷歌于2025年4月推出的另一个用于agent和agent之间通信的协议称为A2A协议(Agent-to-Agent Protocal)

至此,大模型的生态开始百花齐放,未来的想象空间是无限的。尽管工作流、智能体、MCP等概念兴起,但其实都是老一套工程方面的事情。大模型本身能力已近极限,一方面模型大小达极限,一个顶级大语言模型训练成本超1亿美元。另一方面,模型能力也快达极限,前十名模型能力差距从两年前12%缩小到2025年初5.4%,前两名从4.9%缩小到0.7%,模型间差距几乎消失。

正所谓边际收益递减,因此开始探索其他方向,如模型压缩Model Compression ,以减少成本和方便个人使用,包括用更低精度表示模型中的浮点数进行量化Quantization

使用参数量较大的大模型指导参数量较小的小模型进行蒸馏Distillation

删除模型中不重要的神经元以实现模型稀疏,提高速度,即剪枝Pruning;

用更低成本改善微调方式,如**LoRA(Low-Rank Adaptation)**等;

从推理能力方向增强模型能力,如思维链Chain-of-Thought;

通过人类反馈的强化学习让模型更合人心,称为RLHF(人类反馈强化学习)

当然,当所有方向都难以改进时,还可以封装现有大模型接口并对外提供服务。通俗地说,就是套壳(封装并提供服务)

通过提供ai工具、ai服务、ai课程、ai社区等,帮助他人开发和使用ai能力的周边产品,这种方式在ai淘金热中帮助别人淘金以赚取收益,称为卖铲子(不直接卖金子帮人淘金),卖铲子需要对ai各领域产品和生态了如指掌。

和文字相关的自然语言处理NLP有名的包括ChatGPT、claud、gemini、DeepSeek、豆包、通义千问、腾讯元宝等;

和图片相关的是计算机视觉CV,包括很多ai绘画应用。比如闭源的Midjourney、开源的stable diffusion;

绘画工作流软件ComfyUI等;

和语音相关的包括文字转语音的TTS语音转文字的ASR

和视频相关的包括Sora、可灵Kling、极梦等ai视频生成应用以及各种数字人Digital Human应用等。

除了帮助普通用户外,还可以帮助开发者更好地使用ai,比如像英伟达一样提供好的显卡即GPU ,以及配套的开发框架cuda

或者提供专门针对人工智能的处理器,比如专门用于大规模神经网络训练与推理的TPU 和专门用于终端设备推理的ai加速芯片NPU等。

软件方面,可以提供适合ai的编程语言python,提供针对ai编程的库如pytorch、tensorflow、scikit-learn等;

建设ai开源平台和社区如Hugging face

方便开发者本地运行大模型的工具如Ollama

提升大语言模型推理速度的推理引擎如vLLM

还有编程助手,如单独以软件形式存在的Cursor 、或插件形式存在的github copilot等。

ai时代瞬息万变,产品工具层出不穷,但其技术底座依然保持不变,

从最底层的线性代数、微积分、概率论、最优化等数学知识。

到深度学习用神经网络表示函数,以损失函数最小化为目标,通过反向传播训练参数。

再到后续的经典神经网络结构MLP,包括用于图像数据处理的卷积神经网络CNN、用于序列数据处理的循环神经网络RNN,以及引爆整个大模型时代的注意力机制和基于注意力机制发明的Transformer架构,它们共同构建了现代AI技术的基础。

相关推荐
Flying pigs~~3 小时前
LoRA 面试完全指南:低秩分解原理 + Transformer 应用
人工智能·深度学习·lora·大模型·微调·transformer
高洁014 小时前
大模型部署资源不足?轻量化部署解决方案
python·深度学习·机器学习·数据挖掘·transformer
隔壁大炮6 小时前
Day07-RNN介绍
人工智能·pytorch·rnn·深度学习·神经网络·算法·numpy
jllllyuz7 小时前
CNN卷积神经网络MATLAB实现:高速精确的图像分类
matlab·分类·cnn
数智工坊9 小时前
【SIoU Loss论文阅读】:引入角度感知的框回归损失,让检测收敛更快更准
论文阅读·人工智能·深度学习·机器学习·数据挖掘·回归·cnn
高洁0110 小时前
AI项目团队意见分歧?协调与决策方法
人工智能·深度学习·数据挖掘·transformer·知识图谱
bst@微胖子12 小时前
PyTorch深度学习框架之基于CNN的手机价格分类任务
pytorch·深度学习·cnn
隔壁大炮13 小时前
Day07-词嵌入层解释
人工智能·深度学习·算法·计算机视觉·cnn
数智工坊13 小时前
【VarifocalNet(VFNet)论文阅读】:IoU-aware稠密目标检测,把定位质量塞进分类得分
论文阅读·人工智能·深度学习·目标检测·计算机视觉·分类·cnn