查看全课大纲(第 98 / 101 节)
  1. 1.数据分析基本概念
  2. 2.学习数据分析的一般路线
  3. 3.数据分析的流程
  4. 4.数据类型
  5. 5.环境部署(1)
  6. 6.环境部署(2)
  7. 7.课程介绍
  8. 8.TXT文件操作
  9. 9.JSON文件操作
  10. 10.CSV文件操作
  11. 11.Excel文件操作
  12. 12.数据库及SQL常用语法
  13. 13.数据库基本操作
  14. 14.数据库多表连接
  15. 15.实战:欧洲职业足球数据库分析
  16. 16.爬虫简介
  17. 17.URL管理模块
  18. 18.网页下载模块
  19. 19.网页解析模块(1)
  20. 20.网页解析模块(2)
  21. 21.Scrapy简介
  22. 22.Scrapy使用步骤(1)
  23. 23.Scrapy使用步骤(2)
  24. 24.Scrapy使用步骤(3)
  25. 25.Scrapy使用步骤(4)
  26. 26.实战:获取国内城市空气质量指数数据
  27. 27.NumPy和SciPy介绍
  28. 28.多维数组
  29. 29.多维数组操作
  30. 30.NumPy的常用方法
  31. 31.向量化介绍
  32. 32.向量化及通用函数
  33. 33.实战:2016美国大选分析
  34. 34.数据结构-Series
  35. 35.数据结构-DataFrame
  36. 36.数据结构-Index
  37. 37.Series的索引操作
  38. 38.DataFrame的索引操作
  39. 39.索引操作总结
  40. 40.运算与对齐
  41. 41.函数应用操作(1) -- map
  42. 42.函数应用操作 (2) -- apply applymap
  43. 43.文件读写操作
  44. 44.排序操作
  45. 45.数据清洗--处理缺失数据
  46. 46.数据清洗--处理重复数据
  47. 47.数据清洗--替换数据
  48. 48.常用统计方法(1) -- describe quantile
  49. 49.常用统计方法(2) -- sum mean median count
  50. 50.常用统计方法(3) -- max min idxmax idxmin
  51. 51.常用统计方法(4) -- mad var std cumsum
  52. 52.实战:全球食品数据分析
  53. 53.层级索引
  54. 54.分组与聚合介绍
  55. 55.分组操作(1) -- GroupBy对象及常用聚合操作
  56. 56.分组操作(2) -- 自定义分组及聚合操作
  57. 57.透视表介绍
  58. 58.透视表操作
  59. 59.数据规整(1) -- 数据合并concat
  60. 60.数据规整(2) -- 数据连接merge
  61. 61.数据重构(3) -- 数据重构stack unstack
  62. 62.实战:互联网电影资料库分析
  63. 63.探索性数据分析EDA介绍
  64. 64.EDA的目的
  65. 65.EDA常用工具
  66. 66.Matplotlib绘图基本介绍
  67. 67.Matplotlib画布
  68. 68.散点图和柱状图的绘制
  69. 69.直方图的绘制
  70. 70.矩阵绘图
  71. 71.子图的使用
  72. 72.Matplotlib颜色、标记、线型
  73. 73.Matplotlib坐标刻度、标签、图例、标题
  74. 74.Seaborn介绍
  75. 75.数据集分布可视化(1) -- 单变量分布、双变量分布
  76. 76.数据集分布可视化(2) -- 变量关系可视化
  77. 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
  78. 78.交互式数据可视化工具Bokeh介绍
  79. 79.Bokeh绘制散点图、柱状图、盒子图、弦图
  80. 80.Bokeh绘制常用图形元素
  81. 81.3D绘图 -- mplot3d
  82. 82.3D曲线可视化
  83. 83.3D散点图可视化
  84. 84.3D柱状图可视化
  85. 85.Pandas绘图
  86. 86.实战:Lending Club借贷数据探索性分析及可视化
  87. 87.机器学习介绍及应用场景
  88. 88.机器学习建模介绍 (1) -- 分类
  89. 89.机器学习建模介绍 (2) -- 回归
  90. 90.机器学习建模介绍 (3) -- 聚类
  91. 91.机器学习分类
  92. 92.机器学习工具scikit-learn
  93. 93.使用scikit-learn的流程
  94. 94.数据集准备及划分
  95. 95.模型选择
  96. 96.数据预处理及特征工程
  97. 97.过拟合与欠拟合
  98. 98.模型调参介绍
  99. 99.模型调参方法
  100. 100.模型测试及评价
  101. 101.实战:通过移动设备行为数据预测性别和年龄

模型调参介绍

约 10 分钟

📺 正在播放小象学院官方高清录播(支持倍速与清晰度调节)

模型调参与交叉验证

小象实战讲义 · Python数据分析实战

