4. 深度学习基础回顾

各位同学,欢迎来到第四章。这一章我们得把深度学习的基础夯一夯。你可能会问:“我是做ISP的,为什么要学CNN?” 说白了,AI ISP的核心就是用神经网络替代传统的图像处理流水线。不懂CNN,后面讲AI去噪、超分、HDR融合,你根本听不懂。

我个人习惯,讲理论之前先画一张图,把本章的知识脉络理清楚。这样你学起来心里有数。

第4章 知识体系框架图 第4章:CNN与模型轻量化 CNN核心概念 激活 & 归一化 常用网络结构 卷积 / 池化 感受野 / 参数共享 ReLU / BN / LN ResNet / UNet MobileNet 模型轻量化:剪枝 / 量化 / 蒸馏 目标:在AI ISP芯片上高效部署 AI ISP 混合架构:算法 + 芯片协同设计 说明:本章从CNN基础出发,串联激活/归一化、经典网络结构,最终落到模型轻量化技术,为AI ISP芯片部署铺路。

4.1 CNN核心概念:卷积、池化、感受野

卷积神经网络,说白了就是“用卷积核在图像上滑动”。每个卷积核就是一个特征提取器。边缘、纹理、颜色,一层层往上抽象。

卷积操作:输入一张图,尺寸是 H×W×C,卷积核是 K×K×C,输出一张特征图。我刚开始做AI ISP时,经常搞混“通道数”和“卷积核个数”的关系。记住:输出通道数 = 卷积核的个数。

关键公式:输出特征图尺寸 = (输入尺寸 - 卷积核尺寸 + 2×Padding) / Stride + 1

举个例子:输入 224×224,卷积核 3×3,Stride=1,Padding=1,输出还是 224×224。这叫“保持分辨率”,在ISP任务里很常见。

池化层:最大池化、平均池化。它的作用就是降采样,减少计算量。但我在项目中踩过一个坑——在AI去噪网络里用了太多池化,结果图像细节全丢了。后来我改用Stride卷积来降采样,效果好很多。

感受野:这个概念很重要。你想想看,一个3×3的卷积核,感受野就是3×3。但堆叠两层3×3卷积,感受野就变成了5×5。为什么?因为第二层能看到第一层3×3区域的信息,而第一层每个点又覆盖了输入上的3×3区域。这就是“堆叠小卷积核替代大卷积核”的原理,参数量还更少。

我的经验:在AI ISP中,感受野决定了网络能看到多大范围的上下文。去噪任务需要大感受野,但也不能太大,否则会模糊边缘。我一般用3×3卷积堆叠4-6层,感受野大概15×15到21×21,效果比较平衡。

4.2 激活函数与归一化层

激活函数,就是给网络引入非线性。没有激活函数,堆再多层也是线性变换,那跟单层网络没区别。

激活函数 公式 优点 缺点
ReLU max(0, x) 计算快,缓解梯度消失 神经元死亡(负半轴梯度为0)
Leaky ReLU max(αx, x) 解决神经元死亡 α需要调参
PReLU max(ax, x),a可学习 自适应负斜率 参数量略增
GELU x·Φ(x) 在Transformer中表现好 计算稍复杂

我个人习惯,在CNN里首选ReLU。简单、高效、硬件友好。但在AI ISP的量化部署中,ReLU有个问题——它的输出范围是[0, +∞),量化时不好截断。我建议用ReLU6(min(max(0,x), 6)),把输出限制在0到6之间,量化精度更高。

归一化层:Batch Normalization(BN)是2015年提出的,现在几乎成了CNN的标配。它把每层输出归一化到均值为0、方差为1,再学一个缩放和平移。好处是加速训练、缓解梯度消失、还有一点正则化效果。

但BN在AI ISP芯片上有个大坑——推理时BN是线性变换,可以融合到卷积层里。我做过一个项目,芯片的NPU不支持BN单独计算,必须做“BN融合”。代码实现很简单:

# BN融合到卷积层的伪代码
conv_weight = conv_weight * (gamma / sqrt(running_var + eps))
conv_bias = (conv_bias - running_mean) * (gamma / sqrt(running_var + eps)) + beta

融合之后,推理时就不需要单独算BN了,省掉一次内存访问和计算。这在嵌入式芯片上非常关键。

我曾经踩过的坑:在训练时用了BN,但部署到芯片上时忘了做融合。结果推理结果完全不对,查了两天才发现是BN的running_mean和running_var没有冻结。记住:训练时BN是逐batch计算的,推理时必须用全局统计量。

除了BN,还有Layer Normalization(LN)和Instance Normalization(IN)。LN在RNN/Transformer里用得多,IN在图像风格迁移里常见。但在AI ISP里,BN还是主流。

4.3 常用网络结构:ResNet、UNet、MobileNet

这三个网络,是AI ISP里最常用的骨架。我一个个讲。

4.3.1 ResNet:残差连接

ResNet的核心思想就是“跳跃连接”。为什么需要它?因为网络太深了,梯度传不回去。你想想看,50层网络,梯度从最后一层传到第一层,中间连乘50次,如果每次小于1,梯度就消失了。

残差块的做法:让网络去学习“残差”F(x) = H(x) - x,而不是直接学习H(x)。这样梯度可以通过跳跃连接直接回传,不会衰减。

代码示例:一个基本的残差块

class BasicBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, 3, stride, 1)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = nn.Conv2d(out_channels, out_channels, 3, 1, 1)
        self.bn2 = nn.BatchNorm2d(out_channels)
        # 跳跃连接
        self.shortcut = nn.Sequential()
        if stride != 1 or in_channels != out_channels:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, 1, stride),
                nn.BatchNorm2d(out_channels)
            )
    def forward(self, x):
        out = self.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out += self.shortcut(x)  # 残差连接
        out = self.relu(out)
        return out

