大白话之——浅尝深度学习,从神经网络到大模型

May 19, 202554 min read

神经网络(NN)基础

训练 - Training

梯度消失问题 Vanishing Gradient Problem

前向传播和反向传播

前向传播就是神经网络拿到输入,然后一层一层地计算输出,最后得出预测结果。

那么,什么是“反向传播”呢?因为我们想要“教”神经网络学东西,但神经网络的结果有误,却不知道哪里错了。

所以,我们需要通过反向传播,来告诉神经网络每一层应该怎么调整。

TEXT
梯度消失

举个例子,假设我们有一个简单的神经网络:

  • 输入 x = 1
  • 隐藏层(1个神经元)
  • 输出层(1个神经元)
  • 激活函数 g(x) = sigmoid(x)

假设权重:

  • 输入到隐藏层的权重 w₁ = 0.5
  • 隐藏层到输出层的权重 w₂ = 0.5

对于隐藏层,输入是:z₁ = x × w₁ = 1 × 0.5 = 0.5,输出是:a₁ = sigmoid(0.5) ≈ 0.62

对于输出层,输入是来自隐藏层传递:z₂ = a₁ × w₂ = 0.62 × 0.5 = 0.31,输出是:a₂ = sigmoid(0.31) ≈ 0.58

网络输出为 0.58,假设目标是 1,我们知道它错了。

现在,网络进行“反向传播”,每次传播回来,要乘上激活函数的导数 g'(x)。

Sigmoid 函数的导数 σ ′(x) 的最大值是 0.25,这个最大值在 x=0 时取得。

那么问题来了,如果你有很多层,每一层都乘一个 小于 1 的数(比如 0.25),那越乘越小,比如:0.25 × 0.25 × 0.25 × 0.25 × ... ≈ 接近 0

这就意味着:越前面的层,更新得越少,学不到东西,这就叫梯度消失!

非零中心问题 Not Zero-Centered Problem

激活函数

诶,前面只顾着用但忘记讲了,什么是激活函数呢?

激活函数就是神经网络中每个神经元的“小开关”,它把输入变成一个输出值,常见的像:

  • Sigmoid:输出值总是介于 0 到 1,比如 0.9 或 0.1
  • Tanh:输出值在 -1 到 1,比如 -0.8、0、0.9
零中心 zero-centered

其实就是以0为中心,输出结果在0的左边(比0小)或者右边(比0大)的都有,也就是输出结果既有正数也有负数。

比如 Tanh 输出可以是 -0.5,也可以是 +0.5,这叫 zero-centered。

而 Sigmoid 输出总是在 0 以上(从不为负),这就不是 zero-centered。

而本节讲的非零中心问题 Not Zero-Centered Problem,也就是说输出结果没有正负存在的话,就会出现问题。

为什么会出问题?

那么,为什么非零中心就会有问题呢?

想象你在用“梯度下降”让神经网络慢慢变聪明——你要不断调整权重(weights)去找最优值。

假设你有两个权重:w₁ 和 w₂,期望它们会不断进行学习调整。

可是,如果你的激活函数(比如 Sigmoid)输出的都是正值,你算出来的梯度也可能都是正值。

梯度 = 输出误差 × 激活函数的导数 × 输入值,这3部分的乘积影响了梯度的“方向”和“大小”。

对于Sigmoid,每层的输入值、导数都是正的,所以 w₁ 和 w₂ 就会一直 “都增加” 或者 “都减少”,导致权重更新方向不平衡,训练更慢、更难收敛。

梯度 gradient

是的,这里又出现了新词——梯度。

顾名思义,梯度就像楼梯每一个阶梯的高度一样,决定我们修改权重时要迈出的每一步的大小。也就是——现在这个权重应该变大还是变小?变多少?

假设w1的梯度为+0.02,w2的梯度为+0.01,那么,w1、w2权重在更新之后就会变成w1=w1-0.01w2=w2-0.01

Z型路线 zig-zag

回到“为什么会出问题?”这个问题。

正因为非零中心,导致不同权重的更新方向一致,也就是——导致梯度对不同权重的贡献方向一致(不是一起增就是一起减)。

就像你在走楼梯时,每走一阶,左右脚都在朝着同一个方向歪着走,结果就容易变成蛇形走位(锯齿形、Z 字型)。

因此,我们希望激活函数以零为中心。

激活函数的选择 Choice of Activation Function

我们在前面已经介绍过“激活函数”的概念,激活函数实际上决定了:输出值的范围、网络能不能学到复杂的模式、梯度是不是能够顺利传回来等问题。

我们有三种常见的激活函数——Sigmoid、TanH、ReLU。

它们长这样(可以提前标记一下该图,后面将参照对每个激活函数进行解析):

Sigmoid——S曲线

正如上节的图所示,这是一条“S曲线”。

公式sigmoid(x) = 1 / (1 + e^(-x))
输入范围任意数
输出范围(0, 1)(都是正的)
导数 (g’)sigmoid'(x) = sigmoid(x) * (1 - sigmoid(x))

