交叉验证是一种统计技术,用于评估和验证机器学习模型的性能。它涉及将数据集划分为多个子集,然后迭代地使用它们来训练和验证模型。
了解交叉验证
在机器学习中,目标是创建一个可以对新数据和未见数据做出准确预测的模型。为实现这一目标,我们需要在代表我们尝试建模的人群的大型数据集上训练我们的模型。然而,简单地在单个数据集上训练模型可能会导致过度拟合,模型变得过于复杂且特定于训练数据,从而导致在新数据上表现不佳。
交叉验证通过评估模型在多个数据子集上的性能来帮助我们解决这个问题。该过程涉及将数据集随机分成k 份,其中 k 是用户选择的数字。然后,模型在 k-1 折上进行训练,并在剩余的折上进行验证。
此过程重复 k 次,每次折叠仅用于验证一次。对每次折叠的结果进行平均,以获得对模型性能的更可靠估计。
交叉验证的类型
有不同类型的交叉验证技术可用。最常见的是:
K折交叉验证
K 折交叉验证涉及将数据分成 k 个大小相等的子集或折。
然后在 k-1 次折叠上训练模型并在剩余的折叠上进行验证。此过程重复 k 次,每次折叠仅用于验证一次。下面是一个如何使用 scikit-learn 以简洁的方式执行 K 折交叉验证的示例:
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
# 加载鸢尾花数据集
iris = load_iris()
# 创建特征矩阵(X)和目标向量(y)
X = iris.data
y = iris.target
# 初始化逻辑回归模型
model = LogisticRegression()
# 执行 5 折交叉验证并存储准确度得分 scores
= cross_val_score(model, X, y, cv=5)
# 打印所有折叠的平均准确度得分
print("Mean accuracy: ", scores.mean())
# 输出:平均准确度:0.9733333333333334
在这段代码中,我们首先加载鸢尾花数据集并创建特征矩阵和目标向量。然后我们初始化逻辑回归模型。
然后我们可以使用cross_val_scorescikit-learn 中的函数来执行 5 折交叉验证。此函数将机器学习模型、特征矩阵、目标向量和用于交叉验证的折叠数 (cv=5) 作为输入。
然后,该函数将数据分成每个折叠的训练集和测试集,在训练数据上拟合模型,在测试数据上对其进行评估,并返回每个折叠的准确度分数。我们将这些分数存储在一个列表中,并打印所有折叠的平均准确度分数 0.9733。
这段代码简洁易懂,对于想要学习如何在 scikit-learn 中执行 K 折交叉验证的初学者来说是一个很好的选择。
分层 K 折交叉验证
分层 K 折交叉验证类似于 K 折交叉验证,但它确保每个折包含来自数据集中每个类的大致相同比例的样本。这对于不平衡数据集特别有用,其中某些类的样本很少。
from sklearn.model_selection import StratifiedKFold
# 定义具有 5 个分割的分层 K 折交叉验证
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# 定义逻辑回归模型
model = LogisticRegression()
# 遍历每个分割和
在 skf.split(X, y) 中拟合 train_index、test_index 的模型:
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
clf.fit(X_train, y_train )
print("准确度:", model.score(X_test, y_test))
# 输出:准确度:1.0
我们定义了一个StratifiedKFold具有 5 个拆分的对象,设置shuffle=True为随机混洗数据,并random_state=42具有可重复性。
我们还使用 定义了逻辑回归模型LogisticRegression()。
split()最后,我们使用对象的方法遍历每个拆分StratifiedKFold。score()对于每次拆分,我们将数据拆分为训练集和测试集,在训练集上拟合逻辑回归模型,并使用模型的方法在测试集上打印准确率分数。
此代码使用分层 K 折交叉验证在鸢尾花数据集上训练和测试逻辑回归模型,同时确保每个折包含每个目标类别的比例大致相同。
准确度得分为 1.0 表示该模型能够使用训练集中提供的特征对测试集中的所有样本进行正确分类。然而,需要注意的是,在现实场景中获得完美的准确度分数并不总是可能或可取的,还应考虑其他评估指标和技术。
留一法交叉验证
留一法交叉验证是 K 折交叉验证的特例,其中 k 等于数据集中的样本数。在这种技术中,模型在除用于验证的一个样本之外的所有样本上进行训练。对数据集中的每个样本重复此过程。
from sklearn.model_selection import LeaveOneOut
# 创建一个留一法交叉验证对象
loo = LeaveOneOut()
# 遍历每个折叠
for train_index, test_index in loo.split(X):
# 将数据拆分为训练集和测试集
X_train , X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
# 在训练数据上拟合模型 model.fit
(X_train, y_train)
# 在测试数据上测试模型
得分= model.score(X_test, y_test)
# 打印每次迭代的分数
print("Iteration:", train_index[0], "Score:", score)
# outuput: Iteration: 1 Score: 1.0
# 迭代:0 得分:0.0
# 迭代:0 得分:0.0
# 迭代:0 得分:1.0
此代码使用LeaveOneOut类将数据拆分为每个折叠的训练和测试集。然后它在训练数据上拟合模型并在测试数据上测试它,并打印每次迭代的分数。
逻辑回归模型的方法score返回模型在测试数据上的准确率。
对于每次迭代,输出包括两条信息:迭代次数(例如“Iteration: 1”)和模型在该迭代中的得分(例如“Score: 1.0”)。
该分数通常衡量模型在该特定迭代期间对数据的执行情况,分数越高表示性能越好。根据输出,该模型似乎在第一次迭代中表现完美(得分为 1.0),而在第二次和第三次迭代中表现不佳(得分为 0.0)。第四次迭代也获得了 1.0 的满分。
总的来说,很难从这些有限的信息中得出关于模型性能的任何结论,但输出表明模型在某些情况下可能过度拟合数据(在训练数据上表现良好但在新数据上表现不佳)。
交叉验证的优点
交叉验证有几个优点,包括:
- 与使用单个数据集进行训练和测试相比,它可以更准确地估计模型的性能。
- 它有助于识别过度拟合,从而更好地泛化模型。
- 它可用于比较不同的模型并为给定任务选择最佳模型。
交叉验证的缺点
交叉验证也有一些缺点,包括:
- 它的计算成本可能很高,尤其是对于大型数据集和复杂模型。
- 它对k 的选择很敏感,不同的值会导致不同的结果。
- 它假定数据是独立同分布的,但在某些情况下可能并非如此。
交叉验证的最佳实践
为了充分利用交叉验证,遵循一些最佳实践很重要,包括:
- 如果可能,请使用大型数据集来更准确地估计模型的性能。
- 使用合理的 k 值,例如 5 或 10,以平衡计算成本和估计的准确性。
- 如果数据包含不平衡的类,则对数据进行分层,以确保每个折叠包含每个类的代表性样本。
- 在将数据拆分成折叠之前将其打乱,以避免数据排序中的任何偏差。
- 对每个折叠使用相同的预处理步骤,以确保结果的一致性。
- 使用嵌套交叉验证为模型选择最佳超参数以避免过度拟合。
结论
交叉验证是一种用于评估和验证机器学习模型的强大技术。它有助于防止过度拟合并提供更准确的模型性能估计。通过遵循一些最佳实践,我们可以充分利用交叉验证并提高模型的质量。
常见问题
交叉验证的目的是什么?
交叉验证用于评估和验证机器学习模型的性能并防止过度拟合。
有多少种交叉验证?
有几种类型的交叉验证,包括 K 折交叉验证、分层 K 折交叉验证和留一法交叉验证。
交叉验证的优点是什么?
交叉验证提供了对模型性能更准确的估计,有助于识别过度拟合,并可用于比较不同的模型。
交叉验证的缺点是什么?
交叉验证可能计算量大,对 k 的选择敏感,并假设数据是独立且同分布的。
如何在 Python 中实现交叉验证?
可以使用 scikit-learn 库在 Python 中实现交叉验证,该库为此提供了多个类和函数。