零基础实战机器学习
黄佳
新加坡科研局首席研究员
19489 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 24 讲
零基础实战机器学习
15
15
1.0x
00:00/00:00
登录|注册

10|模型优化(下):交叉验证,同时寻找最优的参数

你好,我是黄佳。
欢迎来到零基础实战机器学习。在前面几节课中,我们已经学习了两种优化机器学习模型的方法,一种是做各种特征工程,让特征集更适合模型;另一种是防止过拟合,让模型不用“那么”精确。
这两种方式的优化角度不同,特征工程是从数据预处理的角度,给出更高质量的数据,而防止过拟合则是在模型训练的过程中,控制模型的复杂度。其实,除此之外,我们还可以从模型的验证和评估环节入手,来优化模型性能。

交叉验证:小数据集的资源复用

你知道,在样本充足的情况下,我们会随机将数据分为 3 个部分:训练集、验证集和测试集。其中,训练集用来训练模型,验证集用来模型调优,测试集用来评估模型性能。
不过,你还记不记得我们在第 1 讲中介绍监督学习的时候,我说过有标签的数据是非常难以获得的。本来就很有限的数据集还要被拆成训练集、测试集和验证集,真是让人特别舍不得。
而且,我们知道数据集越大,就越不容易出现过拟合的现象。那么,我们如何利用较小的数据集,从而达到较大数据集的效果呢?这就需要交叉验证。
交叉验证的基本思想是这样的:将训练数据集分为 k 等份,其中 k-1 份用作训练集,单独的那一份用作验证集,整个过程重复 k 次,这也通常称作 k 折。这样就最大程度重复地使用了训练集中的数据,每一个数据都既做了训练,又做了测试,从而在最大程度上提高模型性能的可信度。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了机器学习模型优化的关键方法之一——交叉验证,以及如何使用网格搜索进行超参数调优。通过交叉验证,读者可以充分利用有限的数据集,提高模型性能的可信度。文章详细介绍了交叉验证的基本思想和实现步骤,以及如何使用Python中的sklearn库进行交叉验证。随后,文章介绍了网格搜索的原理和具体操作步骤,以及如何通过GridSearchCV工具自动调参,找到模型的最优参数组合。通过实际代码演示,读者可以了解如何使用GridSearchCV来优化随机森林模型的参数,并评估模型性能。最后,文章强调了优化结果的相对性,提醒读者在不同数据集上谨慎应用最优参数组合。整体而言,本文为读者提供了一种有效的模型优化方法,帮助提高机器学习模型的性能。 在本文中,我们学习了两个重要的模型优化方法:交叉验证和网格搜索。交叉验证是一种有效利用数据的方法,通过重复使用数据集进行训练和验证,提高模型性能的可信度。而网格搜索则是一种超参数调优的技术,通过穷举法寻找最优参数组合。这两个工具的简单易用,可以通过代码反复演练,尝试不同的验证折数和模型超参数。除此之外,我们还学习了特征工程、防过拟合等提升模型效率的方法。在下一讲中,我们将继续学习更多内容,让我们一起期待吧!

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《零基础实战机器学习》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(8)

  • 最新
  • 精选
  • 在路上
    佳哥好,交叉验证会得到多个模型,在预测数据时,是把多个模型的预测值加总求平均值吗?

    作者回复: 交叉验证一般并不是用于训练模型,进行预测,而是求出多次的评估分数,把评估分数求均值。确定模型(或算法)的效果。 如果用这个思想,得到多个模型,然后把预测值求均值,那就是“集成学习”了,并不算是交叉验证啦。

    2021-09-22
    3
  • Siyige2727
    老师好,我按照下面的设置,跑出的结果,为什么验证集上的分数很低呢? GridSearchCV(cv=3, estimator=RandomForestRegressor(), n_jobs=10, param_grid={'bootstrap': [True, False], 'criterion': ['mse', 'mae'], 'max_depth': [3, 5, 6, 10, 12, None], 'max_features': ['auto', 'sqrt'], 'min_samples_leaf': [2, 3, 5, 7, 10], 'min_samples_split': [2, 5, 8, 10], 'n_estimators': [50]}, scoring='r2', verbose=1) 训练集上的R平方分数-调参后的随机森林: 0.8541 测试集上的R平方分数-调参后的随机森林: 0.0481

    作者回复: 这是有可能的,因为我们的数据集其实数据是比较少的,每次拆分训练数据集和测试数据集的情况很不一样。而且随机森林是一个有随机性的模型每一次的返回结果也不同。你修改一下拆分数据时的种子值(random_state),重跑一次,看看还是这么低么? 也可以尝试一下不同的参数值的组合(可以上网搜索一下合适的值),我给出的不一定最好。

    2021-09-22
    2
    3
  • Vincent
    老师你好,关于 CV 有个疑问,CV 是用来评估模型的,而不是用来训练的。如果我们评估出最优的算法,后续用什么方式训练模型呢?把训练集和验证集合并来训练?

    作者回复: 在机器学习中,交叉验证(CV)通常用于评估模型的泛化能力,即模型对未见数据的处理能力。在完成交叉验证并选择了最优的算法和参数后,您提到的“合并训练集和验证集来训练模型”是一种常见的做法。以下是这个过程的一些关键步骤: 交叉验证:在这一步,您会将数据集分为几个部分,通常是“训练集”和“验证集”。然后,您会在不同的训练集上训练模型,并在相应的验证集上评估它们。这有助于您了解不同模型或参数配置在不同子集上的表现,并选择最优的模型和参数。 最终模型训练:一旦您选择了最优的模型和参数,下一步就是使用全部可用数据来训练这个模型。在这个阶段,您可以合并原来的训练集和验证集,因为您已经确定了模型的配置,并且现在需要利用所有数据来训练一个尽可能强大的最终模型。 测试集评估:如果可行,最好还是保留一个独立的测试集,用于在完成最终模型训练后进行评估。这有助于您了解模型在完全未见数据上的表现。

    2024-01-05归属地:上海
  • 静静呀
    老师我的网格搜索报错了,ValueError: Unknown label type: 'continuous',能帮我看看是什么原因吗 from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import GridSearchCV from sklearn.model_selection import train_test_split X = df_LTV.drop(['用户码','年度LTV'],axis=1) #特征集 y = df_LTV['年度LTV'] #标签集 # 拆分成训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state = 0) model_rfr = RandomForestClassifier() # 随机森林模型 # 对随机森林算法进行参数优化 rf_param_grid = {"max_depth": [None], "max_features": [3, 5, 12], "min_samples_split": [2, 5, 10], "min_samples_leaf": [3, 5, 10], "bootstrap": [False], "n_estimators" :[100,300], "criterion": ["gini"]} model_rfr_gs = GridSearchCV(model_rfr, param_grid = rf_param_grid, cv=3, scoring="r2", n_jobs= 10, verbose = 1) model_rfr_gs.fit(X_train, y_train)

    作者回复: 我这里有个笔误,RandomForestClassifier()应该改为RandomForestRegressor(),以Notebook代码为准。回头网页文档我们也修改一下。谢谢同学。

    2023-11-08归属地:上海
  • Matthew
    作业3的代码: # 创建模型 from sklearn.ensemble import RandomForestRegressor model_rfr = RandomForestRegressor() # 对随机森林算法进行参数优化 rfr_param_grid = {'bootstrap': [True, False], 'max_depth': [10, 50, 100, None], 'max_features': ['auto', 'sqrt'], 'min_samples_leaf': [1, 2, 4], 'min_samples_split': [2, 5, 10], 'n_estimators': [50, 500, 2000]} # 导入 网格搜索 工具 from sklearn.model_selection import GridSearchCV model_rfr_gs = GridSearchCV(model_rfr, param_grid = rfr_param_grid, cv = 3, scoring="r2", n_jobs= 10, verbose = 1) model_rfr_gs.fit(X_train, y_train) # 用优化后的参数拟合训练数据集 print(" GridSearchCV 最佳参数组合:", model_rfr_gs.best_params_) # 导入 随机搜索 工具 from sklearn.model_selection import RandomizedSearchCV model_rfr_rs = RandomizedSearchCV(model_rfr, param_distributions = rfr_param_grid, cv = 3, n_iter = 10, scoring="r2", n_jobs= 10, verbose = 1) model_rfr_rs.fit(X_train, y_train) # 用优化后的参数拟合训练数据集 print(" RandomizedSearchCV 最佳参数组合:", model_rfr_rs.best_params_) from sklearn.metrics import r2_score, median_absolute_error #导入Sklearn评估模块 print("GridSearchCV:") print('训练集上的R平方分数-调参后的随机森林: %0.4f' % r2_score(y_train, model_rfr_gs.predict(X_train))) print('测试集上的R平方分数-调参后的随机森林: %0.4f' % r2_score(y_test, model_rfr_gs.predict(X_test))) print("RandomizedSearchCV:") print('训练集上的R平方分数-调参后的随机森林: %0.4f' % r2_score(y_train, model_rfr_rs.predict(X_train))) print('测试集上的R平方分数-调参后的随机森林: %0.4f' % r2_score(y_test, model_rfr_rs.predict(X_test)))

    作者回复: 好的

    2023-06-04归属地:江苏
  • Matthew
    # 留一法分折 LeaveOneOut loo = LeaveOneOut() for fold_, (train_index, test_index) in enumerate(loo.split(df_LTV)): X_train = df_LTV.iloc[train_index].drop(['年度LTV'],axis=1) #训练集X X_test = df_LTV.iloc[test_index].drop(['年度LTV'],axis=1) #验证集X y_train = df_LTV.iloc[train_index]['年度LTV'] #训练集y y_test = df_LTV.loc[test_index]['年度LTV'] #验证集y model_lr.fit(X_train, y_train) #训练模型 # print(f"第{fold_}折验证集R2分数:{r2_score(y_test, model_lr.predict(X_test))}") print(f"第{fold_}折验证集的真值:{y_test.values[0]} ,预测值:{model_lr.predict(X_test)[0]}") # 留多法分折 LeavePOut lpo = LeavePOut(p=10) for fold_, (train_index, test_index) in enumerate(lpo.split(df_LTV)): X_train = df_LTV.iloc[train_index].drop(['年度LTV'],axis=1) #训练集X X_test = df_LTV.iloc[test_index].drop(['年度LTV'],axis=1) #验证集X y_train = df_LTV.iloc[train_index]['年度LTV'] #训练集y y_test = df_LTV.loc[test_index]['年度LTV'] #验证集y model_lr.fit(X_train, y_train) #训练模型 print(f"第{fold_}折验证集R2分数:{r2_score(y_test, model_lr.predict(X_test))}")

    作者回复: 好

    2023-06-03归属地:江苏
  • Matthew
    作业2的代码: # 创建模型 from sklearn.linear_model import LinearRegression model_lr = LinearRegression() # 导入K折工具 from sklearn.model_selection import KFold from sklearn.model_selection import RepeatedKFold from sklearn.model_selection import LeaveOneOut from sklearn.model_selection import LeavePOut # 导入R2分数评估工具 from sklearn.metrics import r2_score # 普通的 KFold 方法 kf5 = KFold(n_splits=5, shuffle=False) #5折 for fold_, (train_index, test_index) in enumerate(kf5.split(df_LTV)): # print(train_index, test_index) X_train = df_LTV.iloc[train_index].drop(['年度LTV'],axis=1) #训练集X X_test = df_LTV.iloc[test_index].drop(['年度LTV'],axis=1) #验证集X y_train = df_LTV.iloc[train_index]['年度LTV'] #训练集y y_test = df_LTV.loc[test_index]['年度LTV'] #验证集y model_lr.fit(X_train, y_train) #训练模型 print(f"第{fold_}折验证集R2分数:{r2_score(y_test, model_lr.predict(X_test))}") # 重复 K 折 RepeatedKFold rkf5 = RepeatedKFold(n_splits=5, n_repeats=10) # 5折,重复10次 for fold_, (train_index, test_index) in enumerate(rkf5.split(df_LTV)): X_train = df_LTV.iloc[train_index].drop(['年度LTV'],axis=1) #训练集X X_test = df_LTV.iloc[test_index].drop(['年度LTV'],axis=1) #验证集X y_train = df_LTV.iloc[train_index]['年度LTV'] #训练集y y_test = df_LTV.loc[test_index]['年度LTV'] #验证集y model_lr.fit(X_train, y_train) #训练模型 print(f"第{fold_}折验证集R2分数:{r2_score(y_test, model_lr.predict(X_test))}")

    作者回复: 好的

    2023-06-03归属地:江苏
  • Matthew
    作业1的代码和结果: # 创建模型 from sklearn.linear_model import Lasso model_lasso = Lasso() #创建Lasso回归模型 # 交叉验证 from sklearn.model_selection import cross_validate # 导入交叉验证工具 cv = 3 scores = cross_validate(model_lasso, X, y, cv=cv, scoring=('r2', 'neg_mean_squared_error'), return_train_score=True) for i in range(cv): print(f"第{i+1}折验证集的fit_time:{scores['fit_time'][i]} ") print(f"第{i+1}折验证集的score_time:{scores['score_time'][i]} ") print(f"第{i+1}折验证集的test_r2:{scores['test_r2'][i]} ") print(f"第{i+1}折验证集的train_r2:{scores['train_r2'][i]} ") print(f"第{i+1}折验证集的test_neg_mean_squared_error:{-scores['test_neg_mean_squared_error'][i]} ") print(f"第{i+1}折验证集的train_neg_mean_squared_error:{-scores['train_neg_mean_squared_error'][i]} ") print("\n") -------------------------------------------------------------------- 第1折验证集的fit_time:0.000865936279296875 第1折验证集的score_time:0.0006310939788818359 第1折验证集的test_r2:0.5509442176019284 第1折验证集的train_r2:0.49295429721273365 第1折验证集的test_neg_mean_squared_error:36374278.87442617 第1折验证集的train_neg_mean_squared_error:3931052.5016323677 第2折验证集的fit_time:0.0009672641754150391 第2折验证集的score_time:0.0004417896270751953 第2折验证集的test_r2:-0.547095575701684 第2折验证集的train_r2:0.756077640106148 第2折验证集的test_neg_mean_squared_error:19259422.630117264 第2折验证集的train_neg_mean_squared_error:10686185.198631434 第3折验证集的fit_time:0.000530242919921875 第3折验证集的score_time:0.0004150867462158203 第3折验证集的test_r2:0.0975132893938776 第3折验证集的train_r2:0.6571299228574952 第3折验证集的test_neg_mean_squared_error:2236906.201517424 第3折验证集的train_neg_mean_squared_error:16312807.147477873

    作者回复: ✌️

    2023-06-02归属地:江苏
收起评论
显示
设置
留言
8
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部