在上一节中,我们学习了如何划分数据集、训练模型并进行评估。然而,一个关键问题尚未解决:如何为模型选择最优的参数配置?本节将深入探讨机器学习中的参数类型,并重点介绍通过交叉验证(Cross Validation)这一科学方法进行模型调参的核心流程。学完本节,你将能够区分模型参数与超参数,并掌握使用交叉验证来寻找最优超参数的实际操作方法。

💡 核心导读

  • 参数的两大类型:理解模型自身参数(通过学习获得)与超参数(需手动设定)的根本区别。
  • 调参的两种途径:依靠领域经验与依靠系统性实验。
  • 交叉验证的原理:掌握将训练集进一步划分为训练子集与验证集,并通过多轮“交叉”实验来评估不同参数性能的核心思想。
  • 五折交叉验证示例:通过一个具体的KNN模型例子,直观理解交叉验证的执行步骤与结果分析。
  • 最终模型的训练:明确交叉验证选定最优参数后,仍需在整个训练集上重新训练最终模型的重要性。

一、 机器学习中的两类参数

在机器学习中,模型的“参数”并非单一概念,通常可以分为两种类型:

  1. 模型自身参数 这类参数是模型内部固有的,不能通过人为直接指定,必须通过算法在训练数据上学习得到。例如:

    • 逻辑回归模型中的各个特征权重(weights)和偏置项(bias)。
    • 神经网络中连接各神经元的权重。 我们通常所说的“训练模型”,其核心目标就是寻找一组最优的模型自身参数,使得模型在训练数据上的预测误差最小。因此,这类参数是模型自动优化的结果,我们无法也不应直接干预。
  2. 超参数 这类参数是凌驾于模型自身参数之上的,用于控制模型整体框架、结构或训练过程的设置。它们通常在模型开始学习之前就需要由人工指定。例如:

    • k近邻(kNN)算法中的邻居数量 k。
    • 支持向量机(SVM)中的正则化系数 C。 由于超参数需要手动设置,其选择具有很大的灵活性,同时也直接影响了模型的最终性能。我们常说的“模型调参”,调的就是超参数。
# 代码示例:展示kNN和逻辑回归模型的超参数设置
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression

# kNN的超参数:n_neighbors (k值)
knn_model = KNeighborsClassifier(n_neighbors=5) # 这里设置超参数 k=5

# 逻辑回归的超参数:C (正则化强度), max_iter (最大迭代次数)
lr_model = LogisticRegression(C=1.0, max_iter=1000) # 设置超参数 C=1.0, max_iter=1000

print("kNN模型类型:", type(knn_model).__name__)
print("逻辑回归模型类型:", type(lr_model).__name__)
# 注意:此时模型尚未训练,其自身参数(如权重)还不存在。
kNN模型类型: KNeighborsClassifier
逻辑回归模型类型: LogisticRegression

二、 如何寻找最优超参数?

既然超参数需要手动设置,我们该如何找到最优值呢?主要有两种途径:

  • 依靠经验:对于特定领域或熟悉的数据集,从业者可以根据先验知识选择一组可能表现良好的超参数。
  • 依靠实验:对于缺乏经验或面对新问题时,更可靠的方法是进行系统性的实验,通过对比不同超参数下模型的性能来选择最优者。交叉验证就是其中最常用、最科学的实验方法。

最简单的实验想法是:尝试超参数的不同取值(例如kNN中k=1,3,5…),在同一个数据集上分别训练模型并评估性能,选择性能最好的那个取值。但这里存在一个关键问题:评估性能时应该使用哪部分数据?

如果使用训练数据来评估,模型会倾向于在见过的数据上表现过好(过拟合),无法反映其泛化到新数据的能力。如果使用预留的测试数据来评估并以此选择参数,那么测试集就被“污染”了,它不再能公正地评估模型的最终性能。

为了解决这个问题,我们需要引入验证集的概念。

三、 验证集与交叉验证

回顾之前的数据集划分:我们将所有数据分为训练集和测试集。测试集被严格隔离,用于最终评估模型。

现在,为了调参,我们从训练集中再划分出一部分数据,称为验证集。调整超参数的过程将在验证集上进行评估,而测试集始终保持“纯洁”,留到最后使用。

那么,如何划分验证集呢?随机选取一小部分? 随机选取可能无法很好地代表整个训练集的分布,评估结果可能不稳定。

交叉验证提供了一种更稳健的解决方案。其核心思想是:将训练集均匀分成K份(称为K折),然后进行K轮实验。在每一轮中,轮流将其中一份作为验证集,剩余的K-1份作为训练集。这样,每一份数据都恰好有一次作为验证集,最终将K轮实验的性能评估结果(如准确率)取平均值,作为该组超参数性能的最终估计。

