機器學習(一) 基於sklearn庫的數據集劃分(交叉驗證)

機器學習中首要環節就是數據集的處理,其中數據集的處理從個人理解(如有錯誤敬請諒解)的角度來說包括兩個方面:數據集劃分和數據清理。其中數據集劃分是指訓練集、驗證集和測試集的數據類別劃分;數據清理是指數據的清洗、刪除等等方面。這兩天主要學的就是如何劃分數據集。

一、數據集劃分(交叉驗證)

劃分數據集的目的主要是爲了後期訓練模型參數的準確性以及測試結果的準確性,避免下列問題:

1.訓練集和測試集分佈不均勻,主要是指實際項目的數據集中如分類任務中1000個樣本,其中A類樣本和B類樣本均爲500個,但是在劃分訓練集和測試集的時候,訓練集選了650個A類和50個B類樣本,結果導致訓練出來的模型偏向於A類樣本,在測試或者實際預測的時候導致B類數據分類不正確;

2.訓練集和測試集分佈不均勻,主要是指實際項目的數據集中如分類任務中1000個樣本,其中A類樣本950個和B類樣本爲50個.那麼在實際劃分訓練集和測試集的時候可能出現的極端情況就是選取了650個A類樣本和50個B類樣本,測試集中B類樣本數爲0,上述情況可導致模型測試不真實,與實際不符合。

 

二、基於sklearn的數據集劃分(交叉驗證)

交叉驗證是指數據集按照一定的規律進行劃分,包括樣本數據的重複使用,即把得到的樣本數據進行切分,組合爲不同的訓練集和測試集,用訓練集來訓練模型,用測試集來評估模型預測的好壞。在此基礎上可以得到多組不同的訓練集和測試集,當前訓練集中的某樣本在下次可能成爲測試集中的樣本,即所謂“交叉”。

其中博主主要使用的是python編程語言,所以應用測試都是基於sklearn庫哈。當前使用的sklearn庫是0.20.0

1.KFold(K折):將所有的樣例劃分爲 k 個組,稱爲摺疊 (fold) (如果 k = n, 這等價於 Leave One Out(留一) 策略),都具有相同的大小(如果可能)。預測函數學習時使用 k - 1 個摺疊中的數據,最後一個剩下的摺疊會用於測試。

2.RepeatedKFold(RK折),重複 K-Fold n 次。當需要運行時可以使用它 KFold n 次,在每次重複中產生不同的分割。

3.LeaveOneOut (LOO) 是一個簡單的交叉驗證。每個學習集都是通過除了一個樣本以外的所有樣本創建的,測試集是被留下的樣本。

4.LeavePOut 與 LeaveOneOut 非常相似,因爲它通過從整個集合中刪除P個樣本來創建所有可能的訓練/測試集。

5.ShuffleSplit 迭代器 將會生成一個用戶給定數量的獨立的訓練/測試數據劃分。樣例首先被打散然後劃分爲一對訓練測試集合。

其中由於標籤的種類分佈不均勻,這時不能採用上述的方法。此時應採用分層抽樣方法,個人理解爲就是基於標籤的數據層進行劃分,如數據集中有A類樣本80%,B類樣本20%,劃分數據集的時候不管採用哪種方法應遵循訓練集和測試集的樣本標籤比例保持爲80%和20%。

6.StratifiedKFold 是 k-fold 的變種,會返回 stratified(分層) 的摺疊:每個小集合中, 各個類別的樣例比例大致和完整數據集中相同。

7.StratifiedShuffleSplit 。此交叉驗證對象是StratifiedKFold和ShuffleSplit的合併,返回分層的隨機摺疊。摺疊是通過保留每個類別的樣品百分比來進行的。

如果潛在的生成過程產生依賴樣本的 groups ,那麼 i.i.d. 假設將會被打破。這樣的數據分組是特定於域的。一個例子是從多個患者收集醫學數據,從每個患者身上採集多個樣本。而這樣的數據很可能取決於個人羣體。 在我們的例子中,每個樣本的患者 ID 將是其 group identifier (組標識符)。

