1 全连接神经网络

1.1 网络由哪些部分组成?

全连接神经网络包含输入层、隐藏层和输出层。输入层接收数据,隐藏层逐层变换特征,输出层产生预测。全连接指相邻两层之间,前一层的每个神经元都与后一层的每个神经元相连,连接上的数值就是权重。

图1:全连接网络与单个神经元的计算过程

1.2 神经元的数学表达

一个神经元分两步计算:

① 加权求和: z=∑i=1nwixi+bz=\sum_{i=1}^{n}w_i x_i+b

② 非线性激活: a=h(z)a = h(z)

把两步合起来记为 a=h(wTx+b)a=h(\mathbf w^{\mathsf T}\mathbf x+b)。整层网络可写成 a=h(Wx+b)\mathbf a=h(W\mathbf x+\mathbf b),其中激活函数通常逐元素作用。

符号 含义 怎么理解
x 输入数据 这一层收到的数值或前一层的输出
w / W 权重 / 权重矩阵 各输入对当前神经元的影响方式与程度
b 偏置 使激活前的结果可以整体平移
z 激活前的值 加权求和后的中间结果
h 激活函数 给网络引入非线性
a 激活后的输出 传给下一层的特征

用一个例子检验。 若 x=[1,2]x=[1,2],w=[0.5,−1]w=[0.5,-1],b=0.5b=0.5,则 z=1×0.5+2×(−1)+0.5=−1z=1\times 0.5+2\times (-1)+0.5=-1。若激活函数是ReLU,输出就是 a=0a=0。先算z,再算a,不要把两步混在一起。

1.3 为什么必须加入非线性激活?

如果每层只有线性或仿射变换,叠很多层仍能合并成一层。以两层为例:

W2(W1x+b1)+b2=(W2W1)x+(W2b1+b2)W_{2}(W_{1}x+b_{1})+b_{2} = (W_{2}W_{1})x + (W_{2}b_{1}+b_{2})

右边仍是一次仿射变换。用 h(x)=cxh(x)=cx 连续作用三次,得到 c3xc^3x,也是同一个道理。隐藏层中的非线性激活,使层的堆叠能够表达更复杂的关系。 输出层是否使用激活、使用什么激活,则由任务决定。

2 激活函数:形状、导数与训练问题

看激活函数要把函数是否饱和、导数是否接近零联系起来。反向传播会把沿途的局部导数连乘,很多小于1的因子连乘后可能非常小,前面层的参数就难以获得有效更新。

图2:四种激活函数及其导数

图2|上排为函数曲线,下排为导数。Sigmoid和Tanh两端变平;ReLU负半轴完全平坦;Leaky ReLU负半轴仍保留斜率。

2.1 Sigmoid

函数: σ(z)=11+e−z\sigma(z)=\frac{1}{1+e^{-z}}

导数: σ′(z)=σ(z)(1−σ(z))=a(1−a)\sigma^{\prime}(z)=\sigma(z)(1-\sigma(z))=a(1-a)。

Sigmoid把任意实数映射到 (0,1)(0,1)。当 z=0z=0 时,输出为0.5,导数达到最大值0.25;当z非常大或非常小时,输出趋近1或0,曲线趋平,导数趋近0,这就是饱和。

它常用于二分类的概率输出。但若许多隐藏层都使用Sigmoid,饱和区域的微小导数,以及连续相乘的较小导数,容易让靠前层出现梯度消失。它的输出也不是以0为中心的。

2.2 Tanh(双曲正切)

函数: tanh⁡(z)=ez−e−zez+e−z\tanh(z)=\frac{e^z-e^{-z}}{e^z+e^{-z}}

导数: tanh⁡′(z)=1−tanh⁡2(z)=1−a2\tanh^{\prime}(z)=1-\tanh^2(z)=1-a^2。

Tanh的值域为 (−1,1)(-1,1),关于原点对称,输出以0为中心。这改善了Sigmoid输出非零中心的问题,但两端仍会饱和,仍可能梯度消失。不能把“零中心”与“不发生梯度消失”画等号。

2.3 ReLU(修正线性单元)

函数: ReLU⁡(z)=max⁡(0,z)\operatorname{ReLU}(z)=\max(0,z)。正数保留,负数置零。