它其实以前很流行被用做激活函数,正因为它的输出——0~1,非常像“概率”,因为概率也是0~1,看起来有意义。

但缺点也正如同我们上面所分析的,它会有:梯度消失问题、非零中心问题,以及其含有exp(x)(exp(x) = e^x,指数函数)导致计算会变慢、效率低。

Tanh——双曲正切

tanh函数其实是sigmoid函数向下平移和收缩后的结果,是其具备了零中心的特性。

公式tanh(x) = (e^x - e^(-x)) / (e^x + e^(-x))
输入范围任意数
输出范围(-1, 1)(符合零中心)
导数 (g’)tanh'(x) = 1 - tanh(x)^2

但同样的,其也会存在梯度消失的问题(函数特性相对于Sigmoid没变,只是向下平移了),并且也用了exp(),运算慢。

ReLU——线性整流函数

ReLU 广泛应用于CNN(从AlexNet 开始),其中一个原因就是:计算特别快——它无需计算exp(x),只要对比一下大小就行。

公式ReLU(x) = max(0, x)
输入范围任意数
输出范围[0, ∞)
导数 (g’)ReLU'(x) = 0 if x < 0, 1 if x > 0

除此之外,根据图像可知,它对于正值输入部分,没有梯度消失的问题。

但对于负值的输入,它直接输出是0了...导致导数也是0 → 进而使其梯度完全没了→ 神经元会鼠掉(永远不再更新)。这是它的一个缺点,也是我们常说的“ReLU 的神经元死亡问题(Dying ReLU Problem)”。

另外一个缺点就是,它不是一个零中心的激活函数。

下面是ReLU的一些变体:

名字公式优点缺点
Leaky ReLUmax(0.01x, x)负数部分也给一点梯度(不死)有点偏正
Parametric ReLUmax(ax, x),a 是可学习的像 Leaky ReLU,但更灵活增加参数
ReLU6min(max(0, x), 6)限制最大值,防止爆炸非连续,仍非零中心
ELUx (x≥0), α*(exp(x)-1)(x小于0)有负输出又平滑要计算 exp(),慢
Maxoutmax(w1x + b1, w2x + b2)更强大参数量变成 2 倍

计算机视觉 - Vision

计算机视觉&卷积神经网络 Vision&CNN

什么是计算机视觉?

就是让电脑“看”图像和视频,并理解里面是什么东西。

就像你看到一只猫,你能立刻知道它是猫。我们希望让电脑也能像人一样做到这一点。

基于计算机视觉,我们可以联想到其在生活中的应用:

应用场景举个例子
图像识别Google Photos 识别“狗狗”或“人脸”
视频搜索快手/抖音用 AI 给你推荐内容
安全系统人脸识别开门、刷虹膜、刷指纹
医学图像处理识别 X 光片里的肿瘤
机器人机器人走路需要“看清”前方障碍物
自动驾驶Tesla 自动识别红绿灯、行人、路标等
计算机视觉为何兴起?
  • 拍照、录像变得很便宜(手机摄像头 + 网络)
  • 视频内容越来越多(2022年,视频占了整个网络82%的流量)
  • 每年互联网用户还增长10%

所以——我们很需要AI能处理图像/视频

计算机视觉的挑战

其实,想让计算机理解图片,是很有挑战的。

科学家常用自然动物的特性来研发新产品,我们可以想一下为何人、动物能理解视觉?

这其实要说到进化论——人类花了10万年进化出抽象思考,花2.3亿年进化走路,又花了5.4亿年进化出视觉感知。

科学家Hubel和Wiesel曾在1959年做实验,分析猫大脑的电信号,在其观察图片时,他们发现:猫的大脑是按“层”来处理图像的——比如,先看边缘和线条 → 再看形状 → 再看“对方是不是猫”等这类抽象的概念。

其实,人类也是这样分层感知图像的。所以现在的神经网络,比如 CNN(卷积神经网络)也模仿这个结构。

但计算机视觉毕竟不是生物,其还受制于图片输入的挑战,比如说:尺寸不一样、角度变化、背景杂乱、同一种东西图片差别大、光线变化、多个物体同时存在、要找出具体区域等问题。

更专业来说,举个例子,数图里的香蕉有几根,计算机视觉需要有目标计数(Object counting)的能力;找出哪里是树,哪里是地面,则需要语义分割(Semantic Segmentation);看视频里有没有人走进房间,则需要动作检测...

初识卷积神经网络 Convolutional Neural Networks (CNNs)

在1998年,Yann LeCun用CNN和反向传播算法识别了手写数字(MNIST 数据集),准确率高达 99.67%,比人类还强。

CNN正如上述所说,是通过分层来处理的,并且分为了两个板块:

第一个板块是特征提取,这里包括了卷积层(Convolutional layer)和池化层(下采样层)(Pooling (subsampling) layer)。

第二个板块是分类,这里包括了全连接层(Fully connected layer)。

第一层是输入层,用于接收原始数据。

CNN-卷积层 Convolutional layer

