多分类(Multiclass Classification)&多标签分类(Multi-label Classification)

TensorFlow-v2.15

TensorFlow-v2.15

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

一、多分类(Multiclass Classification)

1.1 多分类任务的定义

多分类任务是指将样本划分到三个或更多类别中的任务(区别于二分类的 “是 / 否”)。

  • 二分类示例:将样本分为 “class 1” 和 “not 1” 两类,用逻辑回归即可解决。
  • 多分类示例:将样本分为 4 个类别(红叉、蓝圈、黄方块、紫三角),需要更复杂的模型(如 Softmax 回归、带 Softmax 输出的神经网络)。

1.2 多分类的核心模型:Softmax 回归

Softmax 回归是逻辑回归在多分类场景的推广,核心是通过 “Softmax 函数” 将线性输出转化为类别概率分布

①逻辑回归 vs. Softmax 回归(Cost 部分)

  • 逻辑回归(二分类)

    • 输入 ,通过 Sigmoid 函数输出类别 1 的概率:

    • 类别 0 的概率为

    • 损失函数(交叉熵损失)为

    • 其中 y∈{0,1} 是真实标签。

  • Softmax 回归(多分类)

    • .假设共有 N 个类别,先计算每个类别的线性得分 z1​,z2​,…,zN​(即 ),再通过 Softmax 函数将得分转化为概率:

    • 所有 ai​ 之和为 1,满足概率的基本性质。

    • 损失函数(交叉熵损失)为:

    • 直观理解:若真实类别是 j,则损失是 “对预测概率 aj​ 取负对数”

    • aj​ 越接近 1,损失越小;越接近 0,损失越大。


1.3 带 Softmax 输出的神经网络

在深度学习中,我们可以将 Softmax 作为神经网络的输出层,处理多分类任务。

以识别手写数字的 MNIST 数据集(10 个类别:0-9)为例,网络结构通常为:

  • 隐藏层:使用 ReLU 激活(引入非线性,高效训练),如 “25 个神经元的 Dense 层 + 15 个神经元的 Dense 层”。
  • 输出层:10 个神经元,使用 Softmax 激活,输出 10 个类别各自的概率(如

这种结构的本质是:隐藏层提取输入的非线性特征,输出层通过 Softmax 将特征映射为类别概率


1.4 实战:TensorFlow/Keras 实现多分类模型(MNIST with softmax)

基于 TensorFlow/Keras 的代码框架,步骤如下:

  • ①定义模型(specify the model)
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense

model = Sequential([
    Dense(units=25, activation='relu'),   # 隐藏层1:25个神经元,ReLU激活
    Dense(units=15, activation='relu'),   # 隐藏层2:15个神经元,ReLU激活
    Dense(units=10, activation='softmax') # 输出层:10个类别,Softmax激活
])
  • ②定义损失函数(specify loss and cost)

        多分类任务通常使用稀疏分类交叉熵损失SparseCategoricalCrossentropy):

from tensorflow.keras.losses import SparseCategoricalCrossentropy

model.compile(loss=SparseCategoricalCrossentropy())
  • ③训练模型(Train on data)
model.fit(X, y, epochs=100)  # X是输入特征,y是真实标签(如0-9的整数)

1.5 数值稳定性优化(Numerical Roundoff Errors)

在深度学习中,直接计算 Softmax 或 Sigmoid 可能因数值溢出(如 当 很大时趋于无穷)导致计算不稳定。因此需要更精确的实现方式:

①. 逻辑回归的数值稳定优化

对于二分类任务,避免直接计算 Sigmoid 后再求损失,而是直接对线性输出(logits)计算损失:

# 不推荐:先过Sigmoid再算损失
model = Sequential([
    Dense(units=25, activation='relu'),
    Dense(units=15, activation='relu'),
    Dense(units=1, activation='sigmoid')
])
model.compile(loss=BinaryCrossentropy())

# 推荐:对logits直接计算损失(数值更稳定)
model = Sequential([
    Dense(units=25, activation='relu'),
    Dense(units=15, activation='relu'),
    Dense(units=1, activation='linear')  # 输出层无激活,直接输出logits
])
model.compile(loss=BinaryCrossentropy(from_logits=True))
# 预测时再用Sigmoid转换为概率
logits = model.predict(X)
prob = tf.nn.sigmoid(logits)

②. Softmax 回归的数值稳定优化

同理,多分类任务也应对输出层的 logits 直接计算损失

# 不推荐:先过Softmax再算损失
model = Sequential([
    Dense(units=25, activation='relu'),
    Dense(units=15, activation='relu'),
    Dense(units=10, activation='softmax')
])
model.compile(loss=SparseCategoricalCrossentropy())

