機器學習中首要環節就是數據集的處理,其中數據集的處理從個人理解(如有錯誤敬請諒解)的角度來說包括兩個方面:數據集劃分和數據清理。其中數據集劃分是指訓練集、驗證集和測試集的數據類別劃分;數據清理是指數據的清洗、刪除等等方面。這兩天主要學的就是如何劃分數據集。
一、數據集劃分(交叉驗證)
劃分數據集的目的主要是為了后期訓練模型參數的準確性以及測試結果的準確性,避免下列問題:
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折):將所有的樣例劃分為??個組,稱為折疊 (fold) (如果?
, 這等價于?Leave One Out(留一)?策略),都具有相同的大小(如果可能)。預測函數學習時使用?
?個折疊中的數據,最后一個剩下的折疊會用于測試。
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
?,但為每個訓練/測試集刪除與??組有關的樣本。
11.GroupShuffleSplit
?迭代器是?ShuffleSplit
?和?LeavePGroupsOut
?的組合,它生成一個隨機劃分分區的序列,其中為每個分組提供了一個組子集。
時間序列數據的特點是時間 (autocorrelation(自相關性)) 附近的觀測之間的相關性。 然而,傳統的交叉驗證技術,例如?KFold
?和?ShuffleSplit
?假設樣本是獨立的且分布相同的,并且在時間序列數據上會導致訓練和測試實例之間不合理的相關性(產生廣義誤差的估計較差)。 因此,對 “future(未來)” 觀測的時間序列數據模型的評估至少與用于訓練模型的觀測模型非常重要。為了達到這個目的,一個解決方案是由?TimeSeriesSplit
?提供的。
12.
TimeSeriesSplit
?是?k-fold?的一個變體,它首先返回??折作為訓練數據集,并且( 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,RepeatedKFoldX=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