卷积层就像一个会滑动的小窗口,用来一块块“扫描”图片局部,通过乘法 + 偏置计算出每块区域有没有特征,然后拼成一个新图(特征图)继续传下去。

其中,“会滑动的小窗口”就叫滤波器(Filter / Kernel)。它是一组固定大小的权重(比如 3×3 的权重矩阵),负责“检查某种特征”,比如:边缘、角、亮暗变化等。

然后,通过滤波器每次滑动时候覆盖的那一块小区域就叫做局部感受野(Local Receptive Field),比如这个小窗口是 3×3,那它每次“看的”就是图片中的一个 3×3 小块。

还有一个参数共享(Parameter Sharing)的概念,意思是:同一个滤波器(也就是同一组参数)在整张图上反复使用。

卷积完了之后,会对结果立马套一个激活函数,常用的是 ReLU(把负数变0,正数保留)。图像通过卷积层,最终生成特征图(feature map)作为输出传给下一层。

以上是一个步长为1的滤波器,代表着每次滤波器的那个窗口移动1格,最终我们得到一个6*6的特征图。

填充 Padding

在上面我们观察到,原始图像经过滤波器后,得出的结果矩阵会比输入的要小。而Padding 的意思是:在图片的边缘“补一圈零”,让卷积之后的图不变小。

加上Padding后,我们卷积层的输出矩阵大小变为:(N+2P-F)/S+1,其中N = 输入图大小,F = 滤波器大小,P = padding 大小,S = 步长 stride。

CNN-池化层 Pooling layer

池化层 = “信息压缩层”,通常是紧跟在卷积层之后使用的,它们是一前一后配合使用,像搭档一样,一个提取特征,一个简化特征。

具体来说,它会用一个小窗口(比如 2×2)在图像上滑动,每次只保留一小块里的最大值或平均值,从而把图像缩小、简化。

池化层不用到激活函数,因为它本质是“取最大值”或“取平均值”,这个操作本身就是非线性的,不用额外加激活函数。

池化有以下好处:

  1. 减少数据量:减少图片尺寸,加快总流程速度,节省内存。
  2. 减少参数,防止过拟合。
  3. 实现“位置不敏感”(Translation Invariance)。比如说,如果猫在图片中稍微移动了位置,池化后还是能够认出来,因为池化层会把附近的一堆值“压缩成一个代表值”(比如最大值),这样就不关心你这个“亮点”原来具体在哪,只关心在不在就行。
CNN-全连接层 Dense layer

全连接层(Fully Connected Layer),也称为密集连接层(Dense Layer),是深度学习神经网络中的一种基本层类型,其每一个神经元都和前一层的所有输出相连接。

Dense(全连接)层就是把前面 CNN 找到的所有“特征”拉成一条线,然后统一做最终判断,比如“这是不是一只猫”。

通过前面所说的卷积层、池化层,我们实现了对图片的一块块扫描(卷积),提取出了特征(哪些地方有耳朵、眼睛),然后用池化压缩、简化这些信息,这些都保留了空间结构(比如耳朵在猫的上方,腿在猫的下方)。

到了最后一步,我们不再关心这些特征的具体位置,而是只想知道:“有没有耳朵?有没有眼睛?那就是猫!”

所以我们把这些信息,全都“拉平”成一条向量(flatten),然后送给全连接层判断。

ImageNet

ImageNet 是一个超级大的图片库,里面有超过 1400 万张图片,而且每张图片都标注好了这是什么东西。

我们期待AI学会“看图说话”,就需要将ImageNet这种带有很多标签的图像喂给AI进行训练。

由此也有了,ImageNet Challenge竞赛,这是一个图像分类的世界级比赛,谁的 AI 模型在这上面得分高,谁就是图像识别界的佼佼者。

常见的模型有AlexNet 2012, ZFNet 2013, VGNet 2014, GoogLeNet 2014, ResNet 2015, ReduNet 2022等,我们这里只抽一些来讲。

VGNet 2014

VGGNet 是牛津大学的一个研究团队(VGG = Visual Geometry Group)在 2014 年提出的一个深度卷积神经网络模型。

重点特点是:用很多个小的 3x3 卷积层,一层一层叠得很深,结构非常规整、漂亮,像“堆乐高”。

GoogLeNet 2014

GoogLeNet 用 Inception 模块聪明组合不同大小的卷积核,同时又节省计算资源,是 AlexNet 的升级加强版。

你可以想象 Inception 模块是这样的场景:图片里有大猫、有小狗、有细节、有整体……你用 1x1、3x3、5x5 的卷积“眼睛”去看,看完再把结果拼起来,就能看清楚不同尺寸的特征。

ResNet 2015

我们总结一下前面的两个模型:

  • VGNet(2014)是简单粗暴的堆卷积。它堆很多 3×3 的卷积,网络很深(16或19层),但结构很整齐,结果很好,但参数超级多(138M 参数!)——很占内存,也难训练。
  • GoogLeNet / Inception v1(2014)是聪明节省资源。用Inception模块来并行试不同的卷积(1x1、3x3、5x5)+ pooling,一次搞定多个尺度特征。然后把结果 concat(拼在一起),这样网络自己决定用哪个。用了大量的 1x1卷积 来降低通道数,降低计算量。

