终于把机器学习中的交叉验证搞懂了!!
交叉验证是机器学习中用于评估模型泛化能力的一种方法,用于衡量模型在训练集之外的新数据上的表现。今天给大家分享机器学习中的一个关键概念,交叉验证。
交叉验证是机器学习中用于评估模型泛化能力的一种方法,用于衡量模型在训练集之外的新数据上的表现。
它的核心思想是将数据集划分为多个子集,模型在不同的子集上交替进行训练和测试,从而减少模型在某一特定数据分割上的偏差。交叉验证能够有效地降低模型过拟合的风险,从而提高模型评估的稳定性和可靠性。
K 折交叉验证将数据集分成 K 个不重叠的子集(折),每次将其中一个子集(折)作为测试集,其余 K-1 个折作为训练集。
重复这个过程 K 次,每次用不同的折作为测试集,最终将 K 次测试的结果平均,以得到模型的总体性能。
优点
缺点
from sklearn.model_selection import KFold, cross_val_scorefrom sklearn.datasets import load_irisfrom sklearn.ensemble import RandomForestClassifier# 加载数据data = load_iris()X, y =>
留一交叉验证是 K 折交叉验证的极端形式,其中 K 等于样本总数 N。
每次选取一个样本作为测试集,其余 N-1 个样本作为训练集,重复该过程 N 次,最后计算平均误差。
优点
缺点
from sklearn.model_selection import LeaveOneOutfrom sklearn.datasets import load_irisfrom sklearn.ensemble import RandomForestClassifier# 加载数据data = load_iris()X, y =>
引导法通过有放回地从原始数据集中抽取样本,生成多个子样本(通常与原始数据集大小相同)。
每次从生成的样本中训练模型,未被抽中的样本(称为“包外样本”)作为测试集。
重复该过程多次,并对多次测试结果进行平均。
优点
缺点:
import numpy as npfrom sklearn.utils import resamplefrom sklearn.metrics import accuracy_scorefrom sklearn.ensemble import RandomForestClassifierfrom sklearn.datasets import load_iris# 加载数据data = load_iris()X, y =>
嵌套交叉验证主要用于模型选择和超参数优化。
外层交叉验证用于评估模型的性能,内层交叉验证用于选择模型的最佳超参数。
具体来说,外层将数据分成多个折,每个折作为验证集,剩余部分作为训练集;而在每个外层折的训练集中,又使用内层交叉验证进行超参数搜索。
优点
缺点
from sklearn.model_selection import GridSearchCV, cross_val_score, KFoldfrom sklearn.datasets import load_irisfrom sklearn.ensemble import RandomForestClassifier# 加载数据data = load_iris()X, y =>
分层交叉验证是一种特殊的交叉验证方法,特别适用于分类任务。
在分层交叉验证中,每个折内的类别分布与整个数据集的类别分布相同,从而在不同折中保持相对一致的标签分布,避免模型评估因为类别失衡而产生偏差。
优点
缺点
from sklearn.model_selection import StratifiedKFold, cross_val_scorefrom sklearn.ensemble import RandomForestClassifierfrom sklearn.datasets import load_iris# 加载数据集data = load_iris()X, y =>
时间序列交叉验证是一种专门用于时间序列数据的模型评估方法。与传统交叉验证方法(如 K 折交叉验证)不同,时间序列交叉验证遵循时间的自然顺序,从过去到未来逐步划分数据。这种方法适用于时间序列预测任务,能够避免将未来的数据泄漏到模型训练过程中,从而保证模型的真实性能评估。
时间序列交叉验证的常用方法
滚动预测法
在滚动预测法中,每次划分训练和测试集时,训练集的大小保持不变,仅在时间上向前滚动。每次只使用最新的训练集数据来预测未来的测试集数据。适合模拟模型实时滚动预测的情况。
优缺点:
import numpy as npfrom sklearn.linear_model import LinearRegressionfrom sklearn.metrics import mean_squared_error# 创建时间序列数据X = np.arange(1, 101).reshape(-1, 1)# 1到100的时间序列y = X.flatten() + np.random.normal(scale=5, size=X.shape[0])# 添加噪声# 定义滚动窗口的大小window_size = 20# 每次训练的窗口大小# 初始化模型model = LinearRegression()# 存储预测结果和误差predictions = []errors = []# 滚动窗口法进行预测for i in range(len(X) - window_size - 1):# 定义训练集和测试集X_train = X[i : i + window_size]y_train = y[i : i + window_size]X_test = X[i + window_size : i + window_size + 1]y_test = y[i + window_size : i + window_size + 1]# 训练模型model.fit(X_train, y_train)# 进行预测y_pred = model.predict(X_test)# 记录预测和误差predictions.append(y_pred[0])mse = mean_squared_error(y_test, y_pred)errors.append(mse)print(f"Window {i+1}: Predicted = {y_pred[0]:.2f}, Actual = {y_test[0]:.2f}, MSE = {mse:.2f}")# 计算平均误差average_mse = np.mean(errors)print(f"\nAverage MSE over all windows: {average_mse:.2f}")
扩展窗口法
在扩展窗口法中,训练集会随着时间不断扩大,即每次训练时,训练集包含更长时间段的数据,而测试集仍为后续的一小部分数据。这种方法能让模型在预测时利用更多历史数据。
优缺点
from sklearn.model_selection import TimeSeriesSplitfrom sklearn.linear_model import LinearRegressionfrom sklearn.metrics import mean_squared_errorimport numpy as np# 创建时间序列数据X = np.arange(1, 101).reshape(-1, 1)y = X.flatten() + np.random.normal(scale=5, size=X.shape[0])# 使用TimeSeriesSplit实现滚动预测法tscv = TimeSeriesSplit(n_splits=5)model = LinearRegression()for train_index, test_index in tscv.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)y_pred = model.predict(X_test)print("Test MSE:", mean_squared_error(y_test, y_pred)