训练集、验证集和测试集的比较
機(jī)器學(xué)習(xí)簡單流程:
? 我們最終的目的是將訓(xùn)練好的模型部署到真實(shí)的環(huán)境中,希望訓(xùn)練好的模型能夠在真實(shí)的數(shù)據(jù)上得到好的預(yù)測效果,換句話說就是希望模型在真實(shí)數(shù)據(jù)上預(yù)測的結(jié)果誤差越小越好。我們把模型在真實(shí)環(huán)境中的誤差叫做泛化誤差,最終的目的是希望訓(xùn)練好的模型泛化誤差越低越好。
我們希望通過某個(gè)信號(hào)來了解模型的泛化誤差,這樣就可以指導(dǎo)我們得到泛化能力更強(qiáng)的模型:
1.訓(xùn)練集與測試集
?
前面說到我們既不能通過直接將泛化誤差作為了解模型泛化能力的信號(hào),因?yàn)樵诓渴瓠h(huán)境和訓(xùn)練模型之間往復(fù),代價(jià)很高,也不能使用模型對(duì)訓(xùn)練數(shù)據(jù)集的擬合程度來作為了解模型泛化能力的信號(hào),因?yàn)槲覀儷@得的數(shù)據(jù)往往不干凈。
更好的方式就是將數(shù)據(jù)分割成兩部分:訓(xùn)練集和測試集。我們可以使用訓(xùn)練集的數(shù)據(jù)來訓(xùn)練模型,然后用測試集上的誤差作為最終模型在應(yīng)對(duì)現(xiàn)實(shí)場景中的泛化誤差。有了測試集,我們想要驗(yàn)證模型的最終效果,只需將訓(xùn)練好的模型在測試集上計(jì)算誤差,即可認(rèn)為此誤差即為泛化誤差的近似,我們只需讓我們訓(xùn)練好的模型在測試集上的誤差最小即可。
這里有幾點(diǎn)需要注意:
前面說了這么多,那如何劃分?jǐn)?shù)據(jù)集為訓(xùn)練集和測試集呢?其實(shí)很簡單,可以自己編寫程序,也可以使用sklearn提供的模塊:
import numpy as np def split_train_test(data,test_ratio):#設(shè)置隨機(jī)數(shù)種子,保證每次生成的結(jié)果都是一樣的np.random.seed(42)#permutation隨機(jī)生成0-len(data)隨機(jī)序列shuffled_indices = np.random.permutation(len(data))#test_ratio為測試集所占的百分比test_set_size = int(len(data) * test_ratio)test_indices = shuffled_indices[:test_set_size]train_indices = shuffled_indices[test_set_size:]#iloc選擇參數(shù)序列中所對(duì)應(yīng)的行return data.iloc[train_indices],data.iloc[test_indices]#測試 train_set,test_set = split_train_test(data,0.2) print(len(train_set), "train +", len(test_set), "test")通過sklearn實(shí)現(xiàn):
from sklearn.model_selection import train_test_split #data:需要進(jìn)行分割的數(shù)據(jù)集 #random_state:設(shè)置隨機(jī)種子,保證每次運(yùn)行生成相同的隨機(jī)數(shù) #test_size:將數(shù)據(jù)分割成訓(xùn)練集的比例 train_set, test_set = train_test_split(data, test_size=0.2, random_state=42)前面介紹的兩種分割數(shù)據(jù)集的方式都是采用純隨機(jī)的采樣方式,這種方式對(duì)于大量數(shù)據(jù)集以及對(duì)于目標(biāo)值分布均勻的情況是可行的。比如對(duì)于分類任務(wù),我們訓(xùn)練一個(gè)二值分類器,可能數(shù)據(jù)中包含大量的正例樣本,僅僅包含10%的反例樣本,此時(shí)的標(biāo)簽分布很不均勻,如果我們通過隨機(jī)采樣的方式,極端情況下可能將正例樣本都劃分到訓(xùn)練集上,而反例樣本恰好都分到測試集,這樣訓(xùn)練出來的模型,效果一定不會(huì)太好,所以我們需要采用分層采樣的方式進(jìn)行劃分?jǐn)?shù)據(jù)集,也就是說保證訓(xùn)練集中既包含一定比例的正例樣本又要包含一定比例的負(fù)例樣本。
幸運(yùn)的是sklearn提供了我們分層抽樣的函數(shù),在這之前先看看官方提供的例子:
from sklearn.model_selection import StratifiedShuffleSplit X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]]) y = np.array([0, 0, 1, 1]) split = StratifiedShuffleSplit(n_splits=3, test_size=0.5, random_state=0) print(split ) # doctest: +ELLIPSIS# StratifiedShuffleSplit(n_splits=3, random_state=0, ...) for train_index, test_index in split.split(X, y):print("TRAIN:", train_index, "TEST:", test_index)X_train, X_test = X[train_index], X[test_index]y_train, y_test = y[train_index], y[test_index]""" StratifiedShuffleSplit(n_splits=3, random_state=0, test_size=0.5,train_size=None) TRAIN: [1 2] TEST: [3 0] TRAIN: [0 2] TEST: [1 3] TRAIN: [0 2] TEST: [3 1] """通過上面的例子我們可以了解使用分層進(jìn)行劃分?jǐn)?shù)據(jù)集的大概流程,以及各個(gè)參數(shù)的含義:
- n_splits:分割迭代的次數(shù),如果我們要?jiǎng)澐钟?xùn)練集和測試集的話,將其設(shè)置為1即可;
- test_size:分割測試集的比例;
- random_state:設(shè)置隨機(jī)種子;
下面通過兩種方式對(duì)原始的mnist數(shù)據(jù)集進(jìn)行劃分,首先要準(zhǔn)備數(shù)據(jù)集:
from sklearn.datasets import fetch_mldata #我將最原始的mnist數(shù)據(jù)集下載到當(dāng)前路徑下,指定data_home mnist = fetch_mldata('MNIST original',data_home=r"./") x_data = mnist["data"].reshape((mnist["data"].shape[0],-1)) y_data = mnist["target"].reshape((mnist["target"].shape[0],-1)) print(x_data.shape) #(70000, 784) print(y_data.shape) #(70000, 1)使用隨機(jī)采樣的方式分割數(shù)據(jù)集:
#使用隨機(jī)采樣方式劃分?jǐn)?shù)據(jù)集 from sklearn.model_selection import train_test_split import numpy as npdata = np.hstack((x_data,y_data)) #先將數(shù)據(jù)集進(jìn)行拼接,要不然我們只針對(duì)樣本進(jìn)行采樣的話,會(huì)找不到對(duì)應(yīng)的標(biāo)簽的 train_set,test_set = train_test_split(data,test_size = 0.2,random_state = 42) print(len(train_set),len(test_set))""" 56000 14000 """- 使用分層采樣的方式分割數(shù)據(jù)集:
如果想要知道抽取的各個(gè)樣本的比例,你可以將數(shù)據(jù)轉(zhuǎn)換成DataFrame對(duì)象(當(dāng)然在處理數(shù)據(jù)的開始你也可以將數(shù)據(jù)轉(zhuǎn)換為DataFrame方便操作):
#將分割后的訓(xùn)練數(shù)據(jù)轉(zhuǎn)換為DataFrame #這里的參數(shù)data可以是分割之后的訓(xùn)練集或者測試集 train_data = pd.DataFrame(train_set) #快速查看對(duì)數(shù)據(jù)的描述 train_data.info() #查看各個(gè)類別的比例 print(train_data[784].value_counts() / len(train_data))2.驗(yàn)證集
前面說到我們將數(shù)據(jù)集劃分為訓(xùn)練集和測試集,我們讓模型在訓(xùn)練集上進(jìn)行訓(xùn)練,然后在測試集上來近似模型的泛化能力。我們?nèi)绻胍暨x不同的模型的話,可以讓兩個(gè)模型分別在訓(xùn)練集上訓(xùn)練,然后將兩個(gè)訓(xùn)練好的模型分別在測試集上進(jìn)行測試,由于我們把測試集上的誤差近似近似為泛化誤差,所以我們自然可以選擇在測試集上誤差小的模型作為最終我們要選擇的泛化能力強(qiáng)的模型。
但是我們要做的不僅是不同的模型與模型之間的對(duì)比,很多時(shí)候我們需要對(duì)模型本身進(jìn)行選擇,假如我們有兩個(gè)模型,線性模型和神經(jīng)網(wǎng)絡(luò)模型,我們知道神經(jīng)網(wǎng)絡(luò)的泛化能力要比線性模型要強(qiáng),我們選擇了神經(jīng)網(wǎng)絡(luò)模型,但是神經(jīng)網(wǎng)絡(luò)中還有很多的需要人工進(jìn)行選擇的參數(shù),比如神經(jīng)網(wǎng)絡(luò)的層數(shù)和每層神經(jīng)網(wǎng)絡(luò)的神經(jīng)元個(gè)數(shù)以及正則化的一些參數(shù)等等,我們將這些參數(shù)稱為超參數(shù)。這些參數(shù)不同選擇對(duì)模型最終的效果也很重要,我們在開發(fā)模型的時(shí)候總是需要調(diào)節(jié)這些超參數(shù)。
現(xiàn)在我們需要調(diào)節(jié)這些超參數(shù)來使得模型泛化能力最強(qiáng)。我們使用測試集來作為泛化誤差估計(jì),而我們最終的目的就是選擇泛化能力強(qiáng)的模型,那么我們可以直接通過模型在測試集上的誤差來調(diào)節(jié)這些參數(shù)不就可以了。可能模型在測試集上的誤差為0,但是你拿著這樣的模型去部署到真實(shí)場景中去使用的話,效果可能會(huì)非常差。
這一現(xiàn)象叫做信息泄露。我們使用測試集作為泛化誤差的近似,所以不到最后是不能將測試集的信息泄露出去的,就好比考試一樣,我們平時(shí)做的題相當(dāng)于訓(xùn)練集,測試集相當(dāng)于最終的考試,我們通過最終的考試來檢驗(yàn)我們最終的學(xué)習(xí)能力,將測試集信息泄露出去,相當(dāng)于學(xué)生提前知道了考試題目,那最后再考這些提前知道的考試題目,當(dāng)然代表不了什么,你在最后的考試中得再高的分?jǐn)?shù),也不能代表你學(xué)習(xí)能力強(qiáng)。而如果通過測試集來調(diào)節(jié)模型,相當(dāng)于不僅知道了考試的題目,學(xué)生還都學(xué)會(huì)怎么做這些題了(因?yàn)槲覀兛隙〞?huì)人為的讓模型在測試集上的誤差最小,因?yàn)檫@是你調(diào)整超參數(shù)的目的),那再拿這些題考試的話,人人都有可能考滿分,但是并沒有起到檢測學(xué)生學(xué)習(xí)能力的作用。原來我們通過測試集來近似泛化誤差,也就是通過考試來檢驗(yàn)學(xué)生的學(xué)習(xí)能力,但是由于信息泄露,此時(shí)的測試集即考試無任何意義,現(xiàn)實(shí)中可能學(xué)生的能力很差。所以,我們在學(xué)習(xí)的時(shí)候,老師會(huì)準(zhǔn)備一些小測試來幫助我們查缺補(bǔ)漏,這些小測試也就是要說的驗(yàn)證集。我們通過驗(yàn)證集來作為調(diào)整模型的依據(jù),這樣不至于將測試集中的信息泄露。
也就是說我們將數(shù)據(jù)劃分訓(xùn)練集、驗(yàn)證集和測試集。在訓(xùn)練集上訓(xùn)練模型,在驗(yàn)證集上評(píng)估模型,一旦找到的最佳的參數(shù),就在測試集上最后測試一次,測試集上的誤差作為泛化誤差的近似。關(guān)于驗(yàn)證集的劃分可以參考測試集的劃分,其實(shí)都是一樣的,這里不再贅述。
吳恩達(dá)老師的視頻中,如果當(dāng)數(shù)據(jù)量不是很大的時(shí)候(萬級(jí)別以下)的時(shí)候?qū)⒂?xùn)練集、驗(yàn)證集以及測試集劃分為6:2:2;若是數(shù)據(jù)很大,可以將訓(xùn)練集、驗(yàn)證集、測試集比例調(diào)整為98:1:1;但是當(dāng)可用的數(shù)據(jù)很少的情況下也可以使用一些高級(jí)的方法,比如留出方,K折交叉驗(yàn)證等。
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的训练集、验证集和测试集的比较的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RAW数据解析
- 下一篇: 【Antd】rawData.some i