写点什么

模型的泛化性能度量:方法、比较与实现

作者:秃头小帅oi
  • 2025-03-27
    福建
  • 本文字数:3781 字

    阅读完需:约 12 分钟

在机器学习领域,模型的泛化性能度量是评估模型在未知数据上表现的关键环节。

通过合理的性能度量,不仅能了解模型的优劣,还能为模型的优化和选择提供科学依据。

本文将深入探讨泛化性能度量的重要性、各种度量方法、它们之间的区别与适用场景,并通过scikit-learn代码示例来展示如何实现这些度量方法。

1. 为什么要做泛化性能度量

模型的最终目标是在面对新数据时能够准确、稳定地进行预测或分类。

然而,在训练过程中,模型可能会出现过拟合(对训练数据拟合得过于紧密,导致在新数据上表现不佳)或欠拟合(未能充分学习数据特征)等问题。

泛化性能度量能够帮助我们:

  1. 客观评估模型优劣:通过量化的指标,准确判断模型在未知数据上的表现,避免主观臆断。

  2. 指导模型优化:明确模型的不足之处,为调整模型参数、选择更合适的算法提供方向。

  3. 比较不同模型:在多个模型之间进行公平、科学的比较,选出最适合特定任务的模型。

  4. 提前预警问题:及时发现模型可能存在的过拟合或欠拟合倾向,采取相应措施加以解决。

2. 度量泛化性能的方法

2.1. 错误率和精度

错误率(Error Rate)是指分类错误的样本数量占样本总数的比例。它直观地反映了模型预测出错的频率。

计算公式:Error Rate=错误样本数总样本数×100Error Rate=错误样本数总样本数×100

假设在 100 个测试样本中,模型错误分类了 10 个样本,那么错误率为 10/100 = 0.1

精度(Accuracy)是指分类正确的样本数量占样本总数的比例,与错误率相对应,反映了模型预测正确的概率。

计算公式:Accuracy=1−Error RateAccuracy=1−Error Rate

在上述 100 个测试样本中,模型正确分类了 90 个样本,精度为 90/100 = 0.9

错误率精度是分类问题的重要指标,它们能够快速给出模型整体的错误情况和正确率。

它们适用于各类别样本分布均衡的情况。

sckit-learn库中有对应的错误率和精度的计算函数,直接使用即可:

from sklearn.datasets import make_classificationfrom sklearn.model_selection import train_test_splitfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.metrics import accuracy_score
# 生成一个二分类数据集X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=42)
# 划分训练集和测试集X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=42)
# 训练一个决策树分类器clf = DecisionTreeClassifier(random_state=42)clf.fit(X_train, y_train)
# 获取预测结果y_pred = clf.predict(X_test)y_proba = clf.predict_proba(X_test)[:, 1]
# 计算错误率,精度error_rate = 1 - accuracy_score(y_test, y_pred)accuracy = accuracy_score(y_test, y_pred)
print(f"错误率: {error_rate:.2f}")print(f"精度: {accuracy:.2f}")
# 输出结果:'''错误率: 0.14精度: 0.86'''
复制代码

2.2. 查准率,查全率和 F1

查准率(Precision)关注的是模型预测为正类的样本中,实际真正为正类的比例,它强调预测结果的可靠性

计算公式:Precision=TPTP+FPPrecision=TPTP+FP

查全率(Recall)衡量的是实际正类样本中,被模型正确预测为正类的比例,它关注的是模型对正类样本的覆盖能力

计算公式:Recall=TPTP+FNRecall=TPTP+FN

F1 分数查准率查全率的调和平均数,综合考虑了两者的关系,提供了一个平衡的指标。

计算公式:F1=2×Precision×RecallPrecision+RecallF1=2×Precision×RecallPrecision+Recall

假设在某个二分类问题中,模型预测出 50 个正例,其中 40 个是真正的正例,实际正例总数为 60 个。

那么,

  • 查准率 = 40 / 50 = 0.8

  • 查全率 = 40 / 60 ≈ 0.6667

  • F1 分数 = 2 * (0.8 * 0.6667) / (0.8 + 0.6667) ≈ 0.7273

在处理不平衡数据集或对正类样本的预测准确性有特殊要求的任务中,查准率查全率和** F1 分数**能更全面地评估模型性能。

例如在医疗诊断中,高查全率意味着尽可能多地检测出患病个体,而高查准率则确保被诊断为患病的个体确实是真正的患者。

这三种指标在sckit-learn库中也有对应的方法:

from sklearn.metrics import (    precision_score,    recall_score,    f1_score,)
# 计算查准率,查全率和F1precision = precision_score(y_test, y_pred)recall = recall_score(y_test, y_pred)f1 = f1_score(y_test, y_pred)
print(f"查准率: {precision:.2f}")print(f"查全率: {recall:.2f}")print(f"F1 分数: {f1:.2f}")
# 运行结果:'''查准率: 0.86查全率: 0.86F1 分数: 0.86'''
复制代码

2.3. ROC 和 AUC

ROC 曲线Receiver Operating Characteristic Curve):以真正例率(TPR)为横轴,假正例率(FPR)为纵轴绘制的曲线。

它反映了模型在不同阈值下的真正例率和假正例率之间的权衡关系。

