1. 从一张“认猫”的图说起:图像分类到底在解决什么问题
图像分类这四个字,听起来像是教科书里的章节名,但如果你真正动手做过一个能跑起来的分类器,就会明白它远不止“给图片贴标签”这么简单。我最早接触这个方向,是从一个很朴素的需求开始的:手头有一批照片,想按内容自动分到不同文件夹里。人眼扫一遍很快,但量一大就顶不住,于是自然想到让机器来做。这就是图像分类最原始、也最核心的诉求——给定一张输入图像,输出它属于哪个预定义类别。
从技术定义上讲,图像分类是计算机视觉里最基础的任务之一。它的输入是一张图像(通常是固定尺寸的张量),输出是一个类别标签,或者更准确地说,是每个类别的概率分布。比如一张 224×224×3 的彩色图,经过网络前向计算,最后得到一个长度为 N 的向量,N 是类别总数,向量里每个值代表“这张图属于该类”的置信度,取最大值对应的类别就是预测结果。听起来简单,但真正难的地方在于:同一个物体,换个角度、换个光照、被遮挡一部分、背景杂乱,像素值可能天差地别,而人脑能轻松认出“这还是那只猫”,机器要做到这一点,需要从海量数据里学到一种对无关变化“不敏感”、对类别差异“敏感”的特征表达。
这也是为什么图像分类长期被当作计算机视觉的“试金石”。很多后来很火的任务,比如目标检测、语义分割、图像检索、甚至多模态理解,底层都依赖一个足够强的分类骨干网络。你可以把分类网络理解成一个“视觉特征提取器”,它先把图像压缩成高维语义向量,后面的任务再在这个向量上做文章。所以搞懂图像分类,不只是学会一个任务,而是拿到了进入整个视觉领域的钥匙。
这篇文章适合谁看?如果你刚入门计算机视觉,想搞清楚图像分类的来龙去脉、主流方法和实操细节,那这篇综述会帮你把脉络理清;如果你已经用过一些预训练模型,但对其中的设计取舍、训练技巧、评估陷阱还比较模糊,那这篇也会补上那些“文档里不写、但实际会踩”的经验。我会尽量用从业者的视角,把原理、选型、实操和避坑串成一条线,而不是堆一堆名词。
2. 图像分类的技术演进:从手工特征到深度表征
2.1 早期手工特征时代:为什么那时候效果上不去
在深度学习大规模应用之前,图像分类主要靠手工设计的特征加浅层分类器。典型流程是:先做预处理(灰度化、去噪、归一化),再提取特征,比如颜色直方图、纹理特征(如 LBP)、边缘特征(如 HOG、SIFT),最后把特征向量喂给 SVM 或随机森林做分类。这套流程在特定场景下能work,比如数字识别、简单物体区分,但泛化能力很有限。
问题出在“手工”两个字上。人设计特征时,脑子里已经预设了“什么信息重要”,比如边缘、角点、颜色分布。但真实图像的类内差异极大,一只猫可以是趴着、站着、侧脸、逆光,手工特征很难覆盖所有变化。更关键的是,特征设计和分类器训练是分离的,特征一旦定死,分类器再强也救不回来。我早期做过一个实验,用 HOG+SVM 区分几种相似物体,训练集准确率能到 90% 以上,但换一批不同背景的测试图,直接掉到 60% 多,这就是泛化鸿沟。
2.2 深度学习的转折点:卷积网络为什么有效
真正的转折发生在卷积神经网络(CNN)被大规模训练之后。CNN 的核心思想其实很符合直觉:图像有很强的局部相关性,相邻像素组成边缘,边缘组成纹理,纹理组成部件,部件组成物体。卷积操作就是用一个滑动窗口(卷积核)在图像上扫,提取局部模式,再通过堆叠多层,让网络自动从低级特征(边缘、颜色)组合出高级语义(眼睛、轮子、猫脸)。
和手工特征相比,CNN 最大的优势是“端到端学习”。特征提取和分类器不再分离,整个网络一起优化,损失函数直接告诉网络“你哪里错了”,反向传播自动调整每一层的卷积核。换句话说,网络自己决定该学什么特征,而不是人来指定。这也是为什么 CNN 在 ImageNet 这类大规模数据集上能大幅超越传统方法。
这里有个容易被忽略的点:CNN 的“平移不变性”并不是天然就有的,而是靠卷积的权重共享和池化操作逐步获得的。卷积核在整张图上共享参数,意味着同一个模式出现在不同位置,都会被同一个核检测到;池化则进一步压缩空间分辨率,让网络对小幅位移不敏感。但要注意,这种不变性是有限的,物体大幅旋转或尺度变化,CNN 仍然会吃力,这也是后来数据增强和更复杂结构要解决的问题。
2.3 经典网络结构回顾:它们各自解决了什么痛点
回顾几个里程碑式的网络,能帮我们理解设计动机。AlexNet 在 2012 年证明了深度 CNN 在大规模分类上的威力,它用了 ReLU 加速训练、Dropout 抑制过拟合、数据增强扩充样本,这些技巧至今仍在用。VGG 则把“深度”推到极致,用连续的小卷积核(3×3)堆叠,证明增加深度能提升性能,但参数量巨大,计算成本高。
GoogLeNet(Inception 系列)换了个思路:与其一味加深,不如让网络“变宽”,在同一层用不同尺寸的卷积核并行提取多尺度特征,再用 1×1 卷积降维,控制计算量。ResNet 则解决了更深网络难训练的问题,引入残差连接,让梯度能跨层直接回传,训练上百层甚至上千层成为可能。可以说,ResNet 之后,分类网络的骨干基本定型,后续很多改进都是在残差结构上做微调。
这些结构背后的共同逻辑是:在“表达能力”和“训练可行性”之间找平衡。更深更宽的网络表达能力强,但容易过拟合、梯度消失、计算爆炸;残差、Inception、批归一化等技术,都是在让深网络变得可训练、可收敛。
3. 训练一个分类器:数据、模型、损失与优化
3.1 数据准备:分类任务里最容易被低估的环节
很多人一上来就调模型,结果发现效果不好,回头一看,数据问题一大堆。图像分类的数据准备,至少包括这几件事:类别定义、样本采集、清洗、划分、增强。类别定义要清晰互斥,别出现“猫”和“宠物”这种重叠类别,否则网络会困惑。样本采集要尽量覆盖真实场景的变化,光照、角度、背景、遮挡都要有,否则模型只在“干净”数据上好看。
数据清洗是苦活但必须做。我见过标注错误的样本,把狗标成猫,网络学得再好也会被带偏。划分训练集、验证集、测试集时,要保证分布一致,不能训练集全是白天图,测试集全是夜景。更隐蔽的坑是“数据泄漏”:同一张图或高度相似的图同时出现在训练和测试里,导致测试准确率虚高。实操中可以用感知哈希或特征相似度去重,避免这种问题。
数据增强是分类任务里性价比最高的技巧之一。随机裁剪、翻转、旋转、颜色抖动、Mixup、CutMix 等方法,能在不增加标注成本的前提下,显著提升泛化能力。但增强策略要和任务匹配,比如识别数字时,过度旋转可能把“6”变成“9”,反而有害。
3.2 损失函数与优化器:为什么交叉熵是默认选择
分类任务最常用的损失是交叉熵。它衡量的是预测概率分布和真实标签分布之间的差异。真实标签通常是 one-hot 向量,交叉熵会推动正确类别的概率趋近于 1,错误类别趋近于 0。相比均方误差,交叉熵在分类任务上梯度更稳定,收敛更快,尤其是配合 Softmax 使用时,梯度形式简洁,不容易饱和。
优化器方面,SGD 加动量是经典组合,泛化性能往往不错,但需要调学习率、动量、权重衰减。Adam 系列自适应优化器收敛快,适合快速实验,但在某些分类任务上泛化略逊于精调后的 SGD。我的经验是:如果追求最终精度且有时间调参,用 SGD+动量;如果快速验证想法,用 Adam 起步。学习率调度也很关键,余弦退火、阶梯下降、warmup 都能影响最终效果。
3.3 评价指标:准确率之外你还应该看什么
准确率是最直观的指标,但在类别不平衡时会有误导。比如 95% 的样本是 A 类,模型全预测 A,准确率也有 95%,但完全没用。这时候要看每类精确率、召回率、F1 值,以及混淆矩阵,搞清楚模型到底在哪些类别上犯错。Top-5 准确率在多类别任务里也常用,它允许模型在前 5 个预测里命中正确类别,更贴近实际使用场景。
还有一个容易被忽视的指标是推理速度。分类模型最终要落地,如果单张图推理要几百毫秒,很多实时场景就用不了。所以评估时要把参数量、FLOPs、实际延迟一起看,不能只盯准确率。
4. 实战中的关键取舍:从模型选型到部署落地
4.1 骨干网络怎么选:精度、速度、资源的三角权衡
选骨干网络,本质上是在精度、速度、内存之间做权衡。如果算力充足、追求极致精度,可以选深层的 ResNet、EfficientNet 或 ConvNeXt 系列;如果要在移动端或边缘设备跑,就要考虑 MobileNet、ShuffleNet 这类轻量网络。我一般会先明确部署环境:是服务器 GPU、还是手机、还是嵌入式芯片?再根据延迟预算反推可接受的模型规模。
另一个实用策略是“预训练+微调”。大多数分类任务的数据量远不如 ImageNet,从零训练很容易过拟合。用在大规模数据上预训练好的权重做初始化,再在自己的数据上微调,往往能用很少的数据达到不错的效果。微调时,底层特征(边缘、纹理)通常通用,可以冻结或小学习率更新;高层特征和分类头跟任务强相关,需要较大学习率。
4.2 迁移学习与微调:小数据集怎么做出可用效果
小数据集做分类,核心思路是“借力”。除了用预训练权重,还可以做这几件事:一是强数据增强,把有限样本“变多”;二是冻结大部分层,只训练最后几层,减少可学习参数;三是用更小的学习率,避免破坏预训练学到的通用特征;四是做交叉验证,充分利用每一份数据。
我做过一个只有几百张图的小任务,直接训练准确率只有 60% 左右,换成预训练模型+冻结底层+适度增强后,验证集到了 85% 以上。这里的关键是别一上来就全网络微调,那样很容易把预训练的好特征“冲掉”。先用小学习率训分类头,再逐步解冻高层,是比较稳的流程。
4.3 部署时的现实问题:量化、剪枝与推理加速
模型训练完只是第一步,部署时还要考虑体积和速度。量化是把浮点权重和激活转成低比特表示(如 int8),能大幅减小模型体积、提升推理速度,但可能带来精度损失,需要校准。剪枝是去掉不重要的连接或通道,减少计算量。知识蒸馏则是用大模型教小模型,让小模型学到接近大模型的表达能力。
这些技术不是必须全上,要看场景。如果只是服务器端批量处理,可能不需要极致优化;如果是手机端实时分类,量化和轻量骨干就很重要。实操中建议先测基线延迟,再逐步加优化,每步都验证精度变化,别一次性堆太多技术导致问题难定位。
5. 那些文档不写但实际会踩的坑
5.1 过拟合的隐蔽信号:训练集太好也可能是坏事
过拟合最明显的信号是训练准确率远高于验证准确率,但有时候它更隐蔽。比如训练和验证都很好,但测试集一塌糊涂,这可能是验证集和测试集分布不一致,或者数据泄漏。还有一种情况是训练准确率一直上不去,看起来像欠拟合,但其实是标签噪声太大,网络在拟合错误标签。判断过拟合不能只看一条曲线,要结合数据质量、划分方式、增强策略一起看。
5.2 类别不平衡与长尾分布:别让多数类主导训练
真实数据往往长尾,少数类样本很少。如果直接用交叉熵,多数类会主导梯度,少数类学不好。常见对策有:重采样(过采样少数类或欠采样多数类)、类别加权损失、Focal Loss 等。重采样简单但可能过拟合少数类;类别加权更温和,但权重需要调。我的经验是先用类别加权,再配合适度的数据增强,通常比单纯重采样稳。
5.3 评估陷阱:测试集泄漏与指标误读
测试集泄漏是分类任务里最致命的错误之一。如果测试图片以任何形式参与训练(包括用于选超参、做增强策略选择),最终指标就不可信。另一个陷阱是只看总体准确率,忽略关键类别的表现。比如医疗影像分类,漏诊的代价远大于误诊,这时候召回率比准确率更重要。评估指标要跟业务目标对齐,不能机械套用。
6. 我个人的几条实操心得
第一,别急着上复杂模型。很多分类问题,用预训练 ResNet 加简单增强就能解决,先把基线跑通,再考虑优化。第二,数据质量比模型结构重要。花时间清洗、平衡、增强数据,收益往往比换网络大。第三,训练日志要记全。学习率、损失、准确率、每类指标都记下来,出问题时才能回溯。第四,验证集要固定。频繁换验证集会让模型选择失去意义。第五,部署前一定测真实数据。实验室指标再好,换到实际场景可能完全不一样,早测早发现问题。
图像分类这个方向,入门容易,做好难。它不像一些新任务那样花哨,但它是很多视觉系统的地基。把地基打牢,后面做检测、分割、检索都会顺很多。如果你正在做分类项目,不妨从数据、模型、评估三条线同时推进,别只盯着准确率一个数字。真正能落地的分类器,是精度、速度、鲁棒性都过得去的那个,而不是排行榜上最高的那个。