示意图:5折交叉验证流程 (以kNN的k=1和k=5为例)
训练集被分为5等份: [块1] [块2] [块3] [块4] [块5]

第1轮实验: 训练集=[块1,块2,块3,块4], 验证集=[块5]
            -> 训练k=1模型,在[块5]上验证,得准确率 A1_k1
            -> 训练k=5模型,在[块5]上验证,得准确率 A1_k5

第2轮实验: 训练集=[块1,块2,块3,块5], 验证集=[块4]
            -> 训练k=1模型,在[块4]上验证,得准确率 A2_k1
            -> 训练k=5模型,在[块4]上验证,得准确率 A2_k5

第3轮实验: 训练集=[块1,块2,块4,块5], 验证集=[块3]
            -> ... 得 A3_k1, A3_k5
第4轮实验: 训练集=[块1,块3,块4,块5], 验证集=[块2]
            -> ... 得 A4_k1, A4_k5
第5轮实验: 训练集=[块2,块3,块4,块5], 验证集=[块1]
            -> ... 得 A5_k1, A5_k5

最终评估:
k=1模型的平均准确率 = (A1_k1 + A2_k1 + A3_k1 + A4_k1 + A5_k1) / 5
k=5模型的平均准确率 = (A1_k5 + A2_k5 + A3_k5 + A4_k5 + A5_k5) / 5
比较两者,平均准确率更高的k值即为更优的超参数选择。

K值(折数)的选择:常用的有5折或10折。数据量很大时,折数可以少一些(如3折、5折)以减少计算时间;数据量较小时,折数可以多一些(如10折)以更充分地利用数据。

四、 实战示例:使用交叉验证为kNN调参

假设我们通过五折交叉验证比较k=1和k=5的kNN模型,得到了如下模拟结果:

# 示例:模拟五折交叉验证的结果计算与比较
import numpy as np

# 模拟五折交叉验证中,k=1和k=5模型在每一折验证集上的准确率(%)
accuracy_k1_per_fold = [93, 90, 91, 95, 94]  # k=1时各折准确率
accuracy_k5_per_fold = [92, 88, 89, 90, 92]  # k=5时各折准确率

# 计算平均准确率
mean_accuracy_k1 = np.mean(accuracy_k1_per_fold)
mean_accuracy_k5 = np.mean(accuracy_k5_per_fold)

print(f"k=1时,模型在验证集上的平均准确率: {mean_accuracy_k1:.1f}%")
print(f"k=5时,模型在验证集上的平均准确率: {mean_accuracy_k5:.1f}%")
print("-" * 50)
if mean_accuracy_k1 > mean_accuracy_k5:
    print("结论:最优超参数 k = 1")
else:
    print("结论:最优超参数 k = 5")
k=1时,模型在验证集上的平均准确率: 92.6%
k=5时,模型在验证集上的平均准确率: 90.2%
--------------------------------------------------
结论:最优超参数 k = 1

通过交叉验证,我们得出k=1是更优的超参数选择。

五、 重要步骤:训练最终模型

一个常见的误区是:通过交叉验证得到最优超参数(如k=1)后,直接使用在某一折(例如第1轮)上训练的模型作为最终模型。

这是不正确的。因为交叉验证中的每一个模型都只使用了训练集的4/5(五折情况下)进行训练,并非全部训练数据。

正确的步骤是:

  1. 使用交叉验证确定最优超参数(如k=1)。
  2. 使用最优超参数,在整个原始训练集(即划分验证集之前的所有训练数据)上重新训练一个全新的模型。这个模型才是我们最终要部署或用于预测的模型。
  3. 最后,使用完全独立的测试集对这个最终模型进行一次性评估,得到其对未知数据泛化能力的无偏估计。
# 示例:使用最优k在整个训练集上训练最终模型,并在测试集评估
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score

# 1. 构造模拟的完整训练集(此处用小规模数据演示)
X_train_full = np.array([[1, 1], [2, 2], [3, 3], [4, 4], [5, 5],
                         [11, 11], [12, 12], [13, 13], [14, 14], [15, 15]])
y_train_full = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1]) # 前5个类0,后5个类1

# 2. 构造模拟的独立测试集
X_test = np.array([[2.5, 2.5], [12.5, 12.5], [5, 5], [15, 15]])
y_test = np.array([0, 1, 0, 1])

# 3. 假设通过交叉验证我们已确定最优 k=1
best_k = 1

# 4. 在整个训练集上训练最终模型
final_model = KNeighborsClassifier(n_neighbors=best_k)
final_model.fit(X_train_full, y_train_full)

# 5. 在测试集上评估最终模型
y_pred = final_model.predict(X_test)
test_accuracy = accuracy_score(y_test, y_pred)