其中,

  • 真正例率(TPR):TPR = 真正例数 / (真正例数 + 假反例数)

  • 假正例率(FPR):FPR = 假正例数 / (假正例数 + 真反例数)

AUC 曲线Area Under ROC Curve):ROC曲线下的面积,用于衡量模型区分正负样本的能力。

AUC值越大,表示模型的区分能力越强。

ROC 和 AUC 适用于评估二分类模型的性能,尤其在需要比较不同模型对正负样本的区分能力时非常有效。

它们能够全面地反映模型在不同阈值下的综合表现,而不受阈值选择的影响。

绘制ROC曲线的代码如下,模型的训练过程和上面的示例类似,这里不再重复:

import matplotlib.pyplot as pltfrom sklearn.metrics import (    roc_auc_score,    roc_curve,)
plt.rcParams["font.sans-serif"] = ["SimHei"] # 设置字体plt.rcParams["axes.unicode_minus"] = False

# 计算ROC AUCroc_auc = roc_auc_score(y_test, y_proba)
# 绘制ROC曲线fpr, tpr, thresholds = roc_curve(y_test, y_proba)plt.figure()plt.plot(fpr, tpr, color="darkorange", lw=2, label=f"ROC curve (area = {roc_auc:.2f})")plt.plot([0, 1], [0, 1], color="navy", lw=2, linestyle="--")plt.xlim([0.0, 1.0])plt.ylim([0.0, 1.05])plt.xlabel("假正例率(FPR)")plt.ylabel("真正例率(TPR)")plt.title("ROC 曲线")plt.legend(loc="lower right")plt.show()
复制代码



2.4. 代价曲线

代价曲线考虑了不同分类错误所造成的实际损失(代价),通过绘制不同阈值下的总代价变化情况,帮助选择最优的分类阈值,使模型在实际应用中的损失最小。

它是对ROC曲线的一种扩展,考虑了不同错误分类的代价。

通过计算ROC曲线上每个点对应的期望总体代价,并在代价平面上绘制线段,取所有线段的下界围成的面积即为代价曲线

代价曲线的绘制方法稍微复杂一些,下面的的代码展示了不同ccp_alpha值对训练集和测试集错误率的影响,以及节点数量的变化。

# 演示代价复杂度剪枝path = clf.cost_complexity_pruning_path(X_train, y_train)ccp_alphas, impurities = path.ccp_alphas, path.impurities
clfs = []for ccp_alpha in ccp_alphas: clf = DecisionTreeClassifier(random_state=0, ccp_alpha=ccp_alpha) clf.fit(X_train, y_train) clfs.append(clf)
node_counts = [clf.tree_.node_count for clf in clfs]depth = [clf.tree_.max_depth for clf in clfs]
train_errors = [1 - clf.score(X_train, y_train) for clf in clfs]test_errors = [1 - clf.score(X_test, y_test) for clf in clfs]
plt.figure(figsize=(12, 6))plt.subplot(121)plt.plot(ccp_alphas, train_errors, marker="o", drawstyle="steps-post", label="train")plt.plot(ccp_alphas, test_errors, marker="o", drawstyle="steps-post", label="test")plt.xlabel("有效 alpha")plt.ylabel("错误率")plt.title("错误率 vs alpha")plt.legend()
plt.subplot(122)plt.plot( ccp_alphas, node_counts, marker="o", drawstyle="steps-post", label="number of nodes")plt.xlabel("有效 alpha")plt.ylabel("节点数")plt.title("节点数 vs alpha")plt.legend()
plt.tight_layout()plt.show()
复制代码



3. 度量方法之间的比较

以上各个度量方法有各自的优缺点和使用场景,整理如下表,使用时请根据具体情况来选择。

4. 总结

模型的泛化性能度量是机器学习流程中不可或缺的一环。

通过合理选择和运用不同的度量方法,我们能够全面、客观地评估模型在未知数据上的表现,为模型的优化和实际应用提供坚实的依据。

在实际项目中,应根据数据特点、业务需求以及模型类型等因素,灵活选择合适的度量指标,充分发挥各指标的优势,确保模型在复杂多变的现实场景中稳定、高效地运行。

行业拓展

分享一个面向研发人群使用的前后端分离的低代码软件——JNPF

基于 Java Boot/.Net Core 双引擎,它适配国产化,支持主流数据库和操作系统,提供五十几种高频预制组件,内置了常用的后台管理系统使用场景和实用模版,通过简单的拖拉拽操作,开发者能够高效完成软件开发,提高开发效率,减少代码编写工作。

JNPF 基于 SpringBoot+Vue.js,提供了一个适合所有水平用户的低代码学习平台,无论是有经验的开发者还是编程新手,都可以在这里找到适合自己的学习路径。

此外,JNPF 支持全源码交付,完全支持根据公司、项目需求、业务需求进行二次改造开发或内网部署,具备多角色门户、登录认证、组织管理、角色授权、表单设计、流程设计、页面配置、报表设计、门户配置、代码生成工具等开箱即用的在线服务。

用户头像

摸个鱼,顺便发点有用的东西 2023-06-19 加入

互联网某厂人(重生版)

评论

发布
暂无评论
模型的泛化性能度量:方法、比较与实现_秃头小帅oi_InfoQ写作社区