导数: ReLU⁡′(z)={1,z>0,0,z<0.\operatorname{ReLU}^{\prime}(z)=\begin{cases}1,&z>0,\\0,&z<0.\end{cases}。零点处数学上不可导,实际计算通常约定为 0。

ReLU计算简单,正半轴导数为1,不会像Sigmoid那样因正向输入很大而饱和,因而能缓解梯度消失。不过负半轴导数为0;如果某个神经元对训练输入持续输出0,它可能难以再通过梯度更新恢复有效响应,称为死亡ReLU。

注意: “ReLU解决了梯度消失”是简化说法。它改善了一种成因,不能保证深层网络中所有梯度都正常。

2.4 Leaky ReLU

函数: f(z)={z,z>0,αz,z≤0.f(z)=\begin{cases}z,&z>0,\\\alpha z,&z\le 0.\end{cases},其中 α 是较小的正常数。

导数: f′(z)={1,z>0,α,z<0.f^{\prime}(z)=\begin{cases}1,&z>0,\\\alpha,&z<0.\end{cases}。零点处的导数需要单独约定。

它给负半轴保留了一条非零梯度通路,从而缓解死亡ReLU。图中为了看清斜率使用 α=0.1\alpha =0.1,实际可选择其他较小值,例如0.01。这里α是负半轴斜率,后面的学习率统一记作η。

2.5 放在一起比较

函数 输出范围 主要特点 需要留意
Sigmoid (0,1) 常用于二分类概率输出 非零中心,两端饱和
Tanh (−1,1) 零中心 两端仍饱和
ReLU [0,+∞) 正半轴导数为1、计算简单 负半轴梯度为0,可能死亡
Leaky ReLU 整个实数域(α>0) 负半轴保留梯度 负半轴斜率需选择

3 训练网络:前向传播 → 损失 → 反向传播 → 更新

3.1 前向传播到底在做什么?

前向传播是使用当前的权重和偏置,逐层计算输出:x⟶a(1)⟶a(2)⟶y^\mathbf x\longrightarrow\mathbf a^{(1)}\longrightarrow\mathbf a^{(2)}\longrightarrow\hat y。概念上就是 y^=fθ(x)\hat y=f_{\theta}(\mathbf x)。此时只是在计算预测,还没有更新参数。

3.2 损失函数:把“预测差多少”变成一个数

回归任务的目标是预测连续数值;分类任务的目标是预测离散类别。我用一个回归例子理解训练过程,采用带1/2系数的均方误差:

J(θ)=12m∑i=1m(y^i−yi)2J(\theta)=\frac{1}{2m}\sum_{i=1}^{m}(\hat y_i-y_i)^2

其中m为样本数,ŷ为预测,y为真实值,θ代表模型参数。平方让正负误差不相互抵消;前面的1/2方便求导时与平方产生的2抵消。单个样本时,L=12(y^−y)2L=\frac{1}{2}(\hat y-y)^2。

把“预测的类别”和“网络内部的数值”分开理解:分类网络通常先输出连续分数或概率,再决定类别;训练常使用交叉熵。

图3:前向传播、损失、反向传播与参数更新

图3|训练中这四步各司其职:前向得到预测,损失衡量误差,反向求梯度,优化器更新参数。

3.3 反向传播与梯度下降有什么区别?

反向传播利用链式法则,从输出端向前逐层计算损失对各参数的导数。每个参数得到自己的梯度,例如 ∂J∂w\frac{\partial J}{\partial w}、∂J∂b\frac{\partial J}{\partial b}。

梯度下降利用这些梯度更新参数:

w←w−η∂J∂wb←b−η∂J∂b\begin{aligned}w&\leftarrow w-\eta\frac{\partial J}{\partial w}\\b&\leftarrow b-\eta\frac{\partial J}{\partial b}\end{aligned}

η是学习率,决定每次调整多大。梯度指向局部上升最快的方向,因此用减号沿负梯度更新。η太大可能震荡或发散,η太小可能进展缓慢。

我把训练分成两件事来记:反向传播求梯度,优化器用梯度更新参数。

3.4 我完整计算一轮训练

网络与初值

a=σ(xw11+b1)a=\sigma (xw_{11}+b_{1}),y^=ReLU⁡(aw21+b2)\hat y=\operatorname{ReLU}(aw_{21}+b_{2})。

输入 x=1x=1,真实值 y=2y=2;初始 w11=0.5w_{11}=0.5,b1=0.5b_{1}=0.5,w21=1w_{21}=1,b2=1b_{2}=1。

第一步:前向传播

z1=1×0.5+0.5=1z_{1}=1\times 0.5+0.5=1,a=σ(1)≈0.731059a=\sigma (1)\approx 0.731059。

z2=a×1+1≈1.731059>0z_{2}=a\times 1+1\approx 1.731059>0,所以 y^=ReLU⁡(z2)≈1.731059\hat y=\operatorname{ReLU}(z_{2})\approx 1.731059。

损失为 L=12(1.731059−2)2≈0.036165L=\frac12(1.731059-2)^2\approx 0.036165。

第二步:先求输出层梯度

由于z₂为正,ReLU在此处的导数为1。输出端误差信号为:

δ2=(y^−y)ReLU⁡′(z2)≈−0.268941\delta_2=(\hat y-y)\operatorname{ReLU}^{\prime}(z_2)\approx-0.268941。

因此 ∂L∂w21=δ2a≈−0.196612\frac{\partial L}{\partial w_{21}}=\delta_2a\approx-0.196612,∂L∂b2=δ2≈−0.268941\frac{\partial L}{\partial b_2}=\delta_2\approx-0.268941。

第三步:梯度继续传到隐藏层

δ1=δ2w21a(1−a)≈−0.052877\delta_1=\delta_2w_{21}a(1-a)\approx-0.052877。

因此 ∂L∂w11=δ1x≈−0.052877\frac{\partial L}{\partial w_{11}}=\delta_1x\approx-0.052877,∂L∂b1=δ1≈−0.052877\frac{\partial L}{\partial b_1}=\delta_1\approx-0.052877。这一步要乘上连接权重w₂₁,再乘上Sigmoid的导数,不能直接把输出层误差照搬过来。

第四步:取η=0.1,同时更新四个参数

参数 旧值 本轮梯度 更新后的值
w₁₁ 0.5 −0.052877 0.505288
b₁ 0.5 −0.052877 0.505288
w₂₁ 1 −0.196612 1.019661
b₂ 1 −0.268941 1.026894

用新参数再次前向,得到 y^≈1.77444\hat y\approx 1.77444,比原来的1.731059更接近真实值2。这里展示的是这一轮更新的效果;一般情况下不能保证任何学习率、任何一步都降低损失。

计算约定:同一轮所有梯度都由更新前的参数计算,再一起更新参数;中间保留足够精度,最后统一取近似值。

4 从图像到CNN:为什么不直接全部展平?

4.1 图像在计算机中是一组数

灰度图可以看作 H×WH\times W 的矩阵,也可保留通道维写成 1×H×W1\times H\times W;RGB彩色图有红、绿、蓝三个通道,按本笔记的约定记为 3×H×W3\times H\times W。

对常见8位灰度图,0表示黑,255表示白,中间数值表示不同灰度。但图像也可能经过缩放或标准化,不能认为送入网络的数值必须始终处于0—255。

本笔记统一使用 C×H×WC\times H\times W;批量数据则记为 N×C×H×WN\times C\times H\times W。N是样本数,C是通道数,H/W是高宽,三类维度要分别看。

4.2 全连接处理图像的局限

把图像展平成一维向量后,原来相邻像素的空间关系不再被全连接结构显式利用;同时参数量可能很大。例如32×32的RGB图像有3072个输入,若接1000个全连接神经元,仅这一层含偏置就有 3072×1000+1000=3,073,0003072\times 1000+1000=3,073,000 个参数。

展平本身只是重新排列数据,并不必然丢失原数值;真正的问题是网络结构没有利用图像的空间局部性。CNN通过局部连接与参数共享来改善这个问题。

  • 局部连接: 每次先观察一个局部窗口,学习局部模式。
  • 参数共享: 同一套卷积权重在不同位置重复使用,用同一特征检测方式扫描整张图。
  • 逐层提取: 后续层组合前面层的响应,形成更复杂的特征表示。

因此,CNN不是单纯的“图片压缩”。它的核心是学习特征;卷积不一定缩小图像,池化等下采样也会丢失部分细节。

5 卷积层:从一个窗口,算到整张特征图

5.1 一次卷积的四个动作

取局部区域 → 对应元素相乘 → 将乘积求和 → 加偏置。 窗口移动到下一个位置后,重复同样的运算,就形成输出特征图。激活函数通常在这一线性运算之后再作用。

图4:同一卷积核在四个位置滑动计算

图4|橙色区域是当前窗口。输入3×3,核2×2,步幅1、无填充,恰好有四个合法位置。

本例输入矩阵与卷积核为: X=[012345678],K=[0123]X=\begin{bmatrix}0&1&2\\3&4&5\\6&7&8\end{bmatrix},\quad K=\begin{bmatrix}0&1\\2&3\end{bmatrix}。

先计算左上位置: 0×0+1×1+3×2+4×3=190\times0+1\times1+3\times2+4\times3=19。滑动四个位置后得到输出: Y=[19253743]Y=\begin{bmatrix}19&25\\37&43\end{bmatrix}。

若偏置为 2,给每个输出位置都加 2: Y=[21273945]Y=\begin{bmatrix}21&27\\39&45\end{bmatrix}。同一输出通道的所有空间位置共享同一个偏置。

5.2 卷积核、步幅与填充

参数 符号 它控制什么?
卷积核空间大小 FH×FW 每次覆盖的局部窗口大小
步幅 S 每次窗口向右或向下移动多少格
填充 P 输入每一侧额外补多少格,本章主要补0
输出空间大小 OH×OW 高、宽方向各能放下多少个窗口

步幅越大,通常可放下的窗口越少;加入填充可以调节输出尺寸,也让边缘像素参与更多窗口。不能笼统地说卷积必然让图片变小。

图5:填充、步幅与输出尺寸

图5|左边看补零,中间看步幅,右边把“数窗口”写成公式。

5.3 输出特征图大小:先理解,再记公式

本章采用常规卷积:膨胀率为1,高宽各方向对称填充,输出尺寸向下取整。高宽参数可分别设置:

输出高: OH=⌊H+2Ph−FHSh⌋+1OH=\left\lfloor\frac{H+2P_h-FH}{S_h}\right\rfloor+1

输出宽: OW=⌊W+2Pw−FWSw⌋+1OW=\left\lfloor\frac{W+2P_w-FW}{S_w}\right\rfloor+1

其中⌊·⌋表示向下取整。若高宽的填充与步幅相同,就统一写P和S。

为什么最后加1?因为第一个窗口放好时就已经产生一个输出值;之后每移动S格,再多产生一个值。H+2P−FHH+2P-FH是窗口在高方向还能移动的总距离。

例1|填充后输出可以更大。 输入3×3,核2×2,P=1,S=1。OH=OW=3+2−21+1=4OH=OW=\frac{3+2-2}{1}+1=4,输出4×4。

例2|步幅使输出缩小。 输入4×4,核2×2,P=0,S=2。OH=OW=4−22+1=2OH=OW=\frac{4-2}{2}+1=2,输出2×2。

例3|不能整除时向下取整。 输入6×6,核3×3,P=0,S=2。OH=OW=⌊6−32⌋+1=2OH=OW=\left\lfloor\frac{6-3}{2}\right\rfloor+1=2;不是2.5,也不能四舍五入成3。

例4|保持尺寸。 输入32×32,核3×3,P=1,S=1,输出32×32。对奇数空间核且S=1,常取 P=F−12P=\frac{F-1}{2} 保持尺寸;这个经验不能直接套到任意偶数核或任意步幅。

6 多通道卷积:看懂手稿里的“立体方块”

6.1 一个完整滤波器,要跨过所有输入通道

输入不再只有一个矩阵,而是C个矩阵,形状为 C×H×WC\times H\times W。对于普通卷积,一个完整滤波器的形状为 C×FH×FWC\times FH\times FW,它在深度方向必须与输入通道数C一致。

可以把这个滤波器想成C张核切片:第1张处理输入第1通道,第2张处理输入第2通道,以此类推。它们属于同一个完整滤波器,不是C个独立的输出滤波器。

图6:滤波器跨输入通道的计算

图6|每个通道先各自乘加,再把这些结果相加,最后只加一次该输出通道的偏置。图中2、5、3是说明求和关系的示例局部和。

6.2 为什么多个输入通道只得到一张特征图?

在每一个空间位置,同一个完整滤波器都把C个通道的信息汇总成一个数。当它滑完整张图,这些数排成一张二维特征图,也就是一个输出通道。

若要输出FN张特征图,就使用FN个不同的完整滤波器。每个滤波器分别学习不同的权重,并分别生成一张特征图。因此:

输入: C×H×WC\times H\times W

权重: FN×C×FH×FWFN\times C\times FH\times FW

输出: FN×OH×OWFN\times OH\times OW

一句话记住:核的深度看输入通道C;输出通道数看滤波器个数FN。 这里讨论普通卷积;分组卷积、深度卷积有另外的通道连接规则,不属于本章基础算例。

6.3 把形状和参数量同时算一遍

输入RGB图像 3×32×323\times 32\times 32,使用6个空间大小为3×3的滤波器,S=1,P=1。

  • 每个完整滤波器的形状为 3×3×33\times 3\times 3:第一个3是通道深度,后两个3为空间高宽。
  • 每个滤波器产生 32×3232\times 32 的二维特征图。
  • 一共有6个滤波器,因此输出是 6×32×326\times 32\times 32。
  • 每个滤波器有27个权重和1个偏置,总参数量为 6×(27+1)=1686\times(27+1)=168。

普通卷积含偏置的参数量为 FN×(C×FH×FW+1)FN\times(C\times FH\times FW+1)。同一组参数在空间位置间共享,所以输出有多少个位置,并不会让权重参数数量同比增加。

7 池化层:保留局部响应,缩小空间尺寸

7.1 最大池化与平均池化

最大池化取窗口中的最大值,强调局部区域最强的响应。平均池化取窗口中所有数的算术平均值,汇总区域整体响应。两者都在每个通道上独立执行。

图7|同一份输入,四种底色对应四个窗口;同样的窗口与步幅,只因汇总方式不同,输出数值就不同。

图7:最大池化与平均池化对照

本例输入为 X=[1233011530101412]X=\begin{bmatrix}1&2&3&3\\0&1&1&5\\3&0&1&0\\1&4&1&2\end{bmatrix},采用 2×2 窗口、步幅 2、无填充。

我先看左上窗口:最大值为 2,平均值为 1。滑动全部窗口后,两种池化的结果分别为 Ymax⁡=[2542],Yavg=[1321]Y_{\max}=\begin{bmatrix}2&5\\4&2\end{bmatrix},\quad Y_{\mathrm{avg}}=\begin{bmatrix}1&3\\2&1\end{bmatrix}。平均结果可以是小数,本例恰好得到整数。

7.2 池化改变什么、不改变什么?

标准最大池化与平均池化通常缩小H/W,但不把不同输入通道相加,因此输入C个通道,输出仍为C个通道。它们没有需要训练的窗口权重。

本章常规池化采用向下取整时,空间尺寸同样按“窗口能放多少次”计算。例如 6×32×326\times 32\times 32 经过2×2、S=2、P=0池化后,输出为 6×16×166\times 16\times 16。若使用其他取整配置或填充约定,需按对应定义计算。

我把“利用空间结构”和“保留全部细节”区分开:池化可以减少后续计算,对小范围位移通常更稳健,但会丢失部分细节,也不保证完全平移不变。

7.3 卷积与池化并排记

对比点 普通卷积 标准最大/平均池化
窗口内怎么计算 对应权重乘加,再加偏置 取最大值或平均值
有无可训练参数 通常有 无
通道如何处理 同一滤波器跨通道求和 各通道独立
输出通道数 由滤波器数决定 与输入相同
空间大小 由核、步幅、填充决定 由窗口、步幅、填充及取整配置决定

8 把整张图串起来:一个小CNN的完整数据流

图8:小型CNN的完整形状变化

输入 3×32×323\times 32\times 32 → 第一次卷积(6个滤波器)得到 6×32×326\times 32\times 32 → ReLU尺寸不变 → 池化得到 6×16×166\times 16\times 16。

第二次卷积(16个滤波器)得到 16×16×1616\times 16\times 16 → ReLU → 池化得到 16×8×816\times 8\times 8 → 展平为1024维 → 全连接输出10个类别分数。

若有N张图,所有形状前面加上N。例如池化后为 N×16×8×8N\times 16\times 8\times 8,展平后为 N×1024N\times 1024。展平只合并每个样本的特征维,不能把N也混进特征数。