
1. 从二分类到多分类为什么这不是简单的“多来几次”很多人学神经网络走到图像分类这一步脑子里第一个蹦出来的场景往往是“猫和狗”——一个典型的二分类问题。输出层放一个神经元接Sigmoid大于0.5判为猫小于0.5判为狗干净利落。但现实中的图像分类任务几乎不会给你只有两个类别的奢侈条件。手写数字识别有10个类别CIFAR-10有10类ImageNet有1000类细粒度分类动辄上万类。这时候如果你还想着“我训练10个二分类器不就行了”那就掉进了一个经典的思维陷阱。我先说结论多分类不是把二分类重复多次而是输出层结构、损失函数、标签编码方式三个层面同时发生变化的一套完整方案。这三个层面必须协同改动缺一个都会导致训练不收敛或者精度惨不忍睹。先讲一个我早期踩过的坑。当时做一个花卉分类的小项目5个类别。我图省事用了5个独立的二分类器每个负责判断“是不是某一类”。训练完发现两个致命问题第一推理时一张图可能同时被多个分类器判为“是”也可能一个都不判输出结果根本没法用第二每个分类器只看到了正样本和负样本的二元信息类别之间的相对关系完全丢失了。比如月季和玫瑰长得很像二分类器各自独立学习根本没法利用“这两个类容易混”这种有价值的结构信息。正确的做法是让网络在同一个输出向量上做决策。假设有C个类别输出层就放C个神经元每个神经元对应一个类别的“得分”。但这里有个关键问题得分本身只是实数可能是3.2也可能是-1.7怎么把它变成概率怎么让概率之间互相制约这就引出了多分类的核心机制——Softmax函数。它的作用不是简单地把每个得分独立映射到0到1而是做一个全局归一化所有类别的概率加起来必须等于1。这意味着一个类别概率上升其他类别必然下降。这种“竞争关系”才是多分类和二分类最本质的区别。二分类里猫的概率是0.8狗的概率就是0.2天然互斥多分类里你必须显式地构造这种互斥。再往深一层想为什么不用Sigmoid逐个处理因为Sigmoid对每个输出独立作用得到的值不满足“和为1”的约束。你可能会说那我手动归一化不就行了可以但手动归一化在反向传播时的梯度行为和Softmax不一样。Softmax的导数形式非常优雅对于正确类别梯度是(预测概率-1)对于错误类别梯度就是预测概率本身。这个形式让梯度计算极其简洁也解释了为什么Softmax和交叉熵损失搭配在一起时梯度会变得特别干净——这个后面讲损失函数时我会展开。所以这一章你要记住的核心认知是多分类的本质是在一个共享的特征表示之上通过Softmax构造类别间的竞争关系让网络学会“相对判断”而不是“绝对判断”。这个认知会贯穿后面所有章节包括数据准备、模型设计、训练调参和结果分析。2. 标签的表示方式从整数到One-Hot的完整链路搞清楚了输出层的结构接下来必须解决一个看似简单但极其容易出错的问题标签怎么表示在二分类里标签就是一个0或1的标量网络输出一个值直接做差算损失。但多分类里标签是一个类别索引比如“3”代表第3类。问题来了你能直接拿这个整数3去和网络的输出向量做运算吗显然不能。网络输出的是一个长度为C的向量标签也必须变成同样长度的向量才能逐元素计算损失。这就引出了One-Hot编码。假设有5个类别标签“3”会被编码成[0, 0, 0, 1, 0]。这个向量的长度等于类别数正确类别的位置是1其余是0。看起来很简单但这里有几个实操中必须注意的细节。第一个细节类别索引从0开始还是从1开始。这个看似无关紧要的问题在实际项目中坑过无数人。Python的列表索引从0开始但很多数据集尤其是从MATLAB时代遗留下来的标签从1开始。如果你用PyTorch的CrossEntropyLoss它期望的标签是0到C-1的整数内部会自动做One-Hot展开。但如果你手动做One-Hot然后送进BCELoss或者自己写的损失函数索引错一位就是灾难性的——网络会把所有样本都学成错误的类别而且损失曲线看起来可能还挺正常因为它在稳定地优化一个错误的目标。第二个细节标签平滑Label Smoothing。标准的One-Hot是“硬标签”正确类别是1其他是0。但硬标签有一个问题它鼓励网络把正确类别的logit推向无穷大因为只有这样才能让Softmax输出无限接近1。这会导致模型过度自信泛化能力下降。标签平滑的做法是把1变成0.9把0变成0.1/(C-1)让目标分布不那么极端。这个技巧在ImageNet级别的任务上几乎是标配但在小数据集上要谨慎使用因为小数据集本身就不容易过拟合平滑可能反而欠拟合。第三个细节类别不均衡时的标签处理。假设你有10个类别但第3类占了80%的样本。这时候如果直接用One-Hot网络会倾向于把所有样本都预测成第3类因为这样损失最小。解决方案有两种一种是在损失函数里给每个类别加权权重和类别频率成反比另一种是在采样时做重采样让每个batch里各类别比例均衡。我个人的经验是中等程度的不均衡最大类不超过最小类的10倍用类别权重就够了极端不均衡超过100倍必须配合重采样否则模型根本学不到少数类的特征。还有一个容易被忽略的点推理阶段的标签处理。训练时我们用One-Hot算损失但推理时我们只需要argmax拿到预测类别索引。这里要注意argmax返回的是索引如果你在训练时把标签做了偏移比如从1开始推理时也要做相应的逆偏移。我见过一个项目训练时标签是0-4推理时忘了这个约定结果所有预测都偏了一位排查了半天才发现是标签编码的问题。下面这张表总结了多分类中标签处理的关键决策点决策点常见做法注意事项标签起始索引0PyTorch/TF默认与框架API对齐避免手动偏移编码方式One-Hot或整数索引整数索引配合CrossEntropyLoss更高效是否平滑大数据集用小数据集慎用平滑系数通常取0.1类别不均衡类别权重或重采样极端不均衡必须重采样推理输出argmax取索引注意与训练时的索引约定一致3. 交叉熵损失多分类任务的方向盘输出层有了Softmax标签有了One-Hot接下来最关键的一环就是损失函数。多分类任务几乎无一例外地使用交叉熵损失Cross-Entropy Loss。但很多人只是知道“分类用交叉熵”却说不清楚它为什么比MSE均方误差好也不知道它在反向传播时到底发生了什么。这一章我把交叉熵拆开讲透。先看交叉熵的数学形式。对于单个样本假设真实标签是One-Hot向量 $y$网络预测概率是 $\hat{y}$交叉熵定义为$$L -\sum_{i1}^{C} y_i \log(\hat{y}_i)$$因为 $y$ 是One-Hot只有正确类别的位置是1其余是0所以这个求和实际上只剩一项$$L -\log(\hat{y}_{\text{correct}})$$也就是说交叉熵损失只关心正确类别的预测概率。正确类别概率越接近1损失越接近0越接近0损失越大而且是大到无穷大。这个性质非常关键它给网络一个极其强烈的信号去提升正确类别的概率。那为什么不用MSEMSE的形式是 $\sum (y_i - \hat{y}_i)^2$。问题在于当预测概率接近0或1时MSE的梯度会变得非常小因为平方函数的导数在极值点附近趋近于0。这意味着网络在“错得离谱”的时候反而学得很慢。而交叉熵的梯度在预测概率接近0时是 $1/\hat{y}$会变得非常大网络会被狠狠地“推一把”。这个差异在实操中非常明显用MSE训练多分类收敛速度可能慢好几倍而且容易卡在局部极小值。再来看交叉熵配合Softmax的梯度。这是整个多分类训练中最优雅的部分。设Softmax之前的logit为 $z$Softmax输出为 $\hat{y}$交叉熵损失为 $L$。经过推导这里不展开完整链式法则只给结论对于每个logit $z_i$梯度是$$\frac{\partial L}{\partial z_i} \hat{y}_i - y_i$$这个形式太漂亮了。对于正确类别$y_i1$梯度是 $\hat{y}_i - 1$是个负数梯度下降会增大这个logit对于错误类别$y_i0$梯度是 $\hat{y}_i$是个正数梯度下降会减小这个logit。而且梯度的幅度直接和预测误差挂钩预测越离谱梯度越大。这就是为什么Softmax交叉熵成为多分类的黄金组合——梯度形式简洁、数值稳定、收敛快。实操中有一个必须注意的坑数值稳定性。Softmax涉及指数运算如果logit很大比如100$e^{100}$ 会溢出如果logit很小比如-100$e^{-100}$ 会下溢到0导致除零错误。解决方案是Log-Sum-Exp技巧在计算Softmax之前先减去logit中的最大值。这个操作不改变Softmax的输出因为分子分母同乘一个常数但能保证指数运算的输入不超过0彻底避免溢出。PyTorch的CrossEntropyLoss内部已经做了这个优化所以直接用它就行。但如果你自己手写Softmax和交叉熵一定要记得加这个保护。还有一个进阶话题Focal Loss。这是交叉熵的一个变体专门解决类别不均衡问题。它的核心思想是给容易分类的样本降权让网络聚焦在难分类的样本上。公式是在交叉熵前面乘一个 $(1-\hat{y})^\gamma$ 的调制因子$\gamma$ 通常取2。当预测概率接近1时调制因子接近0损失被大幅降低当预测概率接近0时调制因子接近1损失基本不变。这个技巧在目标检测里非常流行但在普通图像分类中如果类别不均衡不严重用普通的类别加权交叉熵就够了Focal Loss反而可能引入额外的超参数调优负担。4. 从LeNet到ResNet多分类网络结构的关键设计输出层和损失函数确定之后剩下的问题就是用什么网络来提取特征。多分类任务的网络结构设计和二分类没有本质区别但有几个关键点需要特别注意这些点直接决定了模型能不能学到有判别力的特征。先回顾一下最经典的LeNet-5。这个1998年提出的网络结构极其简单两个卷积层、两个池化层、三个全连接层最后输出10维对应MNIST的10个数字。但就是这么一个简单的结构奠定了CNN做图像分类的基本范式卷积提取局部特征池化降低空间维度全连接做最终决策。LeNet的输出层就是10个神经元接Softmax这个设计至今没有变过。但LeNet有一个明显的局限它太浅了。两个卷积层的感受野有限只能捕捉非常局部的纹理和边缘。对于复杂图像比如CIFAR-10里的飞机、汽车需要更深的网络来捕捉更大范围、更抽象的特征。于是有了VGG、GoogLeNet、ResNet这一系列演进。这里我不打算逐个介绍网络结构而是聚焦一个在多分类任务中极其关键的问题全连接层的设计和全局平均池化的取舍。传统的做法LeNet、AlexNet、VGG是在卷积层之后接一个或多个全连接层最后再接输出层。全连接层的作用是把卷积提取的二维特征图展平成一维向量然后做非线性组合。但全连接层有一个致命问题参数量巨大。假设最后一个卷积层的输出是 $7 \times 7 \times 512$展平后是25088维如果接一个4096维的全连接层参数量就是25088×4096≈1亿。这1亿参数不仅占内存还极易过拟合。ResNet引入了一个优雅的替代方案全局平均池化Global Average Pooling, GAP。做法很简单对每个特征图求全局平均值把 $7 \times 7 \times 512$ 变成 $1 \times 1 \times 512$然后直接接输出层。这样参数量从1亿降到几乎为零而且每个特征图对应一个类别可解释性更强。GAP现在几乎是所有现代分类网络的标准配置。但GAP也不是万能的。如果你的数据集很小GAP可能欠拟合因为它没有足够的参数来拟合复杂的决策边界。这时候可以在GAP之前加一个 $1 \times 1$ 卷积做通道降维或者用一个小型的全连接层比如512维做过渡。我个人的经验是数据量大于5万张时直接用GAP小于1万张时用GAP小全连接层介于两者之间看具体任务复杂度。另一个关键设计点是输出层的维度。这个看似显然——有多少类就放多少个神经元。但有一个容易忽略的细节输出层不要加激活函数。很多人习惯性地在最后一层加ReLU或Sigmoid这是错误的。输出层应该输出原始的logit让Softmax和交叉熵在损失函数内部处理。如果在输出层加了ReLU所有负的logit会被截断为0Softmax的输入分布被破坏梯度也会出问题。PyTorch的CrossEntropyLoss期望的输入就是未经过Softmax的logit这一点一定要记住。还有一个实操中经常遇到的问题迁移学习时的输出层替换。假设你用预训练的ResNet-50做1000类分类现在要迁移到自己的10类任务。正确的做法是把最后的全连接层或GAP之后的输出层替换成新的10维输出层前面的卷积层全部冻结或微调。这里的关键是新输出层的初始化。如果随机初始化初始梯度会很大可能破坏预训练的特征。建议用较小的标准差比如0.01做高斯初始化或者直接用Xavier初始化。另外冻结层数也要根据数据量决定数据少就多冻结数据多就少冻结。下面这张表对比了不同网络结构在多分类任务上的适用场景网络结构参数量适用数据量多分类特点LeNet-5约6万极小1万输出层直接接Softmax简单直接VGG-16约1.3亿中等1-10万全连接层参数大需强正则化ResNet-50约2500万大10万GAP替代全连接参数量小MobileNet约400万移动端/小数据深度可分离卷积轻量高效5. 训练多分类模型的实操细节学习率、Batch Size与正则化网络结构搭好了损失函数选定了接下来就是训练。多分类任务的训练过程和二分类大同小异但有几个参数和技巧需要特别调整。这一章我把自己在多个项目中总结的经验参数和踩坑记录分享出来。先说学习率。多分类任务的输出层维度更高Softmax的梯度行为比Sigmoid更复杂所以学习率通常要比二分类小一些。我的经验值是如果用SGD初始学习率取0.01到0.1如果用Adam取0.001到0.0001。但这不是绝对的关键是要配合学习率预热Warmup。多分类任务在训练初期输出层的随机初始化会导致Softmax输出接近均匀分布梯度方向不稳定。如果一开始就用大学习率很容易震荡。Warmup的做法是在前几个epoch把学习率从0线性增加到初始值让网络先稳定下来。这个技巧在Transformer时代被广泛使用但在CNN多分类任务上同样有效尤其是当batch size较大时。再说Batch Size。多分类任务对batch size比二分类更敏感因为每个batch里的类别分布直接影响梯度的方向。如果batch size太小比如8一个batch里可能只包含2-3个类别梯度会偏向这些类别导致训练不稳定。如果batch size太大比如1024虽然梯度稳定但泛化能力可能下降。我的建议是batch size至少是类别数的5-10倍。比如10分类任务batch size至少取64100分类任务至少取512。如果显存不够可以用梯度累积来模拟大batch。正则化是多分类任务的重中之重。因为输出层维度高模型很容易过拟合。常用的正则化手段有三种L2正则权重衰减、Dropout、数据增强。L2正则的系数通常取1e-4到1e-5太大导致欠拟合太小不起作用。Dropout在全连接层后面加丢弃率0.5在卷积层后面加丢弃率0.2-0.3。数据增强对图像分类尤其重要随机裁剪、水平翻转、颜色抖动这三件套几乎是标配。但要注意不是所有增强都适合所有任务。比如数字识别任务水平翻转会把“6”变成“9”这种增强反而有害。垂直翻转对自然图像通常也没意义因为重力方向是固定的。还有一个容易被忽略的细节Batch Normalization的位置。BN通常放在卷积层之后、激活函数之前。但在多分类任务的输出层之前要不要加BN我的经验是不要。因为BN会改变logit的分布而Softmax对logit的绝对大小敏感。如果在输出层前加BN相当于强制logit的均值为0、方差为1这会限制Softmax输出的动态范围导致模型难以产生高置信度的预测。如果非要用可以在BN之后加一个可学习的缩放参数但这增加了调参复杂度不如直接不用。早停Early Stopping也是多分类任务中必须用的技巧。因为多分类的验证集准确率曲线通常比二分类更平滑不容易出现剧烈的过拟合信号。我的做法是监控验证集损失如果连续10个epoch没有下降就停止训练并回滚到验证集损失最低的模型。注意是监控损失而不是准确率因为准确率是离散的可能长时间不变化而损失是连续的能更早地反映过拟合趋势。下面这张表总结了我常用的多分类训练参数配置参数推荐值说明初始学习率SGD0.01-0.1配合Warmup使用初始学习率Adam0.001-0.0001更稳定适合小数据Batch Size类别数×5-10保证每batch类别多样性权重衰减1e-4到1e-5L2正则防止过拟合Dropout全连接0.5输出层前通常不加Dropout卷积0.2-0.3可选视过拟合程度早停耐心值10个epoch监控验证集损失6. 评估与调优混淆矩阵比准确率更有信息量模型训练完了准确率90%看起来不错。但如果你只盯着准确率可能会错过很多关键信息。多分类任务的评估远比二分类复杂因为类别之间的错误模式才是真正有价值的东西。这一章我讲怎么用混淆矩阵和每类指标来诊断模型以及遇到具体问题时怎么调优。先说什么叫混淆矩阵。它是一个 $C \times C$ 的矩阵行是真实类别列是预测类别。对角线上的数字是正确分类的样本数非对角线是错误分类的样本数。这个矩阵能一眼看出模型在哪些类别上容易混淆。比如在手写数字识别中混淆矩阵经常显示“4”被预测成“9”、“3”被预测成“8”、“5”被预测成“6”。这些错误不是随机的而是因为字形相似。知道了这一点你就可以针对性地做数据增强比如对4和9增加旋转和形变或者调整类别权重。每类精确率、召回率和F1分数也是必须看的指标。精确率是“预测为某类的样本中真正属于该类的比例”召回率是“真正属于某类的样本中被正确预测的比例”。在多分类中这两个指标往往不一致。比如一个类别样本很少模型可能倾向于不预测它导致召回率低但精确率高。F1是两者的调和平均能综合反映。我的习惯是先看混淆矩阵找主要错误模式再看每类F1找短板类别最后针对短板类别做定向优化。常见的调优手段有几种。如果某个类别的召回率特别低说明模型“不敢”预测这个类别可能是类别权重不够或者这个类别的特征不够有判别力。解决方案是增加这个类别的样本权重或者对这个类别做更强的数据增强。如果某个类别的精确率特别低说明模型“过度”预测这个类别可能是这个类别的样本太多或者和其他类别太像。解决方案是降低这个类别的权重或者增加负样本。还有一个进阶技巧Top-K准确率。在类别数很多时比如1000类Top-1准确率可能不高但Top-5准确率很高说明模型其实“知道”正确答案在候选列表里只是排序不够靠前。这时候可以通过标签平滑或者知识蒸馏来提升排序质量。知识蒸馏的做法是用一个更大的教师模型比如ResNet-152的输出概率作为软标签让学生模型比如ResNet-18去拟合。软标签包含了类别之间的相似性信息比如“猫”和“狗”的概率都比“汽车”高比硬标签更有信息量。这个技巧在模型压缩和提升小模型精度上非常有效。最后说一个我踩过的坑验证集和测试集的类别分布不一致。有一次做项目验证集准确率95%测试集只有80%。排查后发现验证集是从训练集随机划分的类别分布和训练集一致但测试集是另一个时间段采集的某些类别的比例差异很大。解决方案是验证集必须和测试集同分布如果做不到至少要在验证集上做类别分层采样保证每个类别的比例和测试集接近。这个教训让我后来养成了一个习惯拿到数据第一件事就是画类别分布图训练集、验证集、测试集各画一张对比着看。7. 一个完整的多分类项目复盘从数据到部署前面六章把多分类的各个环节都拆开讲了这一章我用一个完整的项目案例把它们串起来。这个项目是交通标志分类数据集是GTSRBGerman Traffic Sign Recognition Benchmark共43个类别训练集约3.9万张测试集约1.2万张。我选择这个案例是因为它规模适中、类别多、类别不均衡明显非常能体现多分类任务的典型挑战。数据准备阶段。GTSRB的图片尺寸不一从15×15到250×250都有。第一步是统一尺寸我选了32×32因为这是CIFAR-10的标准尺寸很多预训练模型可以直接用。但缩小尺寸会丢失细节尤其是小标志上的数字和图案。我的做法是先用32×32训练一个基线模型如果某些类别的准确率明显偏低再对这些类别用更大的尺寸比如64×64单独训练一个专家模型。这种“全局专家”的架构在实际项目中很常见。类别不均衡是GTSRB的另一个特点。最多的类别有2000多张最少的只有200多张。我用了加权采样在构造DataLoader时给每个样本一个权重权重和类别频率成反比。这样每个batch里各类别的期望数量大致相等。同时用了类别加权交叉熵权重是类别频率的倒数再归一化。两个手段叠加少数类的召回率从最初的60%提升到了85%以上。模型设计阶段。我选了ResNet-18作为骨干网络因为它在32×32输入上的表现和ResNet-34差不多但参数量少一半。输出层替换成43维用GAP替代全连接。这里有一个细节ResNet原本是为224×224设计的第一层是7×7卷积、步长2然后接3×3最大池化。对于32×32输入这个下采样太激进了特征图会变得太小。我的改动是把第一层换成3×3卷积、步长1去掉最大池化这样特征图在进入残差块之前保持32×32。这个改动让准确率提升了3个百分点。训练阶段。用了Adam优化器初始学习率0.001每20个epoch衰减0.1。Batch size取128因为43个类别128大约是类别数的3倍再小就不稳定了。数据增强用了随机旋转±15度、随机缩放0.9-1.1、颜色抖动亮度、对比度、饱和度各±0.2。没有用水平翻转因为交通标志翻转后可能变成另一个标志比如左转和右转。训练了80个epoch验证集准确率在60个epoch后基本饱和早停触发。评估阶段。最终测试集Top-1准确率97.2%Top-5准确率99.8%。混淆矩阵显示主要错误集中在几个相似的标志上限速30和限速50数字形状相似、禁止超车和禁止大型车超车图案相似。针对这两个混淆对我做了两件事一是对这两对类别增加额外的训练样本从其他数据源补充二是用对比损失在特征层面拉开它们的距离。对比损失的做法是在GAP之后加一个投影头把特征映射到128维空间然后让同类样本的特征距离近、异类样本的特征距离远。这个技巧让这两对类别的F1分数从0.89提升到了0.95。部署阶段。模型导出为ONNX格式用ONNX Runtime做推理。这里有一个坑训练时用了GAP但ONNX对GAP的支持在不同版本间有差异。我最后是把GAP手动展开成ReduceMean操作确保兼容性。推理时的预处理必须和训练时完全一致同样的归一化参数均值0.5、标准差0.5、同样的通道顺序RGB、同样的尺寸32×32。任何不一致都会导致精度下降而且这种下降往往很隐蔽因为模型仍然会输出结果只是结果错了。这个项目让我最深的体会是多分类任务的精度提升80%来自数据质量和标签一致性20%来自模型和调参。GTSRB的标签质量很高所以模型很容易做到95%以上。但如果标签有噪声比如某些图片被标错了类别模型精度会卡在一个瓶颈上怎么调参都上不去。所以如果你发现模型精度不达预期第一件事不是换模型而是抽样检查标签。我通常随机抽100张图人工核对标签如果错误率超过5%就要考虑清洗数据了。8. 多分类任务的边界与常见误区写到这里多分类的核心内容基本讲完了。但还有几个边界问题和常见误区需要澄清这些是我在带新人和做技术评审时经常遇到的。第一个误区多分类和二分类的损失函数可以混用。有人觉得二分类就是C2的多分类所以用交叉熵就行了。理论上没错但实操中二分类用BCELoss配合Sigmoid和多分类用CrossEntropyLoss配合Softmax在数值行为上有差异。BCELoss对每个输出独立计算而CrossEntropyLoss做全局归一化。对于C2的情况两者在数学上等价但梯度尺度不同。我的建议是C2时用二分类的写法C2时用多分类的写法不要为了统一而统一因为框架对两种写法的优化程度不同。第二个误区类别数越多模型越难训练。这个说法不完全对。类别数增加确实会增加输出层的参数量但现代网络的瓶颈通常在特征提取部分不在输出层。真正影响训练难度的是类别之间的可分性。1000个差异很大的类别比如ImageNet可能比10个非常相似的类别比如不同品种的狗更容易训练。所以不要被类别数吓到先分析类别之间的视觉差异有多大。第三个边界多分类 vs 多标签分类。这是两个完全不同的任务。多分类是“一个样本属于且仅属于一个类别”多标签是“一个样本可以同时属于多个类别”。多标签的输出层用Sigmoid而不是Softmax损失函数用二元交叉熵而不是多类交叉熵。我见过有人把多标签任务当多分类做结果模型只能预测一个标签漏掉了其他标签。判断方法很简单看你的标注数据如果一个样本可以同时打多个标签那就是多标签如果只能打一个那就是多分类。第四个边界开集识别Open-Set Recognition。标准的多分类假设测试集的类别和训练集完全一致。但现实中测试时可能出现训练时没见过的类别。这时候Softmax会强行把新类别分到某个已知类别而且可能给出很高的置信度。解决方案有几种一是用阈值法如果最大Softmax概率低于某个阈值就判为“未知”二是用原型网络计算样本特征和每个类别原型的距离距离都很大就判为未知三是用生成模型估计每个类别的数据分布分布外的样本判为未知。这些方法各有优劣选择取决于具体场景。最后一个实操建议永远保留一个“其他”类别。如果你的数据里有一些难以归类的样本不要强行把它们塞进某个类别而是单独设一个“其他”类。这个类别可以包含各种杂项让模型学会“这些不是我要分类的目标”。在部署时如果“其他”类的概率最高就触发人工审核或者拒绝预测。这个策略在工业质检、内容审核等场景中非常实用能显著降低误报率。多分类是神经网络中最基础也最核心的任务之一。把多分类吃透了再去看目标检测、语义分割、实例分割这些更复杂的任务你会发现它们本质上都是在多分类的基础上增加了空间维度的处理。所以这一块的基础打牢了后面的路会好走很多。