虽然 VG 和 GoogLeNet 都是深网络,但“更深≠更好”,层数越多,更会导致梯度消失、优化困难、训练误差反而变大了!

而ResNet利用“残差”连接,如果说传统网络是输入 x → 网络 → 输出 H(x),那么ResNet就是输出 = F(x) + x,其中F(x)就是残差,代表ResNet只学习变化的内容。如果F(x)=0,则输出直接等于了x,这就说明网络优化后至少不会比原来的差,这就避免了“越深越差”的问题!

Visualizing and Understanding CNN

这是一篇 Zeiler 和 Fergus 在 2013 年的论文,其目的是帮助我们看懂 CNN(卷积神经网络)到底“看”到了什么。

遮挡敏感性测试 Occlusion Sensitivity

我们很好奇,网络是否真正识别了物体?

于是,就有了这个测试,它用一个灰色方块,遮挡图片的某一小块区域,观察 CNN 是否还能正确预测。

比如,原图是狗,用灰块遮住耳朵/眼睛/身体某个部位,如果遮住某块区域后预测准确率大幅下降,说明这块区域是 CNN 非常“在意”的。

重复这个过程,滑动这个遮挡块,把整张图都测一遍,得到一个“热图”:亮的区域代表不重要(遮住也能预测),暗的区域代表很重要(遮住后预测就错),这就叫做显著性图(Saliency Map)。

梯度上升法可视化神经元 Gradient Ascent

我们还期望知道,神经元到底关注什么?

梯度上升(Gradient Ascent)法创建一张“假的图片”,让它能激活网络中的某个神经元最强。

简单来说,举个例子,随便弄一张黑色图片(全是0)作为输入,然后正向传播计算这个图激活神经元的值(比如:图像是“狗”的概率分数),再反向传播,计算改变哪些像素能让得分变高。这时,微调图像像素,让它越来越“像”神经元想看到的样子,并不断重复这个过程进行像素微调,最终得到一张“合成图”,可能是一个狗的轮廓、键盘、大象等等。

这说明:网络是通过某些特定图案来认物体的,而不是瞎猜。

最强激活图块 Maximally Activating Patches

我们还可以用最强激活图块法,来测试每层的神经元到底关注啥。

网络里的每个神经元都对一些图案特别敏感,比如第 N 层的某个神经元可能特别喜欢看到“轮胎”。

在这个方法中,我们用很多图片去喂CNN,找到那些让某个神经元“反应最快”的图块,然后把这些图块(patches)显示出来。

通过观察结果,我们可以看到:越往后面的层,看到的图案越复杂,比如:第一层 → 只看到边缘、角落等基本图形,第五层 → 可能能看到狗脸、汽车、沙发。

如何找到相似图片?

最简单的方法,我们可以使用“像素空间”(Similarity Measures / Euclidean distance),也就是,比较图片的每个像素,像素值越接近越相似(欧几里得距离)。但这种方法只能找出看起来很相似的图片,但也许实际上图片的内容根本无关,如下所示:

这时,我们可以使用“特征空间”,我们把图片输入到CNN,取最后一层的feature vector(比如4096堆),然后用向量距离(比如欧几里得距离)比较图片的特征向量,这样以来,我们就可以避免颜色、角度、大小等干扰因素,确保只关注“图像内容”本身。

对抗样本 Adversarial Images

对抗样本就是:“一张肉眼看不出变化的图片,但能让 AI 模型(如 CNN)认错。”

比如我们原图是一只熊猫,CNN预测正确。

这个时候,我们在图像里加入一点点“噪音”,CNN 却把这张图认成 🐒 长臂猿(gibbon)。

为什么CNN容易被骗?

因为人类识别熊猫靠的是抽象特征(黑眼圈、大白脸、毛发),而CNN是靠像素之间的微妙数学关系,所以稍微动一动像素,就可能严重影响模型的判断。

这么一来,对抗样本可能严重威胁机器学习的结果,比如:自动驾驶车看不出停车牌,对抗样本把“停车标志”变得像“限速标志”,车就会不停下来。又或者安检机器识别错武器,把一把刀加入噪音使CNN看起来像雨伞,安检就放行了。

如何制作对抗样本?

对抗样本是我们知道了模型的内部结构、权重和参数,因此专门设计对抗扰动去欺骗它,也被称为白盒攻击(White-box attack)。

白盒攻击最常见的方法是快速梯度符号法——FGSM(Fast Gradient Sign Method),其用于快速生成对抗样本(欺骗模型)。

其公式为:adv_x = x + ε × sign(∇x J(θ, x, y)),其中:

  • x:原图
  • y:原来的标签(比如“猫”)
  • J():损失函数,衡量模型输出错得多严重
  • ∇x J:告诉我们“动哪些像素能让模型出错最多”
  • sign():只取方向(加还是减)
  • ε:扰动强度(越小越不容易被肉眼看出来)
  • adv_x:最终得到的对抗图片