8.GroupKFold 是 k-fold 的變體,它確保同一個 group 在測試和訓練集中都不被表示。

9.LeaveOneGroupOut 是一個交叉驗證方案,它根據第三方提供的 array of integer groups (整數組的數組)來提供樣本。這個組信息可以用來編碼任意域特定的預定義交叉驗證摺疊。每個訓練集都是由除特定組別以外的所有樣本構成的。

10.LeavePGroupsOut 類似於 LeaveOneGroupOut ,但爲每個訓練/測試集刪除與 P 組有關的樣本。

11.GroupShuffleSplit 迭代器是 ShuffleSplit 和 LeavePGroupsOut 的組合,它生成一個隨機劃分分區的序列,其中爲每個分組提供了一個組子集。

時間序列數據的特點是時間 (autocorrelation(自相關性)) 附近的觀測之間的相關性。 然而,傳統的交叉驗證技術,例如 KFold 和 ShuffleSplit 假設樣本是獨立的且分佈相同的,並且在時間序列數據上會導致訓練和測試實例之間不合理的相關性(產生廣義誤差的估計較差)。 因此,對 “future(未來)” 觀測的時間序列數據模型的評估至少與用於訓練模型的觀測模型非常重要。爲了達到這個目的,一個解決方案是由 TimeSeriesSplit 提供的。

12.

TimeSeriesSplit 是 k-fold 的一個變體,它首先返回 k 折作爲訓練數據集,並且( k+1) 折作爲測試數據集。 請注意,與標準的交叉驗證方法不同,連續的訓練集是超越前者的超集。 另外,它將所有的剩餘數據添加到第一個訓練分區,它總是用來訓練模型。這個類可以用來交叉驗證以固定時間間隔觀察到的時間序列數據樣本。

下面是實際的sklearn調用代碼。

# -*- coding: utf-8 -*-
"""
Created on Tue Nov  5 09:10:35 2019

@author: kofzh
"""

import numpy as np
from sklearn.model_selection import StratifiedShuffleSplit,ShuffleSplit,LeavePOut,LeaveOneOut,StratifiedKFold,KFold,RepeatedKFold

X=np.array([
    [1,2,3,4],
    [11,12,13,14],
    [21,22,23,24],
    [31,32,33,34],
    [41,42,43,44],
    [51,52,53,54],
    [61,62,63,64],
    [71,72,73,74]
])
 
y=np.array([1,1,0,0,1,1,0,0])

'''適合樣本便籤分類均勻的數據集'''
#K折
kf =KFold(n_splits=4,random_state=1)
print("KFold")
for train,test in kf.split(X,y):
    print('Train:%s | Test:%s '%(train,test),'\n')
    #print(X[train],X[train])

#RK折,其中n_splits爲數據集分成的份數,n_repeats爲Test數據集中單一數據出現的次數,默認爲10
random_state= 12883823
rkf= RepeatedKFold(n_splits=4,n_repeats=4,random_state=random_state)
print("RKFold")
for train,test in rkf.split(X,y):
    print('Train:%s | Test:%s '%(train,test),'\n')
    #print(X[train],X[train])

#loo,測試集樣本留一,其餘均爲訓練集。感覺和K折的n_splits=樣本數一樣
loo = LeaveOneOut()
print("loo")
for train,test in loo.split(X,y):
    print('Train:%s | Test:%s '%(train,test),'\n')
    
#lpo,刪除p個樣本,p>1時樣本會重疊
lpo = LeavePOut(p=2)
print("lpo")
for train,test in lpo.split(X,y):
    print('Train:%s | Test:%s '%(train,test),'\n')
    
#隨機訓練集和測試集劃分
ss= ShuffleSplit(n_splits=4,test_size=0.25,random_state=0)
print("ss")
for train,test in ss.split(X,y):
    print('Train:%s | Test:%s '%(train,test),'\n')
''''''''''''''''''''''''''''''

