交叉驗證法及Bootstrap取樣
一、Cross Validation(交叉驗證)
1. 解決的問題
用於驗證分類器的效能的資料分析方法,可以抽樣(抽取合適的訓練集和測試集)、可以評估模型(計算模型的預測誤差)。
2. 如何解決
基本原理:將原始資料分組,一部分做訓練集,一部分做測試集。如k-fold cross validation均分成n組,抽取一組為測試集,剩下n-1組為訓練集,依次抽遍,測試結果取預測誤差平均值。
演算法步驟:
Step1: 將學習樣本空間 C分為大小相等的 K份
Step2: fori =1 to K:
取第i份作為測試集
forj =1 to K:
ifi !=j:
將第j份加到訓練集中,作為訓練集的一部分
endif
endfor
endfor
Step3: fori in (K-1訓練集):
訓練第i個訓練集,得到一個分類模型
使用該模型在第N個數據集上測試,計算並儲存模型評估指標
endfor
Step4: 計算模型的平均效能
Step5: 用這K個模型在最終驗證集的分類準確率平均值作為此K-CV下分類器的效能指標.
實現抽樣:(matlab/python裡的scikit-learn庫sklearn.cross_validation)
(1)K-fold(K組)
from sklearn.model_selection import KFold
X=["a","b","c","d"]
kf=KFold(n_splits=4)//分成四組,訓練四次
for train,test in kf.split(X):
print("%s %s" % (train,test))
>>>
[1 2 3] [0]
[0 2 3] [1]
[0 1 3] [2]
[0 1 2] [3]
(2)Repeated K-Fold(隨機分組n次,每次按K組分)
import numpy as np
from sklearn.model_selection import RepeatedKFold
X=np.array([[1,2],[3,4],[1,2],[3,4]])
random_state=12883823
rkf=RepeatedKFold(n_splits=2,n_repeats=2,random_state=random_state)//隨機分成兩組,隨機分組兩次
for train,test in rkf.split(X):
print("%s %s" % (train,test))
>>>
[2 3] [0 1]
[0 1] [2 3]
[0 2] [1 3]
[1 3] [0 2]
(3)LeaveOneOut/LeavePOut(隨機拿出P個數據作為測試集)
from sklearn.model_selection import LeavePOut/LeaveOneOut
X=[1,2,3,4]
lpo=LeavePOut(p=2)/LeaveOneOut()
for train,test in lpo.split(X):
print("%s %s" % (train,test))
>>>
[2 3] [0 1]
[1 3] [0 2]
[1 2] [0 3]
[0 3] [1 2]
[0 2] [1 3]
[0 1] [2 3]
(4)ShuffleSplit(洗牌加隨機抽樣)
import numpy as np
from sklearn.model_selection import ShuffleSplit
X=np.arange(5)
ss=ShuffleSplit(n_splits=3,test_size=2/5,random_state=0)//隨機抽三次,每次抽出測試資料佔2/5)
for train_index,test_index in ss.split(X):
print("%s %s" % (train_index,test_index))
>>>
[1 3 4] [2 0]
[1 4 3] [0 2]
[4 0 2] [1 3]
PS:一個不均衡樣本的例項:http://blog.csdn.net/dream_angel_z/article/details/47110077
3. 優缺點
優點:幾乎能夠訓練到所有資料
缺點:如何確定K的最佳取值(也許碰運氣吧)
二、自助法(Bootstrap)
1. 可以解決的問題
是一種統計方法,適用於小樣本抽樣,可以劃分train/test,可以通過方差估計構造置信區間。(整合學習中的bagging有運用)。
2. 如何解決
基本原理:其實就是利用樣本再生成自助樣本,自助樣本估計樣本,樣本再估計總體。在原始資料中有放回的隨機抽樣,樣本容量仍為n,所得樣本稱為bootstrap樣本。
演算法步驟:
#這個虛擬碼自己寫的,希望可以得到改正
fori =1 to K:
第i次取樣
iflen(train) < m:
隨機抽取一個數據新增到train
endfor
endfor
Python實現:(用bootstrap抽樣)
import random
#抽樣物件
class Sampling(object):
def__init__(self):
pass
defsampling(self):
pass
#bootstrap抽樣
class BootStrap(Sampling):
def __init__(self,n_samples):
self.n_samples=n_samples
def sampling(self):
_slice=[]
whilelen(_slice)<self.n_samples:
p=random.randrange(0,self.n_samples)
_slice.append(p)
return _slice
if __name__ == '__main__':
bootstrap=BootStrap(10)//樣本數十個,則bootstrap樣本容量也為10
for i inrange(5)://bootstrap抽樣次數為5,即抽出五組
_slice=bootstrap.sampling()
print(_slice)
>>>
[8, 0, 6, 2, 8, 7, 2, 6, 7, 1]
[7, 1, 4, 6, 6, 0, 5, 1, 3, 8]
[2, 1, 2, 6, 1, 0, 0, 1, 3, 8]
[1, 4, 4, 2, 5, 9, 4, 6, 0, 1]
[8, 7, 3, 5, 4, 9, 3, 9, 4, 3]
PS:資料前處理例項
https://github.com/Lehyu/pyml/tree/9bcb213b5bd5702f9b7df5d03f3fedcad32e08ae/preprocessing
3. 優缺點
優點:在資料集較小時適合使用;可以從原始資料中產生多個訓練集。
缺點:改變了原始資料的分佈,會引入估計偏差。
如何劃分訓練集/驗證集/測試集?