1. 训练集 (Training Set)
训练集是用于训练模型的数据集。模型通过训练集来学习数据的特征模式,从而调整模型的参数(例如神经网络的权重)。
2. 测试集 (Test Set)
测试集是用于最终评估模型性能的数据集。它是完全独立于训练过程的数据集,模型不会在训练过程中接触到测试集。测试集的主要目的是衡量模型的泛化能力,即模型在未见过的数据上的表现如何。
那么验证集是用来干什么的呢?我们都知道一个模型会有很多可以调节的参数,例如,k-NN分类器需要设定k值,那么选择哪个k值最合适的呢?我们可以选择不同的距离函数,比如L1范数和L2范数等,那么选哪个好?还有不少选择我们甚至连考虑都没有考虑到(比如:点积)。所有这些选择,被称为超参数(hyperparameter)。
一般说来,这些超参数具体怎么设置或取值并不是显而易见的。思路就是多尝试一下,看哪个参数表现好就用哪个。
特别注意:决不能使用测试集来进行调优。当你在设计机器学习算法的时候,应该把测试集看做非常珍贵的资源,不到最后一步,绝不使用它。如果你使用测试集来调优,而且算法看起来效果不错,那么真正的危险在于:算法实际部署后,性能可能会远低于预期。这种情况,称之为算法对测试集过拟合。
真正的思路是:从训练集中取出一部分数据用来调优,我们称之为验证集(validation set)。
3. 验证集 (Validation Set)
验证集是在模型训练的过程中用于调参和评估的一个独立数据集。验证集的主要目的是在训练期间监控模型的表现,帮助选择超参数并防止模型过拟合。验证集的数据并不会被模型用于参数更新。
应用:
- 超参数调整:验证集帮助选择模型的最佳超参数(例如学习率、正则化系数、网络深度等)。
- 防止过拟合:通过验证集的表现,可以判断模型是否在训练集中过拟合。如果在验证集上的误差持续增加而在训练集上减少,则可能发生过拟合。
- 早停 (Early Stopping):如果发现模型在验证集上的性能不再提升,可以在训练过程中提前终止模型的训练。
示例:
- 在神经网络训练中,可以通过验证集来选择最佳的学习率或正则化系数,观察模型在验证集上的损失曲线是否平稳,以判断模型是否过拟合。
交叉验证
简单交叉验证:把训练集分成训练集和验证集。使用验证集来对所有超参数调优。最后只在测试集上跑一次并报告结果。但是这种交叉验证会可能会出现一种情况:一类标签的图像只在验证集而训练集没有,或只在训练集,验证集没有。k折交叉验证解决了这种情况。
k折交叉验证:是一种常用的模型评估方法,用于评估机器学习模型的表现,尤其在数据量有限时,通过反复训练和验证模型来提供一个稳定的性能估计。
基本步骤:
-
数据划分:
- 首先将数据集平均划分为
K
份(也叫K
个 "折" 或 "分块"),每一份的大小尽量相等。
- 首先将数据集平均划分为
-
模型训练与验证:
- 对于每一次训练:
- 选取其中的
K-1
份数据作为训练集。 - 选取剩余的 1 份作为验证集(这一份称为 "验证折")。
- 用训练集训练模型,用验证集评估模型性能(例如计算准确率、F1 分数等)。
- 选取其中的
- 重复以上过程
K
次,每次选取不同的验证集。
- 对于每一次训练:
-
性能评估:
- 在完成所有的
K
次验证后,取K
次评估结果的平均值作为最终模型的性能评估指标。
- 在完成所有的
K折交叉验证代码示例(包含数据分割)
我们将使用 Scikit-learn 提供的 KFold
进行 K折交叉验证,并展示如何在每个折中进行数据集的分割、训练和评估。
步骤:
- 将数据集分为
K
份。 - 每次选取
K-1
份数据进行训练,剩下的 1 份数据作为验证集。 - 计算每一折的模型性能,最后取所有折的平均值作为最终结果。
# 导入所需的库
import numpy as np
from sklearn.model_selection import KFold
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# 加载示例数据集 (Iris数据集)
data = load_iris()
X = data.data # 特征
y = data.target # 标签
# 定义KFold交叉验证,设置K=5
kf = KFold(n_splits=5, shuffle=True, random_state=42)
# 用于存储每一折的准确率
accuracies = []
# 对每个折进行训练和验证
for train_index, val_index in kf.split(X):
# 使用train_index和val_index对数据进行分割
X_train, X_val = X[train_index], X[val_index] # 划分训练集和验证集
y_train, y_val = y[train_index], y[val_index] # 划分对应的标签
# 定义并训练逻辑回归模型
model = LogisticRegression(max_iter=200)
model.fit(X_train, y_train)
# 在验证集上进行预测
y_pred = model.predict(X_val)
# 计算准确率
accuracy = accuracy_score(y_val, y_pred)
# 保存每一折的准确率
accuracies.append(accuracy)
# 打印每一折的结果
print(f"折准确率: {accuracy:.4f}")
# 输出所有折的平均准确率
print(f"K折交叉验证的平均准确率: {np.mean(accuracies):.4f}")
代码说明:
-
数据加载:
- 使用
load_iris()
函数加载了 Iris 数据集,其中X
是特征,y
是标签。
- 使用
-
K折交叉验证对象
KFold
:KFold(n_splits=5)
:将数据集分为 5 份(K=5),每次选取 4 份作为训练集,1 份作为验证集。shuffle=True
:在分割数据集之前,先打乱数据以避免数据集有顺序性带来的偏差。random_state=42
:设置随机种子,以保证每次运行的分割结果一致。打乱数据是一个随机过程,如果每次运行程序时都重新打乱,划分的训练集和验证集可能会不同,这会导致模型的训练和评估结果也不同。通过设置random_state
,我们可以确保每次运行代码时,打乱后的数据划分结果保持一致,这使得模型训练和评估的结果具有可重复性。这里的42
是一个常用的随机种子值,你可以将其替换为其他任何整数。
-
数据分割:
kf.split(X)
:根据划分策略生成每一折的训练集索引 (train_index
) 和验证集索引 (val_index
)。- 使用这些索引从原始数据
X
和标签y
中提取训练集和验证集。
-
模型训练:
- 这里使用的是
LogisticRegression
逻辑回归模型,但你可以替换为任何其他机器学习模型。 model.fit(X_train, y_train)
:在训练集上训练模型。
- 这里使用的是
-
模型验证:
model.predict(X_val)
:在验证集上预测结果。accuracy_score(y_val, y_pred)
:通过对比真实标签和预测结果,计算验证集上的准确率。
-
结果评估:
accuracies
:保存每一折的准确率。- 最后输出所有折的平均准确率,作为模型性能的最终评估。