当我们想要故意攻击模型,使其识别为指定的错误类别,这种过程也叫做目标攻击(Targeted Attack)。

只有神经网络会被骗吗?

其实不是,很多机器学习模型都会被骗,比如linear models,SVM,k-nn等等。

甚至是人脑,其实也会被骗。还记得互联网刚兴起的时候,就有许多视觉错觉的图片,这就是一种对人类大脑的“对抗样本”。

如何防御对抗样本攻击?

办法很简单:在训练的时候,加入对抗样本当作正常样本来训练模型。

比如,原图(猫)→ label 猫,对抗图(被修改过的猫)→ 也标注为猫。

经过反复训练,模型会学会“这个猫虽然加了噪音,也是猫”,从而增强鲁棒性。

深度生成模型 - Deep Generative Models

生成对抗网络 (GAN) Generative Adversarial Network

GAN 是一种用神经网络生成“假数据”的方法,训练过程像玩游戏:两个网络互相对抗。

GAN里面有两个网络:

名字作用类比
Generator(生成器)制造“假货”图片(比如假人脸、假猫)造假者
Discriminator(判别器)判断图片是真货还是假货鉴定专家

他们互相斗争——生成器想办法骗过判别器,判别器想办法识破生成器的伪装。

其目标就是当判别器输出为 0.5 时,表示它完全分不清真假 —— 成功!

如上图所示,判别器D对于输入x(真实图像),D(x)=0,代表其认为这是假的,所以这个时候要修改判别器的参数。

判别器D对于输入G(z)(假图像),D(G(z))=0,代表判别器成功识别出假图,这个时候需要修改生成器的参数;D(G(z))=1,代表判别器成功被生成的假图所欺骗,这个时候需要修改判别器的参数;

当然,如果D(G(z))在0~1范围,这个时候判别器和生成器的参数都需要修改。

判别器(Discriminator)训练

我们通过输入一些真实样本和生成器生成的样本作为输入进行训练,并通过反向传播(backpropagation)修改权重,目标是最小化分类的错误。

生成器(Generator)训练

用随机变量z生成图片G(z),并让判别器判断G(z),希望它误判为真(即D(G(z))=1)。通过反向传播(backpropagation)修改生成器的权重,使得G(z)接近真实图像。目标是最大化判别器的错误。

损失函数 Loss Function

“损失”= 模型做错的程度——模型越笨、越不准,损失越大;模型越聪明、越准确,损失越小。

  • 对于判别器的损失:max_D{ log(D(x)) + log(1 - D(G(z))) }

    其中,对于判别器,我们希望log(D(x))越大越好(即,给真实图打高分更好),log(1 - D(G(z)))也越大越好(即,给假图打低分更好)。

  • 对于生成器的损失:min_G{ log(1 - D(G(z))) }

  • 对于总体目标:min_G max_D{ [ log(D(x)) + log(1 - D(G(z))) ]}

GAN常见的问题

第一个是:模式崩溃(Mode Collapse)

即,生成器只会画一种图(比如总是画猫脸朝右),不会画多种图,因为其只学会了一种骗判别器的方法。

第二个是:不收敛(Non-Convergence)

即,训练中两个网络像“零和博弈”,你赢我输,导致 GAN 在训练时可能一直互斗,模型不稳定。

第三个是:图像失真(Distorted Figures)

即,有时候图像生成怪异、扭曲,表示训练不充分或设计不合理。

自然语言处理(NLP) - Natural Language Processing

我们梳理一下,最开始我们讲的NN神经网络,其中涵盖了许多方向。比如,Vision就是视觉方向,用于处理图片等信息,CNN常用于Vision来识别图像特征;GAN则是一种生成对抗网络的技术,可以用在Vision,来生成对抗样本调节模型;而本节讲的NLP则是语言方向的应用,用于处理文本、语言等方向,比如ChatGPT这类。

所以,简单说,NLP就是让计算机能“理解人类的语言”。

注意力机制 Attention

“Attention” 就是“注意力机制”。想象你在翻译一句长句子:He likes to eat rice.

普通的神经网络,比如 LSTM,有一个大问题:忘记前面说了什么。当网络解码到“吃饭”的时候,前面的“likes”已经忘了……

如果没有注意力机制,模型只能依赖“最后一句话的信息”,可能会忘记前面的内容。

Attention 就像人类的大脑一样:每次翻译一个词的时候,就去原句里“扫一眼”,看看哪个词最相关。

