1. 卷积神经网络的基础概念
卷积神经网络(CNN)是计算机视觉领域的基石技术,理解它的核心组件对算法工程师至关重要。我第一次接触CNN时,被各种卷积操作搞得晕头转向,直到在实际项目中踩过几次坑后才真正明白它们的区别。让我们从最基础的普通卷积开始,逐步拆解这个"黑盒子"。
普通卷积就像用放大镜扫描图片的每个角落。假设输入是张224x224的RGB图片,卷积核大小为3x3,那么每个核会产生一个特征图。计算量公式很简单:输出特征图尺寸 × 卷积核面积 × 输入通道数 × 输出通道数。比如输出112x112的特征图,计算量就是112×112×3×3×3×64 ≈ 2.2亿次乘法。
这里有个容易混淆的点:很多人以为卷积核大小决定计算量,其实输出尺寸影响更大。我在面试候选人时发现,80%的人会忽略输出尺寸对计算量的指数级影响。举个例子,把步长从1改成2,计算量直接减少75%,这比换小卷积核效果明显得多。
2. 分组卷积的进化之路
当网络越来越深时,普通卷积的计算量成了瓶颈。这时分组卷积(Group Convolution)就像救星一样出现了。我第一次用ResNeXt时,发现同样的精度下,分组卷积能让计算量减少近半,当时真是眼前一亮。
分组卷积的精髓在于"分而治之"。把输入通道分成g组,每组独立卷积后再拼接。计算量公式变为:(输出尺寸 × 核面积 × 输入通道/g × 输出通道/g) × g。当g=输入通道数时,就是著名的深度可分离卷积了。
实际应用中我发现个有趣现象:分组数不是越大越好。在移动端部署时,g=8通常是最佳平衡点。有次我把g调到32,虽然计算量降了,但GPU利用率反而下降,因为并行度太高导致调度开销增大。这个经验后来成了我面试必问的实战题。
3. 深度可分离卷积的魔法
深度可分离卷积(Depthwise Separable Convolution)是分组卷积的极致形态,也是MobileNet的核心。它把标准卷积拆成两步:先逐通道空间卷积(Depthwise),再1x1跨通道组合(Pointwise)。
计算量对比很惊人:标准卷积需要Dk×Dk×M×N×Df×Df,而深度可分离只要Dk×Dk×M×Df×Df + M×N×Df×Df。以3x3卷积、输入输出256通道为例,计算量从约500万降到不到30万,节省了94%!
但这里有个坑我踩过:在低端设备上,深度卷积的访存开销可能抵消计算优势。有次在嵌入式设备部署时,改用分组卷积反而比深度卷积快20%。后来用NSight分析才发现,是内存访问模式不适合该芯片架构。
4. 池化层的精妙设计
池化层常被当作简单配角,但其实设计不当会毁掉整个网络。最大池化保留纹理特征,平均池化适合平滑区域。我在做医疗影像时,用混合池化(前几层最大池化,深层用平均池化)让模型精度提升了1.2%。
池化特征图尺寸公式很简单:(W-F+2P)/S +1。但实际使用时要注意:当结果不是整数时,不同框架处理方式不同。PyTorch默认向下取整,TensorFlow可以选padding方式。有次模型迁移时因为这个差异导致特征图对不齐,debug了一整天。
最近流行的替换方案是步长卷积。我在对比测试中发现,对于小模型用步长卷积更好,大模型还是池化更稳定。这个经验后来写进了我们团队的模型设计规范里。
5. 高效网络设计实战技巧
结合这些技术设计高效网络时,我有几个压箱底的技巧。第一是瓶颈结构:用1x1卷积先降维再升维,像Inception模块那样。实测在ResNet50上能省30%计算量,精度只降0.3%。
第二是结构重参数化。训练时用复杂分支,部署时合并成单路径。有次比赛我用这个技巧,在保持精度的同时让推理速度提升2倍,拿了冠军。具体做法是在3x3卷积旁并联1x1和identity分支,训练完把它们等效融合。
最后是硬件感知设计。同样FLOPs,不同操作在芯片上耗时可能差10倍。比如在NPU上,深度卷积要特别处理才能跑满算力。我们自研的芯片专用编译器就是专门优化这类操作的。