ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Surprise 模型选择指南:交叉验证、参数搜索与评估流程详解

Surprise 模型选择指南:交叉验证、参数搜索与评估流程详解 机器学习人工智能【免费下载链接】SurpriseA Python scikit for building and analyzing recommender systems项目地址https://gitcode.com/gh_mirrors/su/Surprise点击查看免费下载Surprise 的model_selection包为推荐系统算法提供了完整的交叉验证与超参数搜索工具链其设计深受 scikit-learn 的model_selection模块启发。本文将围绕 model_selection.rst 展开系统讲解交叉验证迭代器KFold、RepeatedKFold、ShuffleSplit、LeaveOneOut、PredefinedKFold、train_test_split拆分函数、cross_validate批量评估函数以及GridSearchCV与RandomizedSearchCV两大参数搜索类并深入其源码实现帮助读者掌握如何在 Surprise 中科学地评估算法、调优参数并产出可复用的最佳模型。model_selection 包概览surprise/model_selection/目录下包含四个模块对应三类能力模块核心内容源码路径split交叉验证迭代器与数据集拆分函数surprise/model_selection/split.pyvalidationcross_validate交叉验证评估函数surprise/model_selection/validation.pysearchGridSearchCV/RandomizedSearchCV参数搜索surprise/model_selection/search.py其中split模块提供了五种迭代器KFold、RepeatedKFold、ShuffleSplit、LeaveOneOut与PredefinedKFold以及train_test_split函数。validation模块的cross_validate负责在给定迭代器上完成训练—预测—算指标的全流程。search模块则以交叉验证为底层引擎穷举或随机采样参数组合筛选最优配置。交叉验证迭代器如何把数据集切成训练集与测试集所有迭代器都遵循统一的接口构造时传入折叠策略参数调用split(data)返回一个生成器逐次yield出(trainset, testset)二元组。其中trainset是 Trainset 对象testset是原始评分三元组用户 id、物品 id、真实评分的列表可直接喂给算法的fit()与test()。统一入口 get_cv参数归一化无论是cross_validate还是搜索类最终都会通过get_cv把用户传入的cv参数归一化为标准迭代器见 split.pycvNone→ 默认使用KFold(n_splits5)cv为整数 → 等价于KFold(n_splitscv)cv为已实现split()方法的迭代器 → 直接使用否则抛出ValueError。这意味着几乎所有接受cv参数的 API 都共享同一套折叠策略你可以自由地在传一个数字和传一个自定义迭代器之间切换。KFold最基础的 k 折交叉验证KFold(n_splits5, random_stateNone, shuffleTrue)将全部评分数据均分成n_splits份每份轮流作为测试集其余n_splits - 1份作为训练集split.py。关键实现细节n_splits必须 2且小于评分总数否则抛出ValueError切分基于data.raw_ratings的索引洗牌在索引数组上进行get_rng(self.random_state).shuffle(indices)因此不会原地修改原始评分列表每次yield前通过data.construct_trainset(raw_trainset)与data.construct_testset(raw_testset)构建对象random_state仅在shuffleTrue时生效传int作为随机种子可保证多次调用split()得到完全相同的划分适合复现实验。典型用法见 examples/use_cross_validation_iterators.pyfrom surprise import accuracy, Dataset, SVD from surprise.model_selection import KFold data Dataset.load_builtin(ml-100k) kf KFold(n_splits3) algo SVD() for trainset, testset in kf.split(data): algo.fit(trainset) predictions algo.test(testset) accuracy.rmse(predictions, verboseTrue)每次迭代输出一行类似RMSE: 0.9374的结果三折共三行。RepeatedKFold多次重复的 KFoldRepeatedKFold(n_splits5, n_repeats10, random_stateNone)把KFold重复n_repeats次每次使用不同的随机化split.py。其实现非常简洁内部逐次构造KFold(n_splitsself.n_splits, random_staterng, shuffleTrue)并yield from cv.split(data)。get_n_folds()返回n_repeats * n_splits。当数据集规模有限、需要更稳健的误差估计时这是一个低成本的高方差缓解方案。ShuffleSplit随机划分训练集与测试集ShuffleSplit(n_splits5, test_size0.2, train_sizeNone, random_stateNone, shuffleTrue)与 K 折不同它不保证每一折互不相同只是每次都独立地随机抽取测试集split.py。大小参数规则由validate_train_test_sizes统一处理test_sizefloat表示测试集占评分总数的比例int表示绝对条数None时自动取总评分 − 训练集大小train_size同上None时自动取总评分 − 测试集大小校验规则两者都必须严格大于 0 且小于评分总数二者之和不能超过评分总数否则抛ValueError实现上浮点比例会向上取整ceil计算测试集大小、向下取整floor计算训练集大小。train_test_split正是它的一个特例封装。train_test_split一次性划分训练集与测试集train_test_split(data, test_size0.2, train_sizeNone, random_stateNone, shuffleTrue)返回(trainset, testset)二元组split.py。源码中它只是构造了一个ShuffleSplit(n_splits1, ...)并取next(ss.split(data))即只随机划分一次、不进入交叉验证流程。文档明确提示该函数不能用作交叉验证迭代器。完整示例见 examples/train_test_split.pyfrom surprise import accuracy, Dataset, SVD from surprise.model_selection import train_test_split data Dataset.load_builtin(ml-100k) trainset, testset train_test_split(data, test_size0.25) algo SVD() algo.fit(trainset) predictions algo.test(testset) accuracy.rmse(predictions)输出形如RMSE: 0.9411。若想一步完成训练与预测文档也给出了等价写法predictions algo.fit(trainset).test(testset)。LeaveOneOut每个用户恰好留出一条评分LeaveOneOut(n_splits5, random_stateNone, min_n_ratings0)保证每个用户在测试集中恰好有一条评分split.py实现先把raw_ratings按用户 id 聚合为user_ratings字典每折中对每个用户随机抽取一条评分进测试集其余进训练集min_n_ratings用于过滤只有评分条数大于该阈值的用户才会进入本折其余用户被丢弃。例如min_n_ratings2可确保每个用户训练集中至少有 2 条评分、测试集恰好 1 条默认0表示只有 1 条评分的用户也会出现在测试集但不在训练集若某折训练集为空例如min_n_ratings设置过高抛出ValueError提示。该迭代器非常适合评估冷启动用户推荐效果这类场景。PredefinedKFold使用外部预定义折文件当训练/测试折已经由文件预先定义好时如 movielens-100k 自带的u1.base/u1.test…u5.base/u5.test使用PredefinedKFold配合Dataset.load_from_folds()dataset.pyfrom surprise import accuracy, Dataset, Reader, SVD from surprise.model_selection import PredefinedKFold import os files_dir os.path.expanduser(~/.surprise_data/ml-100k/ml-100k/) reader Reader(ml-100k) train_file files_dir u%d.base test_file files_dir u%d.test folds_files [(train_file % i, test_file % i) for i in (1, 2, 3, 4, 5)] data Dataset.load_from_folds(folds_files, readerreader) pkf PredefinedKFold() algo SVD() for trainset, testset in pkf.split(data): algo.fit(trainset) predictions algo.test(testset) accuracy.rmse(predictions, verboseTrue)PredefinedKFold.split()直接读取每一对(train_file, test_file)并构建对应的 trainset/testsetsplit.py。folds_files必须是一个(训练文件, 测试文件)元组组成的列表即使只有一对文件也需用列表包裹。cross_validate一站式交叉验证评估cross_validate(algo, data, measures[rmse, mae], cvNone, return_train_measuresFalse, n_jobs1, pre_dispatch2*n_jobs, verboseFalse)是对上述迭代器的高层封装validation.py它自动完成遍历折 → 训练 → 预测 → 计算指标 → 汇总输出的整个流程。参数说明algo任意继承自 AlgoBase 的算法实例measures要计算的指标名列表必须是 accuracy 模块 中函数名的小写形式默认[rmse, mae]可用rmse、mse、mae、fcp等cv迭代器、整数或None规则与get_cv一致默认 5 折 KFoldreturn_train_measures是否同时计算训练集上的指标默认Falsen_jobs并行评估的折数上限。-1表示使用全部 CPU1表示完全串行便于调试小于-1时使用(n_cpus n_jobs 1)个 CPU如-2表示全部 CPU 减一pre_dispatch控制并行时一次性派发的任务数可为None全部立即创建并派发适合轻量快速任务、整数精确派发数或字符串表达式如默认的2*n_jobs用于防止派发任务过多导致内存爆炸verbose为True时打印每个折的指标与训练/测试耗时并给出所有折的均值与标准差。返回值是一个字典包含test_metric如test_rmse、test_mae为各测试折指标组成的 numpy 数组train_metric仅当return_train_measuresTrue时存在fit_time/test_time各折的训练、测试耗时秒数组。最基础的用法见 examples/basic_usage.pyfrom surprise import Dataset, SVD from surprise.model_selection import cross_validate data Dataset.load_builtin(ml-100k) algo SVD() cross_validate(algo, data, measures[RMSE, MAE], cv5, verboseTrue)输出示例实际数值因随机性而异Evaluating RMSE, MAE of algorithm SVD on 5 split(s). Fold 1 Fold 2 Fold 3 Fold 4 Fold 5 Mean Std RMSE 0.9311 0.9370 0.9320 0.9317 0.9391 0.9342 0.0032 MAE 0.7350 0.7375 0.7341 0.7342 0.7375 0.7357 0.0015 Fit time 6.53 7.11 7.23 7.15 3.99 6.40 1.23 Test time 0.26 0.26 0.25 0.15 0.13 0.21 0.06注意measures传入RMSE/MAE大写也能工作因为源码开头会执行measures [m.lower() for m in measures]统一转小写。从源码看cross_validate的底层由fit_and_score辅助函数支撑validation.py它依次调用algo.fit(trainset)、algo.test(testset)用time.time()记录训练/测试耗时再通过getattr(accuracy, m)动态取到对应指标函数逐项计算。全部折的结果通过 joblib 的Parallel并行执行后重组为上述字典。此外fit_and_score也是GridSearchCV/RandomizedSearchCV复用同一套评估逻辑的基础。GridSearchCV穷举式参数搜索GridSearchCV(algo_class, param_grid, measures[rmse, mae], cvNone, refitFalse, return_train_measuresFalse, n_jobs1, pre_dispatch2*n_jobs, joblib_verbose0)对参数网格做笛卡尔积穷举在每个参数组合 × 每个折上执行训练与评估search.py。参数要点algo_class算法类不是实例如SVDparam_grid字典键为算法参数名值为候选值列表所有组合都会被尝试measures默认[rmse, mae]决定用哪些指标来筛选最优参数cv默认 5 折 KFold规则同前refitFalse默认只做搜索True表示用measures中第一个指标的最优参数在整个数据集上重新训练也可传指标名字符串如mae指定用哪个指标选参。refit 后可用test()/predict()直接使用最佳模型。注意当数据通过load_from_folds()加载时不能使用 refit源码会在fit()中抛出ValueError拦截search.pyreturn_train_measures为True时cv_results中会额外包含训练集指标n_jobs/pre_dispatch与cross_validate语义一致joblib_verbose控制 joblib 的日志详细程度。完整示例见 examples/grid_search_usage.pyfrom surprise import Dataset, SVD from surprise.model_selection import GridSearchCV data Dataset.load_builtin(ml-100k) param_grid {n_epochs: [5, 10], lr_all: [0.002, 0.005], reg_all: [0.4, 0.6]} gs GridSearchCV(SVD, param_grid, measures[rmse, mae], cv3) gs.fit(data) print(gs.best_score[rmse]) # 最佳 RMSE 得分 print(gs.best_params[rmse]) # 取得最佳 RMSE 的参数组合 algo gs.best_estimator[rmse] # 最佳 RMSE 对应的算法实例 algo.fit(data.build_full_trainset())输出示例0.961300130118 {n_epochs: 10, lr_all: 0.005, reg_all: 0.4}搜索结果属性fit()之后搜索对象暴露四个核心属性均为指标名 → 结果的字典best_estimator[m]在指标m上平均表现最优的算法实例best_score[m]对应的最佳平均得分best_params[m]取得该得分的参数组合best_index[m]cv_results中对应参数组合的索引cv_results包含全部折、全部参数组合的完整明细字典可直接导入 pandas DataFrame 做进一步分析pd.DataFrame.from_dict(gs.cv_results)。cv_results的结构每个键都是与参数组合数等长的数组键含义split{i}_test_metric第i折上各参数组合的测试指标mean_test_metric/std_test_metric跨折均值与标准差rank_test_metric各参数组合在该指标上的排名1 为最优mean_fit_time/mean_test_time及 std 变体各参数组合的平均训练/测试耗时params全部参数组合字典的列表param_name每个参数在各组合中的取值列表排名与最优选择逻辑在源码中有明确区分对于mae、rmse、mse这类越小越好的指标best_index取mean_test_measures.argmin()排名越小越优对于fcpFraction of Concordant Pairs这类越大越好的指标则取argmax()排名规则相应反转search.py。嵌套字典参数sim_options / bsl_options的特殊写法param_grid中如果包含sim_options相似度参数或bsl_options基线参数这类嵌套字典需要把内层也写成参数名 → 候选值列表的形式。源码的_parse_options会先用itertools.product对嵌套字典做笛卡尔积展开再与顶层参数组合search.py。文档给出的标准写法param_grid { k: [10, 20], sim_options: { name: [msd, cosine], min_support: [1, 5], user_based: [False], }, }两者还可组合例如对KNNBaseline同时搜索基线与相似度参数param_grid { bsl_options: { method: [als, sgd], reg: [1, 2], }, k: [2, 3], sim_options: { name: [msd, cosine], min_support: [1, 5], user_based: [False], }, }RandomizedSearchCV随机采样式参数搜索当参数空间很大时穷举代价高昂。RandomizedSearchCV从参数分布中随机采样n_iter组配置search.py适合先粗后细coarse-to-fine的调参策略。与GridSearchCV的差异集中在参数定义方式上param_distributions键为参数名值为分布对象需提供rvs采样方法如scipy.stats的分布或候选值列表n_iter采样的参数组合数量默认10random_state随机种子控制从列表值中均匀采样时的可复现性int、RandomState实例或None。采样逻辑_sample_parameters静态方法值得注意若所有参数都以列表给出则先对列表做笛卡尔积生成完整网格再在网格内无放回地随机抽取n_iter组若至少有一个参数是分布对象则逐次对每个参数有放回采样列表参数均匀随机取一个分布参数调用v.rvs(random_staternd)源码注释特别提示连续型参数强烈建议使用连续分布在 SciPy 0.16 之前scipy.stats.distributions不接受自定义 RNG 实例因此使用分布时设置random_state无法保证完全确定性SciPy 0.16 起才保证。其余属性best_estimator、best_score、best_params、best_index、cv_results与GridSearchCV完全一致。三种评估方式的选择建议结合文档与源码可以把整套工具归纳为三个层级快速评估cross_validate(algo, data, cv5)一行代码得到指标均值、标准差与耗时适合对单个算法快速摸底精细控制自行实例化迭代器KFold、LeaveOneOut、PredefinedKFold等并手写fit/test循环适合定制评估流程或使用预定义折文件参数调优GridSearchCV穷举小网格、RandomizedSearchCV采样大空间配合refitTrue直接产出在完整数据上重训的最佳模型衔接线上预测。三者共享同一套get_cv归一化与fit_and_score评估内核因此无论走哪条路径评估口径指标、折叠策略、随机种子都是一致的实验结果可以放心互相参照。更多用法可继续阅读文档 getting_started.rst 中的Use cross-validation iterators与Tune algorithm parameters with GridSearchCV两节以及仓库中的 examples 目录。赞分享机器学习人工智能【免费下载链接】SurpriseA Python scikit for building and analyzing recommender systems项目地址https://gitcode.com/gh_mirrors/su/Surprise点击查看免费下载相关推荐scikit-learn模型选择与评估交叉验证与超参数调优完整指南scikit learn模型选择与评估交叉验证与超参数调优完整指南 在机器学习项目中 scikit learn模型选择 和 模型评估 是确保算法性能的关键环文档机器学习教程机器学习模型评估终极指南5步掌握交叉验证与网格搜索参数调优实战机器学习模型评估终极指南5步掌握交叉验证与网格搜索参数调优实战 欢迎来到handson ml2机器学习实战教程 作为基于Python的开源机器学习教程示例工程教程机器学习深度学习PRMLT模型评估与选择从交叉验证到模型比较的完整指南PRMLT模型评估与选择从交叉验证到模型比较的完整指南 在机器学习项目中模型评估与选择是决定最终性能的关键环节。PRMLT项目作为《模式识别与机器学习》书籍机器学习人工智能上一篇【限时免费】 mT5_multilingual_XLSum不止是多语言摘要这么简单下一篇深度揭秘EdgeFlow如何用算法智慧重塑Blender边缘循环创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表