其原理是,通过给输入句子里的每个词 打分 + 分配注意力:

  1. Encoder会将英文的每个词变成向量,比如:

    英文词向量 hi
    Heh1
    likesh2
    toh3
    eath4
  2. Decoder在翻译中文“喜欢”的时候,使用状态s标识。比如Decoder当前状态是s_t。

  3. 计算英文每个词对现在这个s_t的相关性(匹配程度)。

    e1 = match(s_t, h1) e2 = match(s_t, h2) e3 = match(s_t, h3) e4 = match(s_t, h4)

    这表示 “我现在在翻译‘喜欢’,那英文里哪些词跟它最相关?”

  4. 用 softmax 把这些分数变成“注意力分布”

    a1, a2, a3, a4 = softmax(e1, e2, e3, e4)

    假设likes的注意力分数a2为0.7,是最大,那我们应该将注意力放在likes上。

  5. 生成一个“上下文向量” = a1·h1 + a2·h2 + a3·h3 + a4·h4

    这个向量就是综合加权结果,告诉 Decoder:“这是你要翻译‘喜欢’时应该关注的英文信息”。

Transformer模型

Transformer 是 Google 在 2017 年发明的一个深度学习模型,最初是为了自然语言处理(NLP)设计的,现在也广泛用在图像处理(Computer Vision)里,比如 ChatGPT 和 Midjourney 背后都用了这个技术。

它的核心论文叫:《Attention is All You Need》

整体架构

Transformer 是一个“编码器-解码器(Encoder-Decoder)结构”,分两大块:

  1. 编码器(Encoder):负责读懂输入,比如翻译时的英文句子。
  2. 解码器(Decoder):负责一步步生成输出,比如翻译后的中文句子。
推理阶段 Inference

以翻译为例,它是怎么一步步生成中文句子的呢?

  • 步骤 1:输入转换成 Embedding,喂给编码器(Encoder)

    • 我们把句子 “I love AI” 转成数字向量,叫 Embedding。
    • 然后送进一堆编码器(Encoder Stack)。
  • 步骤 2:编码器处理这个句子,理解它的含义

    • 编码器就像一个“理解机器”。
    • 它看每个词之间的关系(用 Attention)来理解句子的真实意思。
    • 输出:对这句话的“深层理解表示”。
  • 步骤 3:解码器准备开始翻译,第一步先输入 <s>(开始符号)

    • <s> 就像“开始说话”的信号(Start of Sentence)。
    • 把 <s> 转成 Embedding,然后送进解码器。
  • 步骤 4:解码器用两部分信息来猜第一个词

    解码器的“脑子”有两个来源:

    • 自己之前看到的输出(现在只有 <s>)
    • 编码器输出的“整句含义”

    这两个信息一起进来,它开始猜:“第一个翻译的词应该是啥?”

  • 步骤 5:输出层把 decoder (解码器)的结果转成“猜的词的概率”

    比如:“我”:80%、“你”:10%、“它”:5%。

    用 softmax 选出概率最大的词作为翻译的第一个词。

  • 步骤 6:把刚刚预测出来的词(比如“我”)加到 decoder 的输入里

    下一轮 decoder 输入就是:[<s>, 我]

    然后再去猜第二个词,比如:“爱”

    再下一轮是:[<s>, 我, 爱] → 猜 “人工智能”

  • 步骤 7:重复刚刚的流程,直到翻译完

训练阶段 Training

还是以翻译为例,训练的目标是,模型学习如何从英文猜出正确的中文,每次输出一个字。

  • 步骤 1:输入句子变成 Embedding,送入编码器(Encoder)

    • 先把英文 I love AI → 转换成数字向量(Embedding)
    • 喂进 Encoder Stack,让它理解这句话的“意思”。
  • 步骤 2:Encoder 理解这句话,输出“含义表示”

    Encoder 会处理句子所有词之间的关系,输出一句话的理解结果(我们叫它“隐藏表示”)。

  • 步骤 3:把目标句子(“我 爱 人工智能”)右移一位后,送入 Decoder

    比如:目标句子是:<s> 我 爱 人工智能

    右移一位就变成:<s> 我 爱 ,目标要预测的是后面的人工智能

    Decoder 要学会:每次看 <s> → 猜 “我”,再看 <s> 我 → 猜 “爱”,再看 <s> 我 爱 → 猜 “人工智能”。

  • 步骤 4:Decoder 一边看目标句的开头,一边看 Encoder 的理解结果

  • 步骤 5:输出层把 decoder 的结果转成“词的概率”

  • 步骤 6:计算损失 Loss,反向传播(Backpropagation)

    计算“预测值”和“真实答案”的差距,叫做 Loss(损失)。

    然后用这个差距来反向调整整个模型的参数(叫反向传播),让它下次预测得更准。

Teacher Forcing训练

其实前面讲的Training阶段就是Teacher Forcing训练的一个例子。

Teacher Forcing就是用正确的词去喂给AI,而不是依靠AI推测出的词再喂回去。也就是,训练的时候,不管 AI 猜得对不对,都直接告诉它正确答案,让它用“对的词”继续学下去。

不用Teacher Forcing会发生什么呢?

比如:我 爱 人工智能,AI把猜成了喜欢,然后把喜欢喂回去,让它继续“将错就错”。