'''適合樣本便籤分類不均勻的數據集'''
#sK折,K折的變種,主要不同爲數據集的標籤分佈與訓練集的各個標籤類別基本一致
x2 = np.ones(10)
y2 = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1]
sf = StratifiedKFold(n_splits =3,random_state=0)
print("St")
for train,test in sf.split(x2,y2):
    print('Train:%s | Test:%s '%(train,test),'\n')


#SSS折,SS折的變種,主要不同爲數據集的標籤分佈與訓練集的各個標籤類別基本一致
sss = StratifiedShuffleSplit(n_splits =3,test_size=2)
print("Sss")
for train,test in sss.split(x2,y2):
    print('Train:%s | Test:%s '%(train,test),'\n')
''''''''''''''''''''''''''''''

'''適合樣本以組爲分類的數據集'''
from sklearn.model_selection import GroupKFold,LeaveOneGroupOut,LeavePGroupsOut,GroupShuffleSplit
x3 = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 8.8, 9, 10]
y3 = ["a", "b", "b", "b", "c", "c", "c", "d", "d", "d"]
groups = [1, 1, 1, 2, 2, 2, 3, 3, 3, 3]


#gk折,k折的變種,主要不同爲數據集的標籤分佈與組類別有關
gkf = GroupKFold(n_splits =3 )
print("gkf")
for train,test in gkf.split(x3,y3,groups= groups):
    print('Train:%s | Test:%s '%(train,test),'\n')
    

#gloo折,loo折的變種,主要不同爲數據集的標籤分佈與組類別有關
gLOO = LeaveOneGroupOut( )
print("gLOO")
for train,test in gLOO.split(x3,y3,groups= groups):
    print('Train:%s | Test:%s '%(train,test),'\n')
    

#glPo折,lPo折的變種,主要不同爲數據集的標籤分佈與組類別有關
gLPO = LeavePGroupsOut(n_groups = 2)
print("gLPO")
for train,test in gLPO.split(x3,y3,groups= groups):
    print('Train:%s | Test:%s '%(train,test),'\n')

#gss折,LeavePGroupsOut和Shuffle的組合
x4 = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 0.001]
y4 = ["a", "b", "b", "b", "c", "c", "c", "a"]
groups = [1, 1, 2, 2, 3, 3, 4, 4]
gss = GroupShuffleSplit(n_splits=4, test_size=0.2, random_state=0)
print("gss")
for train, test in gss.split(x4, y4, groups=groups):
    print("%s  %s" % (train, test))
''''''''''''''''''''''''''''''

'''適合樣本基於時間序列的數據集'''
from sklearn.model_selection import TimeSeriesSplit
x5 = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]])
y5 = np.array([1, 2, 3, 4, 5, 6])

tss = TimeSeriesSplit(n_splits=3)
print(tss)
TimeSeriesSplit(max_train_size=None, n_splits=3)
print("tss")
for train, test in tss.split(x5):
    print("%s  %s" % (train, test))

其實總結可知:上述方法主要分爲5類,K折和RK折、LOO折、LPO折、SS折。其餘均是基於樣本數據標籤的分佈或者其他原因的變種方法。

 

三、基於時間序列的數據集劃分

從上述基於時間序列的數據集劃分的時候,發現只能從過去N個時刻(N可自行設置)預測未來1個時刻的數據,不能滿足我們想要的過去N個時刻預測未來M個時刻的數據,當然了大佬可以自行寫代碼完成,但是對於我等小弟最好是找個現成成熟的代碼來完成。由於涉及到相應的商業機密,不能將源代碼放出來,不過可以將相應的參考鏈接給出來,可以自行優化即可。

https://machinelearningmastery.com/convert-time-series-supervised-learning-problem-python/

四、總結:

從數學角度來說,交叉驗證以及數據清洗都是更準確的生成放入模型進行訓練的X和Y罷了。。。

參考文獻:

1.https://sklearn.apachecn.org/docs/0.21.3/30.html

2.https://machinelearningmastery.com/convert-time-series-supervised-learning-problem-python/

3.https://blog.csdn.net/weixin_39306118/article/details/89527635

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章