模型評估與改進:交叉驗證

朝南煙發表於2022-05-26

⭐為什麼要劃分測試集與訓練集?

  • 用測試集度量模型對未見過資料的泛化效能

⭐交叉驗證

  • 資料被多次劃分,需要訓練多個模型
  • 最常用K折交叉驗證
    • k是使用者指定的數字,通常取0/5,

    • 5折交叉驗證:資料劃分為5部分,每一部分叫做折。每一折依次輪流作為測試集,其餘做訓練集

      mglearn.plots.plot_cross_validation()

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()
    

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()

  #將資料集劃分為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()

3、交叉驗證的優點

⭐1、每個樣例都能在測試集中出現一次

  • 每個樣例位於一個折中,而每一個折都會被作為一次test

⭐2、提供我們的模型對訓練集選擇的敏感性資訊

  • 它可以告訴我們模型應用於新資料時在最壞和最好情況下的可能表現

⭐3、對我們的資料的使用更加高效

缺點:增加計算成本

?記住:交叉驗證不會返回一個模型

  • 目的只是評估給定演算法在特定資料集訓練後的泛化效能

4、參考文獻

《python機器學習基礎教程》

相關文章