python——机器学习:sklearn模型选择model

2024-06-04 8976阅读
在应用机器学习方法进行模型训练时,需要通过数据切分将数据集分为训练集/验证集/测试集。并且可以通过交叉验证,对模型在验证集上的拟合效果进行预评估,以选择表现最好的模型。此外,可以通过参数网格搜索的方法,确定最优的模型参数。
本篇文章通过具体数据做示例,总结了sklearn中模型选择model_selection模块常用函数的使用。包括:
1. 数据切分:train_test_split
2. K折交叉验证:KFold,StratifiedKFold,cross_val_score
3. 参数网格搜索:GridSearchCV
一、数据导入

导入python自带的wine数据集用于演示。该数据集为一个分类数据集,响应变量y取值为0、1、2.

from sklearn import datasets
wine_data = datasets.load_wine()
X = wine_data.data
y = wine_data.target
print(X.shape)
# (178, 13)
二、数据切分

sklearn中train_test_split函数用于数据切分。其输入为待切分的特征X 和 相应变量y。输出按顺序为:切分后的训练集特征X_train,测试集特征X_test,训练集响应变量y_train,测试集响应变量y_test。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

train_test_split 函数参数说明:

  • train_size:指定训练集大小(整数)/训练集比例(小数)
  • test_size:指定测试集大小(整数)/测试集比例(小数)
  • shuffle:默认值为True,表示在进行数据分割前,先进行数据打乱重排。
  • random_state:随机种子,用来保证每次运行函数时,数据打乱重排的结果是一致的。
  • stratify:用于控对制数据按标签类别进行分层切分。默认值为None,表示随机划分标签。当给定一个array时,将对array中的每个类别按相同的比例切分,此时其取值通常为类别响应变量y。(后面将通过具体实例进行演示)

    当stratify取默认值None时,运行结果如下:

    # 执行如下代码,测试集占比为0.2,查看划分结果
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
    # 查看训练集和测试集大小
    print(X_train.shape, X_test.shape)
    #### 输出:(142, 13) (36, 13)
    # 查看原始数据中标签类别分布,可知标签中有45个值为0,57值为1,40个值为2
    print(sum(y==0), sum(y==1), sum(y==2))
    #### 输出:45 57 40
    ## 查看划分后的标签类别分布,可知并不是对标签按比例分割
    print(sum(y_test==0), sum(y_test==1), sum(y_test==2))
    #### 输出:14 14 8
    

    实际使用中,如果对数据进行随机切分,可能导致某些数据量较少的类别全部被划分入训练集,影响模型的效果。所以,可以在数据分割时,按标签类别分层切分(取stratify=y),代码如下。

    # 按y分布切分
    X_train_1, X_test_1, y_train_1, y_test_1 = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
    #查看测试集中,各类别标签所占比例
    print(sum(y_test_1==0)/sum(y==0))
    print(sum(y_test_1==1)/sum(y==1))
    print(sum(y_test_1==2)/sum(y==2))
    #### 输出:
    #### 0.2033898305084746
    #### 0.19718309859154928
    #### 0.20833333333333334
    

    可见,对每个类别,按0.2的比例切分到了测试集中。

    三、K折交叉验证

    K折交叉验证,指将训练数据等分成K个子集,每次选取1个子集作为验证集,其余K-1个子集作为训练集。该过程重复K次。

    1. KFold

      用于定义一个K折交叉验证。参数 n_splits 表示切分份数,其它参数含义同数据切分部分。如定义一个5折交叉验证:

    from sklearn.model_selection import KFold,StratifiedKFold
    n_splits = 5
    kf = KFold(n_splits, shuffle=True, random_state=42)
    

    其方法有get_n_splits()、split()。

    get_n_splits() 返回切分的数量,split() 返回每个子集中的数据在原数据集中的位置标识。应用方法和结果如下:

    kf_n = KFold(n_splits, shuffle=True, random_state=42).get_n_splits(X,y)
    print(kf_n)
    #### 输出: 5
    
    kf_array = KFold(k, shuffle=True, random_state=42).split(X,y)
    for train_index, test_index in KFold(k, shuffle=True, random_state=42).split(X,y):
        # 打印下标
        #print("TRAIN:", train_index, "TEST:", test_index)
        print("TEST:", test_index)
        # 提取每次切分后训练集和验证集数据
        X_train, X_test = X[train_index], X[test_index]
        y_train, y_test = y[train_index], y[test_index]
    

    输出的每次验证集下标如下所示。可以看到,每次迭代验证集的数据量是总量的1/5,且5次迭代的验证集下标无重复。

    python——机器学习:sklearn模型选择model 第1张

    1. StratifiedKFold

      其使用方法同KFold,其作用是,按y各类别的比例切分。同第二节中,train_test_split 的参数 stratify=y 的情况。

    2. cross_val_score

      该函数用于直接计算K折交叉验证的模型得分。这个得分对所有内置的评分函数,都是得分越高,说明模型拟合越好。该函数的返回值是长度为K的list,为K次迭代在验证集上的模型得分。

    如我们构建一个随机森林模型:

    from sklearn.ensemble import RandomForestClassifier
    rf = RandomForestClassifier(random_state=42)  #随机种子固定
    

    cross_val_score函数输入参数包括:

    • estimator:模型
    • X:特征
    • y:响应变量
    • scoring:评分函数,如果不设置该参数,其默认使用所用模型estimator的score()函数对应的得分。
    • cv:(1)其取值可以是一个整数,表示切分的折数,此时对于响应变量 y 为类别变量时,其默认使用StratifiedKFold()进行切分。其它情况时,使用KFold()进行切分。(2)其取值可以是一个CV切分器,如上述代码中的 kf。(3)其取值也可以是包含每折训练集和测试集下标的array,如上述代码中的 kf_array。(4)默认值为5.
      from sklearn.model_selection import cross_val_score
      # 例:
      kf = KFold(5, shuffle=True, random_state=42)
      cv_score = cross_val_score(rf, X, y, scoring='accuracy' ,cv = kf)
      print(cv_score)
      #### 输出:[0.97222222 0.94444444 0.97222222 0.97142857 1.        ]
      # 例:
      kf_array = KFold(k, shuffle=True, random_state=42).split(X,y)
      cv_score_2 = cross_val_score(rf, X, y, scoring='accuracy' ,cv = kf_array)
      

      补充:(1)评分函数score 可以使用内置的评分函数,其可选取值如下所示:

      (说明文档链接:https://scikit-learn.org/stable/modules/model_evaluation.html#scoring-parameter)

      python——机器学习:sklearn模型选择model 第2张

      python——机器学习:sklearn模型选择model 第3张

      (2)评分函数score 也可以自行定义。使用 sklearn 的 metrics 模块中,make_scorer() 函数。

      from sklearn.metrics import make_scorer
      # 定义一个自己的函数
      # 如均方误差
      import numpy as np
      def my_score_fun(y_true, y_pred):
          score = -np.abs(y_true-y_pred).max()
          # 为了满足得分越大越好,取个负值   
          return score
      cv_score_3 = cross_val_score(rf, X, y, scoring=make_scorer(my_score_fun, greater_is_better = True) ,cv = 5)
      
      四、参数网格搜索

      GridSearchCV 函数,给定模型参数的可选值,对这些可选值所有组合,计算交叉验证的得分,找到最优的参数组合。

      # 函数常用参数说明
      GridSearchCV(estimator, param_grid, scoring, cv)
      # estimator:模型
      # param_grid:字典格式,‘key’为参数名,‘value’为参数取值的list
      # scoring、cv:同上述 cross_val_score() 函数
      

      使用示例:

      from sklearn.model_selection import GridSearchCV
      # 定义参数搜索取值的字典
      rf_para={'max_depth':[3,5,7],'min_samples_split':[5,10]}
      # 定义网格搜索
      rf_search = GridSearchCV(rf, rf_para, cv=5, scoring='accuracy')
      # 模型拟合
      rf_model = rf_search.fit(X,y) 
      # 获取最优参数
      print(rf_model.best_params_)
      #### 输出:{'max_depth': 3, 'min_samples_split': 5}
      #### 如果搜索出的最优参数为边界值,可以尝试在超出边界值的一侧增加取值,再进行搜索
      # 获取最优模型
      rf_best = rf_model.best_estimator_
      print(rf_best)
      #### 输出:RandomForestClassifier(max_depth=3, min_samples_split=5, random_state=42)
      # 计算最优模型的得分
      rf_best.score(X,y) 
      # 使用最优模型进行预测
      rf_pred = rf_best.predict(X)  ## 实际使用中,此处应该使用划分出的测试集中的 X_test
      

    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]