# 推荐:对logits直接计算损失(数值更稳定)
model = Sequential([
    Dense(units=25, activation='relu'),
    Dense(units=15, activation='relu'),
    Dense(units=10, activation='linear')  # 输出层无激活,直接输出logits
])
model.compile(loss=SparseCategoricalCrossentropy(from_logits=True))
# 预测时再用Softmax转换为概率
logits = model.predict(X)
prob = tf.nn.softmax(logits)

这种优化的核心是将 “激活函数 + 损失计算” 合并为更高效的数值计算方式,避免中间步骤的精度损失或溢出。


1.6 扩展:多分类的其他场景与技巧

  • 类别不平衡问题:若某类别样本极少,可通过加权损失(如 class_weight 参数)或数据增强来缓解。
  • 多标签分类:区别于 “每个样本仅属于一个类别” 的多分类,多标签分类允许样本同时属于多个类别(如一张图片同时包含 “猫” 和 “狗”),此时输出层通常用 Sigmoid 激活(每个类别独立预测),损失用二元交叉熵损失
  • 模型评估指标:多分类任务常用准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F1 分数等指标,需根据业务场景选择(如医疗诊断更关注召回率,避免漏诊)。

二、多标签分类(Multi-label Classification)

2.1 多标签分类的任务定义

多标签分类是指一个样本可以同时属于多个类别的分类任务(区别于 “多分类任务中每个样本仅属于一个类别”)。

  • 想象第一张图:同时包含 “car(汽车)” 和 “pedestrian(行人)”,所以标签为 y=​(“1” 表示存在该类别,“0” 表示不存在)。
  • 想象第二张图:仅包含 “pedestrian(行人)”,标签为 y=
  • 想象第三张图:同时包含 “car(汽车)” 和 “bus(公交车)”,标签为 y=​​​。

2.2 多标签分类与多分类的核心区别

维度多分类(Multiclass)多标签分类(Multi-label)
类别关系互斥(一个样本仅属于一个类别)非互斥(一个样本可属于多个类别)
标签形式单个整数(如 y∈{0,1,2,3})二进制向量(如 y∈{0,1}3,每个维度对应一个类别是否存在)
输出层激活Softmax(输出概率和为 1)多个 Sigmoid(每个类别独立输出概率,和不一定为 1)
损失函数分类交叉熵(如 SparseCategoricalCrossentropy)多个二元交叉熵(如 BinaryCrossentropy,每个类别独立计算)

2.3 多标签分类的模型结构

两种模型构建思路:

①独立模型法(训练多个二分类模型)

对每个类别(如 car、bus、pedestrian)单独训练一个二分类神经网络

  • 模型 1:输入图片 → 输出 “是否有 car”(Sigmoid 激活,输出 0-1 概率)。
  • 模型 2:输入图片 → 输出 “是否有 bus”(Sigmoid 激活)。
  • 模型 3:输入图片 → 输出 “是否有 pedestrian”(Sigmoid 激活)。

这种方法的优点是每个类别独立训练,逻辑简单;缺点是重复计算(多个模型共享底层特征却重复训练),效率低

②多输出单模型法(共享特征的多输出网络)

训练一个共享隐藏层的多输出神经网络

  • 隐藏层:提取图片的通用特征(如边缘、形状等),所有类别共享这些特征。
  • 输出层:有 3 个神经元,每个神经元对应一个类别,使用Sigmoid 激活(因为每个类别是独立的二分类问题,输出 0-1 的概率)。

  • a1[3]​ 是 “存在 car” 的概率,
  • a2[3]​ 是 “存在 bus” 的概率,
  • a3[3]​ 是 “存在 pedestrian” 的概率。

这种方法的优点是共享特征提取,训练高效,参数更少;是工业界更常用的方案。

2.4 多标签分类的损失函数

由于每个类别是独立的二分类问题,多标签分类的损失函数是多个二元交叉熵损失的和

对于单个样本,若真实标签为(yi​∈{0,1}),模型输出为 (y^​i​ 是 Sigmoid 输出的概率),则损失为:

在框架中(如 TensorFlow/Keras),可直接使用 BinaryCrossentropy 损失函数,因为它会对每个输出维度独立计算二元交叉熵并求和。

2.5 多标签分类的应用场景

多标签分类在现实中非常常见,典型场景包括:

  • 图像标注:一张图片可能同时包含 “猫”“狗”“草地” 等多个标签。
  • 文本分类:一篇新闻可能同时属于 “科技”“经济”“国际” 等多个类别。
  • 医疗诊断:一个病人可能同时患有 “高血压”“糖尿病” 等多种疾病。