在AI ISP里,ResNet常用于特征提取。比如做图像增强时,我用ResNet-18作为编码器,效果比VGG好很多,而且训练更快。

4.3.2 UNet:编码器-解码器结构

UNet是图像分割领域的经典网络,但在AI ISP里也大放异彩。为什么?因为它的结构天然适合“图像到图像”的任务——输入一张噪声图,输出一张干净图。

UNet的结构分为两部分:

  • 编码器(下采样):逐层提取特征,分辨率降低,通道数增加。
  • 解码器(上采样):逐层恢复分辨率,通过跳跃连接融合编码器的特征。

跳跃连接是UNet的精髓。它把编码器的细节信息直接传给解码器,避免了上采样过程中的信息丢失。我在做AI去噪时,对比过有无跳跃连接的效果——有跳跃连接的PSNR高了1.5dB左右。

我的建议:在AI ISP里,UNet的深度不用太深。4层下采样+4层上采样就够了。太深了,小目标(比如噪点)的信息在下采样过程中就丢了,上采样也找不回来。

4.3.3 MobileNet:轻量级网络

MobileNet是为移动端和嵌入式设备设计的。它的核心是“深度可分离卷积”。

普通卷积:一个卷积核同时处理所有通道。深度可分离卷积:先对每个通道单独做卷积(Depthwise),再用1×1卷积融合通道(Pointwise)。

计算量对比:假设输入是 H×W×C,卷积核是 K×K,输出通道是 M:

  • 普通卷积:H×W×C×K×K×M
  • 深度可分离卷积:H×W×C×K×K + H×W×C×M

当K=3时,深度可分离卷积的计算量大约是普通卷积的1/9到1/8。这个差距在芯片上非常可观。

我在一个AI ISP芯片项目里,把骨干网络从普通卷积换成深度可分离卷积,模型大小从50MB降到了6MB,推理速度提升了5倍,而PSNR只掉了0.3dB。这个trade-off完全值得。

4.4 模型轻量化技术:剪枝、量化、蒸馏

模型做出来了,但跑不动怎么办?轻量化就是干这个的。在AI ISP芯片上,算力和内存都是有限的,必须对模型“动手术”。

4.4.1 剪枝

剪枝就是去掉不重要的连接或通道。说白了,神经网络有很多冗余参数,去掉它们对精度影响不大。

剪枝的流程:

  1. 训练一个完整的大模型。
  2. 评估每个通道或权重的重要性(比如用L1范数)。
  3. 剪掉不重要的部分。
  4. 微调(Fine-tune)恢复精度。

我常用的方法是“结构化剪枝”——直接剪掉整个卷积核或通道。这样剪完之后,模型结构还是规整的,硬件实现起来方便。非结构化剪枝(剪掉单个权重)虽然压缩率更高,但芯片上的稀疏计算单元不是每家都有,兼容性差。

我曾经犯过的错:一次性剪掉50%的通道,结果模型精度直接崩了。后来我改成“渐进式剪枝”——每次剪5%,微调一下,再剪5%。这样精度下降可控,最终剪掉了40%的通道,精度只掉了0.5%。

4.4.2 量化

量化就是把模型参数从FP32变成INT8甚至INT4。为什么能这么做?因为神经网络对噪声有一定的容忍度。

量化的方式有两种:

  • 训练后量化(PTQ):训练完模型后,直接用量化工具转换。简单,但精度损失可能较大。
  • 量化感知训练(QAT):在训练过程中模拟量化误差,让模型适应低精度。精度更高,但需要重新训练。

在AI ISP芯片上,我强烈建议用QAT。因为图像任务对精度很敏感,PTQ量化后PSNR可能掉1-2dB,而QAT只掉0.2-0.3dB。

量化关键点:

  • 校准数据集:PTQ需要几百张有代表性的图片来计算量化范围。
  • 对称量化 vs 非对称量化:ReLU激活后的值都是非负的,用非对称量化更合适。
  • per-tensor vs per-channel:per-channel量化精度更高,但硬件支持需要确认。

4.4.3 知识蒸馏

蒸馏就是“大模型教小模型”。大模型(Teacher)知识丰富,小模型(Student)学它的输出分布,而不是直接学硬标签。

蒸馏的损失函数通常包含两部分:

  1. 硬标签损失:Student的输出与真实标签的交叉熵。
  2. 软标签损失:Student的输出与Teacher的输出(经过温度系数软化)的KL散度。

我在一个AI ISP项目里,用ResNet-50作为Teacher,MobileNet作为Student。蒸馏之后,MobileNet的精度从原来的92.3%提升到了94.1%,接近ResNet-50的95.2%。而MobileNet的推理速度是ResNet-50的8倍。

我的经验:蒸馏的温度系数T很关键。T越大,软标签越平滑,小模型学到的知识越丰富。我一般从T=4开始试,然后根据验证集精度调整。

4.5 本章小结

这一章内容不少,但都是后面AI ISP实战的基础。我帮你梳理一下重点:

  • CNN核心:卷积、池化、感受野——理解特征提取的底层逻辑。
  • 激活与归一化:ReLU+BN是黄金组合,但部署时别忘了做BN融合。
  • 网络结构:ResNet解决梯度消失,UNet适合图像到图像,MobileNet用深度可分离卷积降低计算量。
  • 轻量化:剪枝、量化、蒸馏三件套,是模型上芯片的必经之路。