⭐为什么要划分测试集与训练集?

  • 用测试集度量模型对未见过数据的泛化性能

⭐交叉验证

  • 数据被多次划分,需要训练多个模型
  • 最常用K折交叉验证
    • k是用户指定的数字,通常取0/5,

    • 5折交叉验证:数据划分为5部分,每一部分叫做折。每一折依次轮流作为测试集,其余做训练集

      mglearn.plots.plot_cross_validation()

模型评估与改进:交叉验证-LMLPHP

1、scikit-learn中的交叉验证

利用model_selection中的cross_val_score(模型,训练数据,真实标签)

  #在iris数据上,利用logisticregre进行评估

  from sklearn.linear_model import LogisticRegression
  from sklearn.datasets import load_iris
  from sklearn.model_selection import cross_val_score

  iris = load_iris()
  lrg = LogisticRegression()

  scores = cross_val_score(lrg,iris.data,iris.target)
  print("cross_validation scores:{}".format(scores))

  '''
  `cross_validation scores:[0.96666667 1.         0.93333333 0.96666667 1.        ]`
  '''

默认情况下,cross_val_score执行3折交叉验证,可通过修改cv值改变折数

  #总结交叉验证精度:计算平均值

  print("Average cross-validation:{:.2f}".format(scores.mean()))

  '''
  `Average cross-validation:0.97`
  '''

2、分层k折交叉验证和其它策略

⭐sklearn里面的交叉验证

  • 分类问题时使用:分层交叉验证

    • 使每个折中类别之间的比例与整个数据集中的比例相同
  • 回归问题:标准k折交叉验证

    mglearn.plots.plot_stratified_cross_validation()
    

模型评估与改进:交叉验证-LMLPHP

2.1 对交叉验证的更多控制

⭐可以用cv来调节cross_val_score的折数

  • sklearn还提供一个交叉验证分离器(cross_validatoin splitter)作为cv参数

    #在分类数据集上使用标准K折交叉验证
    #需要从model_selection导入KFold分离器类,并将其实例化
    
    from sklearn.model_selection import KFold
    
    kf = KFold(n_splits=5) #5折
    
    scores = cross_val_score(lrg,iris.data,iris.target,cv=kf)
    print("cross_validation scores:{}".format(scores))
    
    '''
    `cross_validation scores:[1.         1.         0.86666667 0.93333333 0.83333333]`
    '''
    
    kf = KFold(n_splits=3) #3折
    
    scores = cross_val_score(lrg,iris.data,iris.target,cv=kf)
    print("cross_validation scores:{}".format(scores))
    
    '''
    `cross_validation scores:[0. 0. 0.]`
    '''
    

📣
在iris数据集上使用3折交叉验证很糟,因为它每个折对应一个类别

⭐可以将数据打乱,代替分层

  kf = KFold(n_splits=3,shuffle=True)
  scores = cross_val_score(lrg,iris.data,iris.target,cv=kf)
  print("cross_validation scores:{}".format(scores))

  '''
  `cross_validation scores:[0.94 0.96 0.98]`
  '''

2.2 留一法交叉验证(leave-one-out)

⭐每折只包含单个样本的k折交叉验证

  • 每次划分,选择单个数据点作为测试集

  • 非常耗时,适合小数据集给出好的估计结果

    from sklearn.model_selection import LeaveOneOut
    
    loo = LeaveOneOut()
    scores = cross_val_score(lrg,iris.data,iris.target,cv=loo)
    print("cross_validation scores:{}".format(scores.mean()))
    
    '''
    `cross_validation scores:0.9666666666666667`
    '''
    

2.3 打乱划分交叉验证

⭐每次划分为训练集取样train_size个样本,为测试集取样test_size个样本,将这个划分重复n_iters次

  mglearn.plots.plot_shuffle_split()

模型评估与改进:交叉验证-LMLPHP

  #将数据集划分为50%的训练集和50%的测试集,共运行10次迭代

  from sklearn.model_selection import ShuffleSplit
  shuffle_split = ShuffleSplit(test_size=.5,train_size=.5,n_splits=10)

  scores = cross_val_score(lrg,iris.data,iris.target,cv=shuffle_split)
  print("cross_validation scores:{}".format(scores))

  '''
  ```
  cross_validation scores:[0.97333333 0.93333333 0.92       0.94666667 0.93333333 0.97333333
   0.94666667 0.88       0.97333333 0.96      ]
  ```
  '''

📣
打乱划分交叉验证可以在训练集和测试集大小之外独立控制迭代次数
允许在每次迭代中仅使用部分数据

  • train_size,test_size之和不等于1来实现

2.4 分组交叉验证

⭐适用于数据中分组高相关度时。
GroupsKFold

  • 参数:groups,说明数据属于哪一组,同一组的数据要么都在测试集,要么都在训练集

    from sklearn.model_selection import GroupKFold
    from sklearn.datasets import make_blobs
    
    X,y = make_blobs(n_samples=12,random_state=0)
    groups = [0,0,0,1,1,1,1,2,2,3,3,3]
    gk = GroupKFold(n_splits=3) #3折
    
    scores = cross_val_score(lrg,X,y,groups,cv=gk)
    print("cross_validation scores:{}".format(scores))
    
    '''
    `cross_validation scores:[0.75       0.6        0.66666667]`
    '''
    

  mglearn.plots.plot_group_kfold()

模型评估与改进:交叉验证-LMLPHP

3、交叉验证的优点

⭐1、每个样例都能在测试集中出现一次

  • 每个样例位于一个折中,而每一个折都会被作为一次test

⭐2、提供我们的模型对训练集选择的敏感性信息

  • 它可以告诉我们模型应用于新数据时在最坏和最好情况下的可能表现

⭐3、对我们的数据的使用更加高效

缺点:增加计算成本

📣记住:交叉验证不会返回一个模型

  • 目的只是评估给定算法在特定数据集训练后的泛化性能

4、参考文献

《python机器学习基础教程》

05-26 22:33