print(f"使用最优超参数 k={best_k} 在整个训练集上训练最终模型。")
print(f"在独立测试集上的准确率为: {test_accuracy:.2%}")
使用最优超参数 k=1 在整个训练集上训练最终模型。
在独立测试集上的准确率为: 100.00%

📝 动手练一练

  1. 概念辨析:假设你训练了一个线性回归模型,模型学到的斜率(slope)和截距(intercept)属于哪类参数?你在创建模型时设置的“是否对数据进行标准化”这个选项,又属于哪类参数?
👉 点击查看参考答案
  • 斜率与截距:属于模型自身参数。它们是通过最小化损失函数,在训练数据上学习得到的,不能直接设定。
  • 是否标准化:属于超参数。它控制了数据预处理的一个步骤,是在模型训练开始前就需要人为设定的选项,会影响模型的学习过程与最终性能。
  1. 代码实践:在上一节的“动手练一练”中,你尝试了不同的k值。请修改下面的代码,使用sklearn.model_selection中的cross_val_score函数(默认使用分层k折交叉验证),对k=1,2,3,4,5这五个候选值进行评估,并输出它们的平均交叉验证准确率。哪个k值表现最好?(提示:cross_val_score函数返回每一折的得分列表,需要对其取平均值)
👉 点击查看参考答案
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score

# 使用与之前一致的模拟训练集
X_train_simulated = np.array([[1, 1], [2, 2], [3, 3], [4, 4], [5, 5],
                               [11, 11], [12, 12], [13, 13], [14, 14], [15, 15]])
y_train_simulated = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1])

k_candidates = [1, 2, 3, 4, 5]
print("五折交叉验证平均准确率(k=1~5):")
best_k = None
best_score = 0
for k in k_candidates:
    knn = KNeighborsClassifier(n_neighbors=k)
    # cv=5 表示5折交叉验证
    scores = cross_val_score(knn, X_train_simulated, y_train_simulated, cv=5, scoring='accuracy')
    mean_accuracy = scores.mean()
    print(f"  k = {k}: 平均准确率 = {mean_accuracy:.4f}")
    if mean_accuracy > best_score:
        best_score = mean_accuracy
        best_k = k

print(f"\n根据交叉验证,最优 k = {best_k}, 其平均准确率为 {best_score:.4f}")

运行后,你将看到类似以下的输出。由于数据完全对称且可分,k=1通常能获得最高准确率。实际结果以运行为准。

五折交叉验证平均准确率(k=1~5):
  k = 1: 平均准确率 = 1.0000
  k = 2: 平均准确率 = 1.0000
  k = 3: 平均准确率 = 1.0000
  k = 4: 平均准确率 = 1.0000
  k = 5: 平均准确率 = 1.0000

根据交叉验证,最优 k = 1, 其平均准确率为 1.0000

注意:本例中k=1至k=5的交叉验证平均准确率均为1.0000(这份示例数据的类别边界非常清晰,k取哪个值都能全对),任选其一皆可;代码按遍历顺序输出并保留k=1作为最优值。

本章小结

本节我们揭开了模型调参的神秘面纱。关键在于区分模型自身参数与超参数,并理解调参的核心目标是寻找最优超参数。交叉验证作为一项重要的实验技术,通过将训练集多次划分并轮流作为验证集,为我们提供了评估超参数性能的稳健方法。记住,交叉验证完成后,务必使用最优超参数在整个训练集上重新训练,才能得到面向最终应用的模型。

📋 行动清单

  • 清晰复述模型自身参数与超参数的区别,并能各举一例。
  • 在白板上画出5折交叉验证的数据流转示意图,并向同伴解释其如何避免评估偏差。
  • 在Python中,使用sklearn.model_selection.cross_val_score函数,对你熟悉的某个数据集(或模拟数据)上的分类器进行交叉验证调参练习。

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 本节课件:模型调参介绍
    PDF · 494KB
    下载
  • 全套课件打包(第1-5章)
    ZIP · 12.8MB
    下载
  • 全套课件打包(第6-8章)
    ZIP · 15MB
    下载
  • 实战数据集:AppleStore 应用商城分析
    ZIP · 329KB
    下载
  • 实战数据集:女性服装电商分析
    ZIP · 2.8MB
    下载
  • Python 数据分析环境搭建指南
    PDF · 2MB
    下载
  • Scrapy 安装教程
    PDF · 12.7MB
    下载
  • 附加实战项目:AppleStore 应用商城数据分析
    ZIP · 0.3MB · ipynb + CSV 数据
    下载
  • 附加实战项目:银行电话营销数据分析
    ZIP · 0.4MB · ipynb + CSV 数据
    下载
  • 附加实战项目:女性服装电商评论数据分析
    ZIP · 2.7MB · ipynb + CSV 数据
    下载
  • 附加实战项目:美国化学学会杂志数据分析
    ZIP · 34.2MB · ipynb + SQLite 数据库
    下载