这样会导致:

  • 错误越滚越大。假设第一个词就错了,下面就会在错的基础上继续猜。
  • 太慢了。如果一个词一个词地跑,每次都要等前面的词预测完,速度非常慢。而Teacher Forcing可以一次性并行地预测整个句子的所有词。

BERT模型

BERT(Bidirectional Encoder Representations from Transformers),基于 Transformer 的双向编码表示。

BERT 是一种基于 Transformer 的模型,是 Google 提出的一个强大的自然语言理解模型,它可以理解句子里的每个词是啥意思、跟其他词的关系。

整体架构

Transformer 有两个部分:Encoder 和 Decoder,BERT 只用了 Encoder,专注于理解(而不是生成)。

预训练方式

BERT使用两种“填空题”练习法训练模型。

第一种是,Masked Language Model(MLM),也就是随机把句子里 15% 的词遮住(变成 [MASK]),让模型猜出被遮住的词。

第二种是,Next Sentence Prediction(NSP),给模型两句话,问它第二句话是不是第一句的下一句。其中,输入数据一半是真的(顺序对),一半是随机拼的,这个任务帮助模型理解句子之间的关系。

应用

BERT 就像一台“语言理解引擎”,我们可以在它上面加一个小层,来做各种任务。比如:

  • 文本分类(比如情感分析、新闻分类等)
  • 命名实体识别(NER)
  • 问答系统(QA)

大语言模型 - LLMs

模型大小 Model Size

Transformer 模型有多少个参数?

Transformer 的“模型大小”(Model Size)= 各个部分的参数加起来

符号含义举例
E每个 token 的向量长度(Embedding size)比如 768、1024
H注意力头的数量(Number of heads)比如 12 个头
EH等于 E × H(总共 attention 用了多少空间)768×12=9216

对于Encoder模块:

其结构大概是:输入 → 多头注意力 → 加残差 & 标准化 → 前馈神经网络 → 加残差 & 标准化

对于多头注意力(Multi-head Attention),其用到了Wq、Wk、Wv、Wo这四个矩阵,每个大小是E × E,所以参数量=4E² + 4E(E² 是矩阵,E 是偏置项)。

对于前馈神经网络(Feed-forward),其为一个小型的2层神经网络:E → EH → E,用到了H × H和H × E两个矩阵,所以参数量=2EH + E + H(E + H是偏置项)。

对于标准化层(Layer Norm),其只要每个 token 加一个缩放和偏移的常数:2 × E,所以总参数为2E。

所以对于Encoder模块,其总参数为:4E² + 2EH + 9E + H(其中包含每层有 2 个 LayerNorm,位于Attention 后 + FeedForward 后),近似值为4E² + 2EH。

对于Decoder模块:

其多了一个组件:Masked Multi-head Attention,所以相比于Encoder模块,其多了一个Multi-head Attention,同时也伴随着多了一个Layer Norm,共三个(分别位于Masked-Attention后 + Cross-Attention 后 + FeedForward 后)。

所以对于Decoder模块,其总参数为:2*(4E² + 4E) + (2EH + E + H) + 3*(2E) = 8E² + 2EH + 15E + H,近似值为8E² + 2EH。

剪枝和蒸馏 Pruning and distillation

这里用GPT画了个流程图:

TEXT
剪枝 Pruning

意思就是:把 没用的部分剪掉(就像修树一样)。

具体来说,一般剪掉Attention Head(多头注意力里的“某几头”不重要,直接剪掉)、宽度/Channel(隐藏维度 H、embedding 维度 E 太宽,缩小它们)、深度/Layer(总共32层,删掉一半,变成16层,只保留连续的一段)。

如何定义不重要呢?

可以用小数据集跑一次前向,只看前向计算的影响,然后打分 → 排名 → 选出“重要的部分”。

就像一个厨师一样,做了一份菜,我们把配料一个个试着关掉一个,尝一口菜,看看有没有变化。

蒸馏 Distillation

意思是:让一个小模型学习大模型的行为,就像老师教学生。

具体来说:在Embedding 输出中,学习词的表示方式;在Attention / FFN 输出中,学习中间的每层输出(Block Loss);在最终输出 Logits中,学习最终预测哪个词(Logit Loss)。

基准指标 Benchmark metrics

LLM(大语言模型)要想评估“聪不聪明”,得像学生一样参加考试。这些“考试”就叫做 benchmarks(基准测试)。

这些“考试”有六大类:

名字中文意思测什么?
HellaSwag语境常识判断看模型是否知道日常生活中“最合理”的事
WinoGrande常识+指代判断看模型能不能理解“谁是谁”
MMLU多学科知识像大学生一样考法律、医学、历史等
ARC抽象推理能力解决看起来“人类轻松但AI难”的问题
GSM8K小学数学题多步算术推理(文字题)
MBPPPython 编程看模型能否写出对的函数来解决问题

LoRA微调和量化 LoRA fine-tuning and quantization

LoRA是什么

LoRA 是一种让“大模型变得容易微调(fine-tune)”的方法:

不直接改动原模型,而是偷偷在旁边加一个“小补丁”,这块补丁参数少、训练快,还不会破坏原本学到的知识。