2.6 扩展:多标签分类的评估指标

由于标签非互斥,多分类的 “准确率” 指标不再适用,需采用更适合的指标:

  • 精确率(Precision):模型预测为 “存在” 的类别中,真正存在的比例()。
  • 召回率(Recall):真实存在的类别中,模型预测为 “存在” 的比例(​)。
  • F1 分数:精确率和召回率的调和平均(),综合两者性能。
  • Hamming 损失:预测错误的标签数占总标签数的比例,衡量整体标签预测的准确性。

您可能感兴趣的与本文相关的镜像

TensorFlow-v2.15

TensorFlow-v2.15

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

### 多分类问题中的 ROC 和 AUC 在多分类问题中,传统的二分类 ROC 曲线和 AUC 需要扩展到多个类别上。通常的做法是通过一对多(One-vs-Rest, OvR)或一对一(One-vs-One, OvO)策略来处理多分类问题。 #### One-vs-Rest (OvR) 方法 在这种方法下,每个类别的样本被标记为正类,而其他所有类别的样本则被视为负类。这样可以构建 \( C \) 条独立的 ROC 曲线(\( C \) 是类别总数)。每条曲线对应于一个特定类别的性能表现[^1]。 对于每一类,计算其对应的 TPR(True Positive Rate)和 FPR(False Positive Rate),并绘制相应的 ROC 曲线。最终可以通过平均这些单类别的 AUC 值得到整体的 AUC 表现: \[ AUC_{macro} = \frac{1}{C} \sum_{i=1}^{C} AUC_i \] 其中,\( AUC_i \) 表示第 \( i \) 类别下的 AUC 值[^2]。 #### Micro 平均法 Micro 平均法则是在全局范围内统计真正例数(TP)、假正例数(FP)和真反例数(TN),从而统一计算整个数据集上的 TPR 和 FPR。这种方法不区分具体类别,而是将所有预测结果汇总在一起进行分析。这种方式更适合关注总体错误率的应用场景[^3]。 以下是基于 Python 的 `scikit-learn` 实现多分类 ROC-AUC 的代码示例: ```python from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.preprocessing import label_binarize from sklearn.multiclass import OneVsRestClassifier from sklearn.linear_model import LogisticRegression from sklearn.metrics import roc_curve, auc, roc_auc_score import matplotlib.pyplot as plt from itertools import cycle import numpy as np # 创建模拟数据集 X, y = make_classification(n_samples=1000, n_classes=3, n_informative=3, random_state=42) # 将标签转换为 one-hot 编码形式 y_bin = label_binarize(y, classes=[0, 1, 2]) n_classes = y_bin.shape[1] # 划分训练集与测试集 X_train, X_test, y_train, y_test = train_test_split(X, y_bin, test_size=.5, random_state=42) # 使用逻辑回归作为基础分类器 classifier = OneVsRestClassifier(LogisticRegression()) y_score = classifier.fit(X_train, y_train).predict_proba(X_test) # 计算微平均 ROC 曲线和 AUC fpr_micro, tpr_micro, _ = roc_curve(y_test.ravel(), y_score.ravel()) auc_micro = auc(fpr_micro, tpr_micro) # 计算宏平均 ROC 曲线和 AUC fpr = dict() tpr = dict() roc_auc = dict() for i in range(n_classes): fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i]) roc_auc[i] = auc(fpr[i], tpr[i]) all_fpr = np.unique(np.concatenate([fpr[i] for i in range(n_classes)])) mean_tpr = np.zeros_like(all_fpr) for i in range(n_classes): mean_tpr += np.interp(all_fpr, fpr[i], tpr[i]) mean_tpr /= n_classes fpr_macro = all_fpr tpr_macro = mean_tpr auc_macro = auc(fpr_macro, tpr_macro) plt.figure(figsize=(8, 6)) # 绘制微平均 ROC 曲线 plt.plot(fpr_micro, tpr_micro, label=f'Micro-average ROC curve (area = {auc_micro:.2f})', color='deeppink') # 绘制宏平均 ROC 曲线 plt.plot(fpr_macro, tpr_macro, label=f'Macro-average ROC curve (area = {auc_macro:.2f})', color='navy') # 添加对角线基线和其他设置 plt.plot([0, 1], [0, 1], 'k--') plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('Receiver Operating Characteristic for multi-class data') plt.legend(loc="lower right") plt.show() ``` 上述代码展示了如何利用 `scikit-learn` 库实现多分类问题中的 ROC 和 AUC 计算,并分别给出了 Macro 和 Micro 平均的结果可视化。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值