在我们前面的数据科学系列文章中,我们通过两个案例研究(回归和分类)对数据分析和建模进行了详细探讨。在这些基础上,本系列将深入探讨机器学习中的各种技术和方法,旨在帮助读者掌握更复杂的机器学习模型及其应用。
本系列的第一篇文章将重点介绍交叉验证,这是一种用于模型评估和优化的重要技术。通过交叉验证,我们可以更准确地评估模型的性能,并有效避免过拟合和欠拟合问题。
交叉验证概述
交叉验证是一种将数据集分成多个子集的方法,以便对模型进行多次训练和测试,从而获得更可靠的性能评估。通过这种方法,我们可以更好地了解模型在不同数据分布下的表现,减少由于数据分割带来的偏差。
数据形状要求
在使用 Scikit-Learn 之前,需要了解数据形状的基本要求。大多数算法需要两个输入,即 X 和 y:
- X:特征矩阵,形状为 [n_samples, n_features]
- y:目标/标签向量,形状为 [n_samples,] 或 [n_samples, n_targets](取决于算法是否支持多标签)
注意:
- 如果 X 只有一个特征,形状必须是 [n_samples, 1] 而不是 [n_samples,]。
- Scikit-Learn 支持 numpy 和 pandas 数据,只要形状正确。例如,如果使用 pandas,X 可以是 DataFrame,y 可以是 Series 或 DataFrame。
Scikit-Learn API 基础用法
使用 Scikit-Learn API 的常见步骤如下:
- 导入模型类
- 通过实例化该类选择模型的超参数
- 将数据安排成特征矩阵和目标向量
- 使用
fit()
方法将模型拟合到数据上 - 使用
predict()
方法进行推断
实践操作
首先,我们加载一个回归数据集,并进行预处理。
import numpy as np
from sklearn.datasets import load_diabetes
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
diabetes = load_diabetes()
X = diabetes.data
y = diabetes.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
导入模型类
from sklearn.linear_model import LinearRegression
选择模型超参数
对于线性回归示例,我们可以实例化 LinearRegression
类,并指定我们希望通过 fit_intercept
超参数来拟合截距:
model = LinearRegression(fit_intercept=True)
model
数据安排
确保特征矩阵和目标向量的形状正确:
assert len(X_train.shape) == 2 and len(X_test.shape) == 2 # 确保特征矩阵形状正确
assert len(y_train.shape) == 1 and len(y_test.shape) == 1 # 确保目标向量形状正确
拟合模型
model.fit(X_train, y_train) # 使用训练集拟合模型
进行预测
y_hat = model.predict(X_test) # 使用测试集进行预测
计算均方误差
from sklearn.metrics import mean_squared_error
mean_squared_error(y_test, y_hat)
交叉验证的应用
仅使用训练集和测试集进行模型评估并不可靠,因为这可能会导致模型对数据分割方式的偶然性过于敏感。交叉验证通过多次分割数据并重复训练和测试,提供了更可靠的模型评估方法。
K折交叉验证
K折交叉验证是一种常见的交叉验证方法,将数据分成K个子集,每次使用其中一个子集进行测试,其余子集用于训练。
from sklearn.model_selection import cross_val_score
cross_val_score(model, X_train, y_train, cv=5) # 5折交叉验证
ShuffleSplit
ShuffleSplit 是 KFold 的一种变体,允许更精细地控制迭代次数和每次分割的样本比例。
from sklearn.model_selection import ShuffleSplit
shuffle_cv = ShuffleSplit(n_splits=5, test_size=0.3, random_state=0)
cross_val_score(model, X_train, y_train, cv=shuffle_cv)
分层K折交叉验证
分层K折交叉验证确保每个子集中各类样本的比例与原始数据集中相同,适用于分类问题。
from sklearn.model_selection import StratifiedKFold
sk_cv = StratifiedKFold(n_splits=3)
cross_val_score(model, X_train, y_train, cv=sk_cv)
Group KFold
Group KFold 确保同一组的数据不会同时出现在训练集和测试集中,适用于需要避免组数据泄露的情况。
from sklearn.model_selection import GroupKFold
gkf = GroupKFold(n_splits=5)
groups = np.random.randint(0, 5, size=y_train.shape[0])
cross_val_score(model, X_train, y_train, cv=gkf, groups=groups)
网格搜索与嵌套交叉验证
网格搜索
网格搜索通过自动尝试多种超参数组合,找到模型的最佳配置。
from sklearn.model_selection import GridSearchCV
param_grid = {'fit_intercept': [True, False], 'positive': [True, False]}
grid = GridSearchCV(model, param_grid, cv=shuffle_cv, refit=True)
grid.fit(X_train, y_train)
grid.best_params_
嵌套交叉验证
嵌套交叉验证通过将交叉验证嵌套在另一个交叉验证中,进一步提高模型评估的稳定性和可靠性。
from sklearn.model_selection import KFold
inner_cv = KFold(n_splits=4, shuffle=True, random_state=1)
outer_cv = KFold(n_splits=4, shuffle=True, random_state=1)
inner_model = GridSearchCV(model, param_grid=param_grid, cv=inner_cv)
nested_score = cross_val_score(inner_model, X, y, scoring='neg_mean_squared_error', cv=outer_cv)
nested_score.mean()
如果你觉得这篇博文对你有帮助,请点赞、收藏、关注我,并且可以打赏支持我!
欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。
谢谢大家的支持!