为何需要LoRA

传统的微调方式有几个大问题:

  • 你要改动模型里的所有参数,这太大了(LLM 动辄上百亿参数)
  • 太耗内存、时间、钱(需要多个GPU,训练几天)
  • 用的数据少时,模型容易过拟合,反而变差
  • 想用这个模型做别的任务,得再训一遍,很麻烦

所以:我们希望只“小修小补”,不要“大动干戈”!

微调 Fine-tuning

微调其实就是拿一个已经训练好的大模型(比如 GPT),再喂一些你的新数据,让它适应新的任务或领域。这种方式比从头训练模型要快很多。

LoRA核心思想

LoRA其实就是没有动原来模型的参数,只在旁边加一个低秩矩阵,像一个可调节的外挂一样做调整。

假设模型中的某个权重矩阵为W0,LoRA不改W₀,而是加一个更新项 ΔW,让新的权重 = W₀ + ΔW。

而 ΔW 不直接训练,而是写成 ΔW = B × A,这样就只需要训练B和A两个小矩阵即可。

举个例子,如果说原来的输出是:h = W₀ x,那LoRA后,输出为h' = W₀ x + BAx(多了个补丁BA)。

量化 Quantization

量化的目标是减小内存和计算量。

我们思考:我真的需要那么高的精度吗?模型的每个数字都要到小数点后面6位甚至更多?其实不需要!

于是,我们可以把原来的高精度数字(FP32)“压缩”成低精度的整数,比如 Int8(8位整数)。

但注意!量化是有损压缩,可能会导致误差,如果压缩不当,还会影响模型效果。

对于LoRA,采用量化可以更进一步降低内存使用,甚至能让消费级显卡也能训练上大的模型。

提示词 Prompting

相信大家对Prompt已经很熟悉了,在日常使用ChatGPT中,我们会使用各种Prompt来让AI完成我们想做的事。

就像你对一个人说:“请帮我画一只科学家的猫”,AI 就会画出来。

Prompt类型
  1. 简单提示(Simple Prompt): 类似问答型的提问,如:彩虹有多少种颜色?

  2. 指令提示(Instruction Prompt):

    给出一个任务,AI 按你的意思完成。如:写一首鼓励人的诗,让我开心。

  3. 复杂提示(Complicated Prompt):

    包含表格、多个问题、信息抽取。如:下面是一个公司表格,问:哪家公司员工最多?

提示词的设计艺术 Prompt Engineering

我们怎么问问题、怎么给指令,才能让 AI 给出最好的答案呢?

我们可以用CO-STAR 框架这个写提示词的万能模板:

这是一个六步法:

缩写含义解释
CContext背景:你要做什么?
OObjective目标:你想 AI 做什么?
SStyle风格:写作风格、模仿谁?
TTone语气:温柔?专业?有说服力?
AAudience受众:给谁看?老人?小孩?专家?
RResponse回复格式:比如生成一个 Facebook 帖子

比如:我在做一个吹风机广告,帮我写个广告发 Facebook,卖吹风机给中老年人,模仿 Dyson 的风格。

上下文学习 In-Context Learning(ICL)

ICL被称为小样本学习(few-shot learning / few-shot prompting),和“微调模型”不同,ICL 不用重新训练模型,直接在 Prompt 里放例子就行了。

比如:

TEXT

AI 根据前两个例子,就能猜出:“Good meal!” 是 Positive。

思维链 Chain of Thought (CoT)

思维链就是让 AI 一步一步思考,就像做数学题一样写出过程,准确率大增,比如:

TEXT

思维链提高了 LLM 进行复杂推理的能力,可以让其有更高水平的数学能力。

零样本思维链 Zero-Shot Chain of Thought

Zero-Shot Chain of Thought是连例子都不给,就一句提示语让 AI 自己慢慢推理。

提示语通常是:“Let’s think step by step.”、“Let’s break this down.”、“Let’s solve this logically.”...

自我一致性 Self-Consistency

AI 有时每次想的答案不同,那怎么办?

我们可以让 AI 多次回答,再投票选出多数答案(就像民主投票)。

但缺点是:计算量大(每次都让 AI 再算 5~10 遍)。

草稿链 Chain of Draft

草稿链是不让 AI 想那么多文字,而是直接用公式、缩略步骤来推理,又快又准。

比如:

TEXT
提示词微调 Prompt-Tuning/P-Tuning

Prompt-Tuning(提示微调)是一种非常省参数的微调方法,意思是:

不用把整个大模型(几百亿参数)重新训练,只训练一小块,结果也能不错!

假设 LLM 是一个超级聪明的助理,但你不能改它大脑(太大了),只能在它“听见问题”之前加点引导。

具体来说,就是在前面加一个小模型:这个小模型不干别的,就负责把任务目标变成一段「特殊提示语」(虚拟 tokens)加在问题前面。

整体流程如下:

TEXT

浏览量

最后修改于

May 23, 2025
Made withbyMr.Ke