【机器学习】(27)—— 神经网络多分类

神经网络多分类:一对多和 Softmax

文章目录

  • [神经网络多分类:一对多和 Softmax](#神经网络多分类:一对多和 Softmax)
    • [1. 选项从两个变成多个](#1. 选项从两个变成多个)
    • [2. 一对多:每个类确认一次](#2. 一对多:每个类确认一次)
      • [2.1 放到一张网络里](#2.1 放到一张网络里)
    • [3. Softmax:在类与类之间分概率](#3. Softmax:在类与类之间分概率)
    • [4. 汽车例子:按重量分三档](#4. 汽车例子:按重量分三档)
    • [5. 和多标签区分](#5. 和多标签区分)
    • [6. 动手:Iris 上对比逻辑回归与 MLP](#6. 动手:Iris 上对比逻辑回归与 MLP)
    • [7. 实现时几个容易混的点](#7. 实现时几个容易混的点)
    • [8. 适用边界与常见误区](#8. 适用边界与常见误区)
      • [8.1 适用边界](#8.1 适用边界)
      • [8.2 常见误区](#8.2 常见误区)
    • [9. 关键术语速查](#9. 关键术语速查)
    • [10. 延伸阅读](#10. 延伸阅读)
    • [11. 小结](#11. 小结)

摘要 :专栏前半段的分类多是「高效 / 非高效」二选一。车型档位、故障类型、手写数字这类问题,选项往往有三个以上,而且每个样本只属于其中一类 。第 13 篇从通用角度介绍过多分类;本篇把它接到神经网络输出层上,讲清 一对多(one-vs-all)Softmax 差在哪里、概率要不要加起来等于 1,以及什么时候不该用 Softmax。适合读完浅层网络实践的读者。


1. 选项从两个变成多个

二分类输出一个概率 p p p,再靠阈值切成 0/1。多分类时,标签变成 0 , 1 , ... , K − 1 0,1,\ldots,K-1 0,1,...,K−1,模型要给出 K K K 个分数或概率,最后通常取最大的那一类。

二分类 多分类(单标签)
例子 是否高效 轻 / 中 / 重 三档
输出 1 个概率 K K K 个值
约束 p ∈ ( 0 , 1 ) p\in(0,1) p∈(0,1) Softmax 下各类概率和为 1

和第 13 篇一样,先分清:

  • 多分类:单选题,每辆车只能落在一档
  • 多标签:多选题,一张图可以同时有「猫」和「户外」

本篇默认讲单选题。多标签一般是每个标签各接一个 Sigmoid,不要用 Softmax 硬凑。

第 8~12 篇的阈值、混淆矩阵、精确率 / 召回率,在多分类里仍然用得上,只是混淆矩阵从 2 × 2 2\times 2 2×2 变成 K × K K\times K K×K。第 13 篇已从「不用神经网络」的角度讲过 OvR / Softmax;本篇重点是:这些头接在 MLP 最后一层时该怎么选


2. 一对多:每个类确认一次

一对多(One-vs-All / One-vs-Rest) :有 K K K 个类,就准备 K K K 个二分类问题。

对「轻 / 中 / 重」三档:

  1. 是不是轻?(对比:不是轻)
  2. 是不是中?
  3. 是不是重?

预测时看哪个分类器最「肯定」,或比较各自的分数。类数不多时,这个想法很直观;类数上到成百上千,就维护成本高、也慢。

2.1 放到一张网络里

不必真的训练 K K K 个完全独立的模型。可以共用前面的隐藏层,输出层放 K K K 个节点,每个节点各自接 Sigmoid

每个输出表示「是不是这一类」的概率,彼此独立 估计。因此三者加起来不一定等于 1------有可能都偏低或都偏高。

水果图的例子里,网络可能给出「梨 0.84、葡萄 0.07......」,加总超过 1,这在一对多设定里并不奇怪:它在分别回答「是不是梨」「是不是葡萄」,而不是在「四种水果里只能选一个」的约束下分配概率。

预测时常见做法是:看哪一路 Sigmoid 输出最大,就把该类当作预测;若业务允许「都不像」,也可以要求最大概率超过某阈值,否则判为未知。阈值仍建议在验证集上定,和第 09 篇同一思路。


3. Softmax:在类与类之间分概率

若业务要求「轻、中、重三者互斥,必须落在一档」,更常见的是 Softmax(也常叫一对一 / one-vs-one 语境下的相对概率,和第 13 篇用语一致即可)。

先对每个类算一个未归一化分数 z j z_j zj(logits),再:

p j = e z j ∑ k = 1 K e z k p_j = \frac{e^{z_j}}{\sum_{k=1}^{K} e^{z_k}} pj=∑k=1Kezkezj

于是 p j > 0 p_j>0 pj>0,且 ∑ j p j = 1 \sum_j p_j = 1 ∑jpj=1。

可以把它看成逻辑回归里 Sigmoid 往多类的推广:Sigmoid 处理「是 / 否」;Softmax 处理「在 K K K 个选项里挑一个」。

手算一个小数:设三档分数 z = ( 1.0 , 2.0 , 0.0 ) z=(1.0,\ 2.0,\ 0.0) z=(1.0, 2.0, 0.0),则

e 1 ≈ 2.72 , e 2 ≈ 7.39 , e 0 = 1 e^{1}\approx 2.72,\quad e^{2}\approx 7.39,\quad e^{0}=1 e1≈2.72,e2≈7.39,e0=1

分母 ≈ 11.11 \approx 11.11 ≈11.11,于是

p ≈ ( 0.24 , 0.67 , 0.09 ) p \approx (0.24,\ 0.67,\ 0.09) p≈(0.24, 0.67, 0.09)

「中」档分数最高,概率也被抬得最高;提高某一档的 z z z,会挤占其他档的概率------这就是「互相竞争」。

一对多 + Sigmoid Softmax
各类是否互斥建模 不强求 强求,概率互相挤占
概率和是否为 1 不一定
典型用途 类可近似独立判断 单标签多分类默认选择

类特别多(例如上万类)时,完整 Softmax 算分母会贵,工程上会用候选采样等近似;入门阶段类数不大,用完整 Softmax 即可。

数值上算 Softmax 时,常先减去 max ⁡ k z k \max_k z_k maxkzk 再取指数,避免 e z e^{z} ez 溢出。手算小例子不必纠结;自己用 NumPy 实现时记得这一步。框架里的 Softmax 一般已处理稳定计算。


4. 汽车例子:按重量分三档

把专栏里的重量粗分成三档标签(演示用,阈值可改):

档位 条件(千磅) 标签
< 3.0 < 3.0 <3.0 0
3.0 3.0 3.0~ 4.0 4.0 4.0 1
> 4.0 > 4.0 >4.0 2

二分类问「高不高效」;这里问「偏轻、适中还是偏重」。特征仍可用重量、排量等,输出层改为 3 个节点。

  • 若用 Softmax:三个概率和为 1,取 argmax 得档位。
  • 若用三个 Sigmoid:更像三个独立「是不是这一档」的问题;对互斥档位,一般不如 Softmax 合适。

损失方面,Softmax 多分类常用交叉熵 (多类版 Log Loss)。训练仍是前向算 p p p、算损失、反向更新(第 25 篇),只是输出维数从 1 变成 K K K。

若训练集里「重」车特别少,Softmax 仍可能偷懒少报「重」------第 20 篇的类别不平衡问题在多分类里同样存在,需要看每类召回,必要时加类别权重或重采样。


5. 和多标签区分

场景 该用什么
每张图只有一种主果蔬 Softmax 多分类
一碗里同时有苹果和橙子 多个 Sigmoid / 多个二分类,不用 Softmax
邮件:垃圾 / 正常 二分类 Sigmoid 即可
故障码:互斥的 5 种故障 Softmax

Softmax 的假设是:每个样本恰好属于一类。不满足就换输出头,别硬套。

训练标签也要一致:若标注规范里允许「既算中型又算偏重」,那是多标签问题,应拆成多个是/否,而不是强行塞进三个互斥档。和业务对齐标签定义,往往比纠结隐藏层宽度更重要。


6. 动手:Iris 上对比逻辑回归与 MLP

python 复制代码
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import accuracy_score, log_loss, classification_report

X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=0, stratify=y
)

def eval_model(name, clf):
    pipe = Pipeline([("scaler", StandardScaler()), ("clf", clf)])
    pipe.fit(X_train, y_train)
    proba = pipe.predict_proba(X_test)
    pred = pipe.predict(X_test)
    print(name, {
        "acc": round(accuracy_score(y_test, pred), 3),
        "logloss": round(log_loss(y_test, proba), 3),
    })
    # Softmax 概率应按行求和为 1
    print("  prob row sums:", proba.sum(axis=1).round(3)[:5], "...")
    return pipe

# 逻辑回归多分类默认可用 Softmax(multinomial)
eval_model(
    "logreg",
    LogisticRegression(max_iter=1000, multi_class="multinomial"),
)

eval_model(
    "mlp",
    MLPClassifier(
        hidden_layer_sizes=(8,),
        activation="relu",
        learning_rate_init=0.01,
        max_iter=2000,
        random_state=0,
    ),
)

看两件事:准确率 / log loss 是否合理;proba 每一行是否加起来接近 1(Softmax 行为)。MLPClassifier 在多类问题上会走 Softmax 风格的输出;若你自己用底层框架搭网络,输出层要明确写成 Softmax + 交叉熵,别和隐藏层的 ReLU 搞混。

汽车三档数据可以把 y 换成按重量分箱的标签,特征用 weightdisplacement 等,流程相同:先标准化,再 MLP,再用混淆矩阵看哪两档最容易混(第 09、13 篇)。

打印 classification_report 时,重点看每一档的 precision / recall,而不是只看总 accuracy。三档样本若几乎均衡,准确率还算有参考价值;若某一档极少,总准确率容易虚高。


7. 实现时几个容易混的点

输出激活和隐藏激活不是一回事。

隐藏层继续用 ReLU(第 24、26 篇);多分类输出才是 Softmax 或若干 Sigmoid。

一对多的 Sigmoid 概率不要当成「已经归一化」。

若产品文案写「三类概率加总 100%」,就应上 Softmax,或事后自己归一化并说明含义变了。

类很多时。

完整 Softmax 分母要对所有类求和。类数极大时,候选采样等技巧会只对部分负类算分,那是工程优化,入门先把小 K K K 做对。

评估。

准确率在类别不平衡时仍可能骗人(第 20 篇);多分类更要看每类召回、宏平均 / 加权 F1,以及 K × K K\times K K×K 混淆矩阵。

和浅层网络实践怎么接。

第 26 篇的圆环是二分类。改成三类点(例如内、中、外三环)后,把 MLPClassifier 的标签换成 0/1/2,输出自动变成三维 Softmax 概率,调隐藏层宽度和学习率的方法不变。先保证二分类能分弯,再加类数,排查时更轻松。


8. 适用边界与常见误区

8.1 适用边界

  • 本篇接在神经网络输出层;第 13 篇的 OvR / OvO 思想对树模型、SVM 同样适用。
  • Softmax 管「选哪个类」,不管特征脏不脏、有没有泄漏------第 18~22 篇的检查仍然要做。
  • 回归(预测 MPG 连续值)不是 Softmax 的场景。

8.2 常见误区

误区 更稳妥的理解
多分类就是多标签 单选 vs 多选,输出头不同
有 K K K 个 Sigmoid 输出,概率必加总为 1 一对多不保证;Softmax 才保证
隐藏层也要用 Softmax Softmax 一般在输出层
类一多就先上很深的网 先确认标签是否互斥、数据是否够
只报总准确率 结合每类指标和混淆矩阵
Softmax 概率能直接当校准很好的置信度 未校准前别过度解读;需要时再做概率校准

9. 关键术语速查

术语 含义
多分类 每样本恰好一类, K ≥ 3 K\ge 3 K≥3
一对多 每类一个「是该类 / 不是」问题
Softmax 将 K K K 个分数变成和为 1 的概率
logit Softmax 之前的原始分数 z j z_j zj
交叉熵 多分类常用损失,对接 Softmax
多标签 每样本可同时有多个标签

10. 延伸阅读

资源 适合看什么
专栏第 13 篇 OvR、OvO、多分类与多标签
专栏第 24 篇 Sigmoid 与输出激活
sklearn LogisticRegression multi_class='multinomial'
sklearn MLPClassifier 多类 MLP
Iris 数据集 三类小样本练习

11. 小结

神经网络做多分类,关键在输出层怎么接:一对多用 K K K 个 Sigmoid,各类概率可以独立、加总不必为 1;标签互斥时用 Softmax,让概率在 K K K 类里互相竞争且加总为 1。隐藏层仍用 ReLU 一类激活,和输出头分开选。

text 复制代码
互斥单标签 → Softmax + 交叉熵
可重叠多标签 → 每标签 Sigmoid
二分类 → 一个 Sigmoid 即可

汽车从「是否高效」换成「轻 / 中 / 重」后,只是 K K K 从 2 变成 3,前面的划分、标准化和过拟合处理并不过时。

接输出头之前先确认标签互不互斥:互斥用 Softmax,可重叠用多个 Sigmoid。头接错了,后面网络再深,优化的也是错问题。

下一篇会对神经网络做一次总结,然后过度到后面的 Embedding 等内容。

系列导航


如果本篇对你有帮助,欢迎点赞、收藏、关注博主,机器学习专栏持续更新中,下次更新不迷路。

相关推荐
湘美书院--湘美谈教育2 小时前
湘美谈教育互联网逻辑:AI时代的社会学猜想
大数据·人工智能·深度学习·机器学习·生活
KKKlucifer2 小时前
多源异构通信数据统一识别:运营商分类分级平台关键技术与落地成
人工智能·分类·数据挖掘
陕西企来客4 小时前
生成式引擎优化(GEO)行业白皮书:从流量分配到认知占有的战略跃迁
人工智能·算法·机器学习·技术好geo优化
m沐沐4 小时前
【深度学习】循环神经网络RNN——结构、原理与长期依赖问题解析
人工智能·pytorch·python·rnn·深度学习·算法·机器学习
workflower5 小时前
情境感知系统
人工智能·机器学习·设计模式·自然语言处理·机器人
AAIshangyanxiu6 小时前
Python 机器学习与深度学习气象水文海洋全域应用技术体系:地学时空数据 AI 建模、数值模式后处理、气象海洋水文智能预测与数据处理
人工智能·python·机器学习·水文气象·气象预测·气象海洋
fl1768316 小时前
电力场景配网耐张线夹绝缘保护套安装状态检测数据集VOC+YOLO格式2375张2类别
人工智能·yolo·机器学习
祝威廉6 小时前
四条语句跑完机器学习:让模型成为一个 SQL 函数
人工智能·sql·机器学习
Ro Jace7 小时前
模型驱动、知识驱动、数据驱动有什么区别?
神经网络