机器学习数据集划分实战:6:2:2 黄金比例与 10 折交叉验证的 Python 实现
机器学习数据集划分实战6:2:2黄金比例与10折交叉验证的Python实现数据集划分的核心逻辑当你第一次接触机器学习项目时最容易被忽视却至关重要的步骤就是数据集的合理划分。想象一下如果让一个学生只反复练习期末考试原题他的高分能代表真实能力吗同样机器学习模型也需要不同类型的考题来检验其泛化能力。在真实项目中我们通常将数据划分为三个互斥的子集训练集相当于学生的课本和练习题用于模型参数的学习验证集相当于模拟考试用于调整模型结构和超参数测试集相当于最终期末考试用于无偏评估模型性能from sklearn.model_selection import train_test_split # 原始数据集 X, y load_data() # 首次划分分离测试集20% X_train_val, X_test, y_train_val, y_test train_test_split( X, y, test_size0.2, random_state42) # 二次划分训练集60%和验证集20% X_train, X_val, y_train, y_val train_test_split( X_train_val, y_train_val, test_size0.25, random_state42)6:2:2划分的工程实践6:2:2是中小规模数据集万级样本的经典划分比例。这种分配在资源消耗和评估可靠性之间取得了良好平衡。我们通过Scikit-learn的train_test_split实现这一比例def split_622(X, y, random_seed42): # 第一次分割保留60%训练40%临时集 X_train, X_temp, y_train, y_temp train_test_split( X, y, test_size0.4, random_staterandom_seed) # 第二次分割将临时集均分为验证和测试集 X_val, X_test, y_val, y_test train_test_split( X_temp, y_temp, test_size0.5, random_staterandom_seed) return X_train, X_val, X_test, y_train, y_val, y_test关键参数说明test_size每次分割的比例参数random_state确保结果可复现stratify保持类别分布一致分类问题必需提示对于类别不平衡数据务必设置stratifyy以保证各集合中类别比例相同交叉验证的进阶应用当数据量有限时K折交叉验证K-Fold CV能更充分利用数据。10折交叉验证是业界标准它将训练集分成10份轮流用9份训练1份验证重复10次from sklearn.model_selection import KFold from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score kf KFold(n_splits10, shuffleTrue, random_state42) model RandomForestClassifier() scores [] for train_index, val_index in kf.split(X_train): X_train_fold, X_val_fold X_train[train_index], X_train[val_index] y_train_fold, y_val_fold y_train[train_index], y_train[val_index] model.fit(X_train_fold, y_train_fold) preds model.predict(X_val_fold) scores.append(accuracy_score(y_val_fold, preds)) print(f平均准确率{np.mean(scores):.4f} (±{np.std(scores):.4f}))对于类别不平衡数据应使用分层K折交叉验证StratifiedKFold确保每折的类别分布与整体一致from sklearn.model_selection import StratifiedKFold skf StratifiedKFold(n_splits10, shuffleTrue, random_state42) # 使用方式与普通KFold相同不同划分策略对比方法适用场景优点缺点简单划分(6:2:2)数据量充足(10k样本)实现简单计算成本低验证结果受随机划分影响较大标准K折中小规模数据充分利用数据结果稳定训练k个模型计算成本高分层K折类别不平衡数据保持类别分布评估更准确实现稍复杂留一法(LOOCV)极小数据集(1k样本)最大程度利用数据计算成本极高(n次训练)超参数调优实战结合交叉验证进行网格搜索是调参的金标准。Scikit-learn提供了GridSearchCV一站式解决方案from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [100, 200, 300], max_depth: [None, 5, 10], min_samples_split: [2, 5] } grid_search GridSearchCV( estimatorRandomForestClassifier(), param_gridparam_grid, cvStratifiedKFold(n_splits5), n_jobs-1, # 使用所有CPU核心 scoringaccuracy ) grid_search.fit(X_train, y_train) print(f最佳参数{grid_search.best_params_}) print(f最佳验证分数{grid_search.best_score_:.4f})图像识别特殊处理对于图像数据需特别注意数据泄漏问题。如果原始数据包含同一物体的多张照片如不同角度必须确保这些图像不会被分到不同集合。此时应基于主体而非图像进行划分from sklearn.model_selection import GroupKFold # 假设groups数组包含每张图像对应的主体ID gkf GroupKFold(n_splits5) for train_index, val_index in gkf.split(X, y, groups): X_train, X_val X[train_index], X[val_index] y_train, y_val y[train_index], y[val_index] # 训练和验证流程...评估指标与结果解释不同的划分方法会导致评估结果存在差异。理解这些差异对模型选择至关重要训练集表现反映模型记忆能力过高可能预示过拟合验证集表现反映模型泛化能力用于指导调参测试集表现最终无偏评估只应使用一次典型评估流程# 在最佳参数下训练最终模型 final_model RandomForestClassifier(**grid_search.best_params_) final_model.fit(X_train, y_train) # 在测试集上最终评估 test_acc final_model.score(X_test, y_test) print(f测试集准确率{test_acc:.4f}) # 比较训练/验证/测试表现 train_acc final_model.score(X_train, y_train) val_acc grid_search.best_score_ print(f训练集{train_acc:.4f} | 验证集{val_acc:.4f} | 测试集{test_acc:.4f})当发现训练准确率远高于验证/测试准确率时表明模型可能过拟合需要增加正则化或减少模型复杂度。