3、神经网络基础:卷积神经网络(CNN)核心概念
各位同学,欢迎来到第三章。前面我们聊了RAW域的基础,现在要进入神经网络的世界了。说实话,我第一次接触CNN时也觉得概念挺多,但别担心,咱们一个一个拆开看。
卷积神经网络,说白了就是专门为处理网格状数据(比如图像)设计的网络结构。它不像全连接网络那样把每个像素都拉成一维向量,而是保留了空间结构信息。这一点在图像处理里太重要了。
核心思想:CNN通过局部连接、权值共享和池化操作,大幅减少了参数量,同时提取出有层次的特征——从边缘到纹理,再到物体部件。
3.1 卷积层(Convolutional Layer)
卷积层是CNN的“眼睛”。它用一组可学习的卷积核(也叫滤波器)在输入图像上滑动,计算点积,生成特征图。
我习惯把卷积核想象成“特征探测器”。比如一个3×3的核,可能专门检测垂直边缘;另一个核可能检测纹理。每个核在整张图上共享权重——这就是权值共享,参数量一下就降下来了。
关键参数:
- 卷积核大小(Kernel Size):常见3×3、5×5、7×7。小核堆叠比大核更高效,参数量少,非线性更强。
- 步长(Stride):每次滑动的像素数。步长=2时,输出尺寸减半。
- 填充(Padding):在输入边缘补零,控制输出尺寸。'same'填充保持尺寸不变,'valid'填充则缩小。
- 输入输出通道数:输入通道数=上一层输出通道数;输出通道数=本层卷积核个数。
我的经验:在RAW域处理中,我常用3×3卷积核堆叠3-4层,感受野相当于7×7,但参数量更少,训练也更稳定。步长一般用1,下采样交给池化层或步长2的卷积。
输出特征图尺寸计算公式:
输出尺寸 = (输入尺寸 - 卷积核大小 + 2 × 填充) / 步长 + 1
举个例子:输入224×224,卷积核3×3,步长1,填充1,输出还是224×224。如果步长2,输出就是112×112。
3.2 池化层(Pooling Layer)
池化层的作用是下采样,降低特征图的空间维度,同时保留主要特征。它没有可学习的参数,只是做统计操作。
常见池化方式:
| 类型 | 操作 | 特点 | 适用场景 |
|---|---|---|---|
| 最大池化(Max Pooling) | 取窗口内最大值 | 保留最显著特征,对纹理敏感 | 分类任务,特征提取 |
| 平均池化(Average Pooling) | 取窗口内平均值 | 保留整体信息,更平滑 | 全局特征聚合,减少过拟合 |
| 全局平均池化(GAP) | 对整个特征图取平均 | 替代全连接层,参数量为0 | 分类网络尾部 |
池化核大小通常2×2,步长2,这样特征图尺寸减半。我见过有人用3×3池化,但效果一般,信息丢失太多。
避坑指南:我曾经在RAW域降噪任务中,在浅层用了池化层,结果丢失了高频细节,噪声反而更明显。后来我改用步长2的卷积做下采样,保留了更多信息。所以,在低层特征提取阶段,慎用池化。
3.3 全连接层(Fully Connected Layer)
全连接层把前面提取到的特征“展平”并映射到输出空间。每个神经元与上一层的所有神经元相连,所以参数量巨大。
在CNN中,全连接层通常放在网络尾部,用于分类或回归。比如最后输出10个神经元对应10个类别,通过softmax得到概率分布。
但全连接层的参数量太吓人了。举个例子:输入特征图7×7×512,展平后是25088个神经元,如果全连接层有4096个神经元,那这一层的参数量就是25088×4096≈1亿!
所以现在很多网络用全局平均池化(GAP)替代全连接层。GAP把每个通道的特征图取平均,得到一个向量,再直接接分类层。参数量几乎为0,还能防止过拟合。
我的建议:在RAW域处理中,如果网络不大,可以用1-2层全连接层做特征融合;如果网络很深,优先用GAP。我在做RAW域去马赛克时,用GAP替换全连接层后,参数量减少了80%,效果反而更好。
3.4 激活函数(Activation Function)
激活函数给网络引入非线性。没有它,再多层也只是线性变换,表达能力有限。
常用激活函数对比:
| 函数 | 公式 | 优点 | 缺点 |
|---|---|---|---|
| Sigmoid | σ(x)=1/(1+e-x) | 输出在(0,1),适合概率 | 梯度饱和,容易梯度消失;输出非零均值 |
| Tanh | tanh(x)=(ex-e-x)/(ex+e-x) | 输出零均值,比Sigmoid好 | 仍有梯度饱和问题 |
| ReLU | f(x)=max(0,x) | 计算快,缓解梯度消失 | 神经元死亡(负半轴梯度为0) |
| Leaky ReLU | f(x)=max(αx,x),α小正数 | 解决神经元死亡 | α需要调参 |
| ELU | f(x)=x if x>0 else α(ex-1) | 负半轴平滑,抗噪声 | 计算稍复杂 |
我个人最常用ReLU,简单高效。但在RAW域处理中,我遇到过ReLU导致神经元大量死亡的情况——因为RAW数据是线性值,负值很少,但经过卷积后可能出现负响应,ReLU一刀切掉,信息就丢了。后来我换成Leaky ReLU或PReLU,效果明显改善。
小技巧:在RAW域网络的浅层,建议用Leaky ReLU或ELU;深层可以用ReLU。这样既保留信息,又保持计算效率。
3.5 损失函数(Loss Function)
损失函数衡量模型预测与真实值的差距,是网络优化的目标。不同任务用不同损失函数。
常见损失函数:
- 均方误差(MSE):L = (y_pred - y_true)²。适合回归任务,对异常值敏感。
- 平均误差(MAE):L = |y_pred - y_true|。对异常值更鲁棒,但梯度恒定。
- 交叉熵损失(Cross-Entropy):L = -Σ y_true·log(y_pred)。分类任务标配,配合softmax使用。
- Huber损失:误差小时用MSE,误差大时用MAE。结合两者优点。
在RAW域处理中,我常用L1损失(MAE)做降噪和去马赛克。为什么?因为L2损失(MSE)会过度惩罚大误差,导致结果过于平滑,丢失纹理。L1损失保留边缘更好。
实战经验:我在做RAW域去噪时,对比过L1和L2损失。L2的PSNR高,但视觉上模糊;L1的PSNR略低,但纹理清晰。后来我用L1+感知损失(Perceptual Loss),效果最好。所以,别只看指标,要看视觉质量。
3.6 本章知识体系
下面这张图总结了CNN的核心组件和它们的关系:
这张图展示了CNN的标准流程:输入→卷积→激活→池化→重复→全连接→输出。每个模块都有它的作用,缺一不可。
3.7 小结
这一章我们覆盖了CNN的五大核心组件:
- 卷积层——特征提取的主力,局部连接+权值共享
- 池化层——下采样,降低维度,保留主要特征
- 全连接层——特征映射到输出,参数量大,可用GAP替代
- 激活函数——引入非线性,ReLU最常用,RAW域推荐Leaky ReLU
- 损失函数——优化目标,回归用L1/L2,分类用交叉熵