|
今天我給大家盤點下機器學(xué)習(xí)中所使用的交叉驗證器都有哪些,用最直觀的圖解方式來幫助大家理解他們是如何工作的。 數(shù)據(jù)集說明數(shù)據(jù)集來源于kaggle M5 Forecasting - Accuracy[1] 該任務(wù)是盡可能精確地預(yù)測沃爾瑪在美國銷售的各種產(chǎn)品的單位銷售額(demand)。本文將使用其中的一部分數(shù)據(jù)。 該數(shù)據(jù)樣例如下。 數(shù)據(jù)集的劃分需要根據(jù)交叉驗證基本原理來操作。首先需要將所有數(shù)據(jù)集劃分為訓(xùn)練集和測試集,再再訓(xùn)練集中利用交叉驗證劃分訓(xùn)練集和驗證集,如下圖所示。 首先按照日期date劃分測試集和訓(xùn)練集,如下圖所示。 為本次演示需求,創(chuàng)造了一些新的特征,最終篩選并使用了如下幾個變量。 Training columns: 設(shè)置如下兩個全局變量,以及用來存儲每種交叉驗證得分結(jié)果的DataFrame 交叉驗證交叉驗證(Cross Validation) 是在機器學(xué)習(xí)建立模型和驗證模型參數(shù)時常用的方法。顧名思義,就是重復(fù)的使用數(shù)據(jù),把得到的樣本數(shù)據(jù)進行切分,組合為不同的訓(xùn)練集和測試集。用訓(xùn)練集來訓(xùn)練模型,測試集來評估模型的好壞。 交叉驗證的目的
交叉驗證的種類根據(jù)切分的方法不同,交叉驗證分為下面三種: 第一種是簡單交叉驗證首先,隨機的將樣本數(shù)據(jù)分為兩部分(比如:70%的訓(xùn)練集,30%的測試集),然后用訓(xùn)練集來訓(xùn)練模型,在測試集上驗證模型及參數(shù)。接著再把樣本打亂,重新選擇訓(xùn)練集和測試集,繼續(xù)訓(xùn)練數(shù)據(jù)和檢驗?zāi)P汀W詈筮x擇損失函數(shù)評估最優(yōu)的模型和參數(shù)。 第二種是K折交叉驗證(K-Fold Cross Validation)和第一種方法不同, 折交叉驗證會把樣本數(shù)據(jù)隨機的分成 份,每次隨機的選擇 份作為訓(xùn)練集,剩下的1份做測試集。當(dāng)這一輪完成后,重新隨機選擇 份來訓(xùn)練數(shù)據(jù)。若干輪(小于 )之后,選擇損失函數(shù)評估最優(yōu)的模型和參數(shù)。 第三種是留一交叉驗證(Leave-one-out Cross Validation)它是第二種情況的特例,此時 等于樣本數(shù) ,這樣對于 個樣本,每次選擇 個樣本來訓(xùn)練數(shù)據(jù),留一個樣本來驗證模型預(yù)測的好壞。此方法主要用于樣本量非常少的情況,比如對于普通適中問題, 小于50時,一般采用留一交叉驗證。 下面將用圖解方法詳細介紹12種交叉驗證方法,主要參考scikit-learn官網(wǎng)[2]介紹。 交叉驗證器01 K折交叉驗證--沒有打亂折交叉驗證器 KFold,提供訓(xùn)練/驗證索引以拆分訓(xùn)練/驗證集中的數(shù)據(jù)。將數(shù)據(jù)集拆分為 個連續(xù)的折疊(默認情況下不改組)。然后將每個折疊用作一次驗證,而剩余的 個折疊形成訓(xùn)練集。 from sklearn.model_selection import KFold不建議使用這種類型的交叉驗證來處理時間序列數(shù)據(jù),因為它忽略了數(shù)據(jù)的連貫性。實際的測試數(shù)據(jù)是將來的一個時期。 如下圖所示,黑色部分為被用作的驗證的一個折疊,而黃色部分為被用作訓(xùn)練的 個折疊。 另外數(shù)據(jù)分布圖是5折交叉驗證中每個驗證數(shù)據(jù)集(黑色部分),及實際用作驗證模型的數(shù)據(jù)集的組合分布圖。 02 K折交叉驗證--打亂的K折交叉驗證器KFold設(shè)置參數(shù) from sklearn.model_selection import KFold在每次迭代中,五分之一的數(shù)據(jù)仍然是驗證集,但這一次它是隨機分布在整個數(shù)據(jù)中。與前面一樣,在一個迭代中用作驗證的每個示例永遠不會在另一個迭代中用作驗證。 如下圖所示,黑色部分為被用作驗證的數(shù)據(jù)集,很明顯,驗證集數(shù)據(jù)是被打亂了的。 03 隨機排列交叉驗證隨機排列交叉驗證器ShuffleSplit,生成索引以將數(shù)據(jù)拆分為訓(xùn)練集和驗證集。 注意:與其他交叉驗證策略相反,隨機拆分并不能保證所有折疊都會不同,盡管對于大型數(shù)據(jù)集來說z這是很有可能。 from sklearn.model_selection import ShuffleSplitShuffleSplit將在每次迭代過程中隨機抽取整個數(shù)據(jù)集,生成一個訓(xùn)練集和一個驗證集。 由于部分數(shù)據(jù)未包含在訓(xùn)練中,該方法比普通的k倍交叉驗證更快。 如下圖所示,黑色部分為被用作驗證的數(shù)據(jù)集,橙色是被用作訓(xùn)練的數(shù)據(jù)集,而白色部分為未被包含在訓(xùn)練和驗證集中的數(shù)據(jù)集。 04 分層K折交叉驗證--沒有打亂分層 折交叉驗證器StratifiedKFold。 提供訓(xùn)練/驗證索引以拆分訓(xùn)練/驗證集中的數(shù)據(jù)。這個交叉驗證對象是 from sklearn.model_selection import StratifiedKFold就跟普通的 折交叉驗證類似,但是每折包含每個目標(biāo)樣本的大約相同的百分比。更好地使用分類而不是回歸。 其中有幾點需要注意:
如下圖所示,在沒有打亂的情況下,驗證集(圖中黑色部分)分布是有一定的規(guī)律的。 且從下面的數(shù)據(jù)分布圖可見,5折交叉驗證數(shù)據(jù)密度分布曲線基本重合,說明雖然劃分的樣本不同,但其分布基本一致。 05 分層K折交叉驗證--打亂的對于每個目標(biāo),折疊包大約相同百分比的樣本,但首先數(shù)據(jù)被打亂。這里需要注意的是,該交叉驗證的拆分數(shù)據(jù)方法是一致的,僅僅是在拆分前,先打亂數(shù)據(jù)的排列,再進行分層 折交叉驗證。 from sklearn.model_selection import StratifiedKFold 如下圖所示,打亂的分層K折交叉驗證的驗證集是沒有規(guī)律、隨機分布的。 該交叉驗證的數(shù)據(jù)分布與未被打亂的分層K折交叉驗證基本一致。 06 分組K折交叉驗證具有非重疊組的 折迭代器變體GroupKFold。 同一組不會出現(xiàn)在兩個不同的折疊中(不同組的數(shù)量必須至少等于折疊的數(shù)量)。這些折疊是近似平衡的,因為每個折疊中不同組的數(shù)量是近似相同的。 可以從數(shù)據(jù)集的另一特定列(年)來定義組。確保同一組中不同時處于訓(xùn)練集和驗證集中。 該交叉驗證器分組是在方法 from sklearn.model_selection import GroupKFold如下圖所示,由于數(shù)據(jù)集原因(不是包含5個整年(組)),因此5折交叉驗證中,并不能保證沒次都包含相同數(shù)據(jù)數(shù)量的驗證集。 在上一個示例中,我們使用年作為組,在下一個示例中使用月作為組。大家可以通過下面圖可以很明顯地看看有什么區(qū)別。 from sklearn.model_selection import GroupKFold如下圖所示,每次迭代均是以月為組來取驗證集。 ![]() 07 分組K折交叉驗證--留一組留一組交叉驗證器LeaveOneGroupOut。 根據(jù)第三方提供的整數(shù)組數(shù)組保留樣本。此組信息可用于編碼任意特定于域的預(yù)定義交叉驗證折疊。 因此,每個訓(xùn)練集由除與特定組相關(guān)的樣本之外的所有樣本構(gòu)成。 例如,組可以是樣本收集的年份、月份等,因此允許針對基于時間的拆分進行交叉驗證。 from sklearn.model_selection import LeaveOneGroupOut在每次迭代中,模型都使用留一組之外的所有組的樣本進行訓(xùn)練。如果以月份為組,則執(zhí)行12次迭代。 由下圖可以看到該分組K折交叉驗證的拆分數(shù)據(jù)方法。 ![]() 08 分組K折交叉驗證--留N組LeavePGroupsOut將 LeavePGroupsOut 和 LeaveOneGroupOut 的區(qū)別在于,前者使用所有樣本分配到 通過參數(shù) from sklearn.model_selection import LeavePGroupsOut由下圖可知,因 ![]() 09 隨機排列的分組K折交叉驗證Shuffle-Group(s)-Out 交叉驗證迭代器GroupShuffleSplit GroupShuffleSplit迭代器為ShuffleSplit和LeavePGroupsOut的兩種方法的結(jié)合,并生成一個隨機分區(qū)序列,其中每個分區(qū)都會保留組的一個子集。 例如,組可以是樣本收集的年份,因此允許針對基于時間的拆分進行交叉驗證。 LeavePGroupsOut 和 GroupShuffleSplit 之間的區(qū)別在于,前者使用大小 例如,與 注意:參數(shù) 定義組,并在每次迭代中隨機抽樣整個數(shù)據(jù)集,以生成一個訓(xùn)練集和一個驗證集。 from sklearn.model_selection import GroupShuffleSplit從圖中可見,斷開(白色)部分為未取到的數(shù)據(jù)集,每一行中每段(以白色空白為界)中驗證集(黑色)比例及位置都是一致的。而不同行之間驗證集的位置是不同的。 ![]() 10 時間序列交叉驗證時間序列數(shù)據(jù)的特征在于時間上接近的觀測值之間的相關(guān)性(自相關(guān))。然而,經(jīng)典的交叉驗證技術(shù),例如 KFold 和 ShuffleSplit假設(shè)樣本是獨立的和同分布的,并且會導(dǎo)致時間序列數(shù)據(jù)的訓(xùn)練和測試實例之間不合理的相關(guān)性(產(chǎn)生對泛化誤差的不良估計)。 因此,在“未來”觀察中評估我們的模型的時間序列數(shù)據(jù)非常重要,這與用于訓(xùn)練模型的觀察最不相似。為了實現(xiàn)這一點,提供了一種解決方案TimeSeriesSplit。 TimeSeriesSplit是KFold的變體,它首先返回 折疊成訓(xùn)練集和 第 折疊作為驗證集。請注意,與標(biāo)準交叉驗證方法不同,連續(xù)訓(xùn)練集是它們之前的超集。此外,它將所有剩余數(shù)據(jù)添加到第一個訓(xùn)練分區(qū),該分區(qū)始終用于訓(xùn)練模型。 from sklearn.model_selection import TimeSeriesSplit這種方法建議用于時間序列數(shù)據(jù)。在時間序列分割中,訓(xùn)練集通常分為兩部分。第一部分始終是訓(xùn)練集,而后一部分是驗證集。 由下圖可知,驗證集的長度保持不變,而訓(xùn)練集隨著每次迭代的不斷增大。 ![]() 11 封閉時間序列交叉驗證這是自定義的一種交叉驗證方法。該方法函數(shù)見文末函數(shù)附錄。 btscv = BlockingTimeSeriesSplit(n_splits=NFOLDS)由下圖可見,訓(xùn)練和驗證集在每次迭代中都是唯一的。沒有值被使用兩次。列車集總是在驗證之前。由于在較少的樣本中訓(xùn)練,它也比其他交叉驗證方法更快。 ![]() 12 清除K折交叉驗證這是基于_BaseKFold的一種交叉驗證方法。在每次迭代中,在訓(xùn)練集之前和之后,我們會刪除一些樣本。 cont = pd.Series(train.index)由下圖可看出,訓(xùn)練集前后刪除了一些樣本。且其劃分訓(xùn)練集和驗證集的方法與基礎(chǔ)不打亂的 ![]() 將 cont = pd.Series(train.index)由下圖可看出,不僅在訓(xùn)練集前后刪除了部分樣本,在驗證集后面也刪除了一些樣本,這些樣本的大小將取決于參數(shù) ![]() 各交叉驗證結(jié)果比較cm = sns.light_palette('green', as_cmap=True, reverse=True)![]() 附錄封閉時間序列交叉驗證函數(shù)清除K折交叉驗證函數(shù)from sklearn.model_selection._split import _BaseKFold參考資料數(shù)據(jù)集: https://www./c/m5-forecasting-accuracy [2]交叉驗證: https:///stable/modules/classes.html |
|
|