python划分训练集、验证集和测试集
機器學習簡單流程:
我們最終的目的是將訓練好的模型部署到真實的環境中,希望訓練好的模型能夠在真實的數據上得到好的預測效果,換句話說就是希望模型在真實數據上預測的結果誤差越小越好。我們把模型在真實環境中的誤差叫做泛化誤差,最終的目的是希望訓練好的模型泛化誤差越低越好。
我們希望通過某個信號來了解模型的泛化誤差,這樣就可以指導我們得到泛化能力更強的模型:
1.訓練集與測試集
前面說到我們既不能通過直接將泛化誤差作為了解模型泛化能力的信號,因為在部署環境和訓練模型之間往復,代價很高,也不能使用模型對訓練數據集的擬合程度來作為了解模型泛化能力的信號,因為我們獲得的數據往往不干凈。
更好的方式就是將數據分割成兩部分:訓練集和測試集。我們可以使用訓練集的數據來訓練模型,然后用測試集上的誤差作為最終模型在應對現實場景中的泛化誤差。有了測試集,我們想要驗證模型的最終效果,只需將訓練好的模型在測試集上計算誤差,即可認為此誤差即為泛化誤差的近似,我們只需讓我們訓練好的模型在測試集上的誤差最小即可。
這里有幾點需要注意:
前面說了這么多,那如何劃分數據集為訓練集和測試集呢?其實很簡單,可以自己編寫程序,也可以使用sklearn提供的模塊:
通過簡單代碼實現:
import numpy as np def split_train_test(data,test_ratio):#設置隨機數種子,保證每次生成的結果都是一樣的np.random.seed(42)#permutation隨機生成0-len(data)隨機序列shuffled_indices = np.random.permutation(len(data))#test_ratio為測試集所占的半分比test_set_size = int(len(data)) * test_ratiotest_indices = shuffled_indices[:test_ratio]train_indices = shuffled_indices[test_set_size:]#iloc選擇參數序列中所對應的行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實現:
from sklearn.model_selection import train_test_split #data:需要進行分割的數據集 #random_state:設置隨機種子,保證每次運行生成相同的隨機數 #test_size:將數據分割成訓練集的比例 train_set, test_set = train_test_split(data, test_size=0.2, random_state=42)前面介紹的兩種分割數據集的方式都是采用純隨機的采樣方式,這種方式對于大量數據集以及對于目標值分布均勻的情況是可行的。比如對于分類任務,我們訓練一個二值分類器,可能數據中包含大量的正例樣本,僅僅包含10%的反例樣本,此時的標簽分布很不均勻,如果我們通過隨機采樣的方式,極端情況下可能將正例樣本都劃分到訓練集上,而反例樣本恰好都分到測試集,這樣訓練出來的模型,效果一定不會太好,所以我們需要采用分層采樣的方式進行劃分數據集,也就是說保證訓練集中既包含一定比例的正例樣本又要包含一定比例的負例樣本。
幸運的是sklearn提供了我們分層抽樣的函數,在這之前先看看官方提供的例子:
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] """通過上面的例子我們可以了解使用分層進行劃分數據集的大概流程,以及各個參數的含義:
- n_splits:分割迭代的次數,如果我們要劃分訓練集和測試集的話,將其設置為1即可;
- test_size:分割測試集的比例;
- random_state:設置隨機種子;
下面通過兩種方式對原始的mnist數據集進行劃分,首先要準備數據集:
from sklearn.datasets import fetch_mldata #我將最原始的mnist數據集下載到當前路徑下,指定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)- 使用隨機采樣的方式分割數據集:
- 使用分層采樣的方式分割數據集:
如果想要知道抽取的各個樣本的比例,你可以將數據轉換成DataFrame對象(當然在處理數據的開始你也可以將數據轉換為DataFrame方便操作):
#將分割后的訓練數據轉換為DataFrame #這里的參數data可以是分割之后的訓練集或者測試集 train_data = pd.DataFrame(train_set) #快速查看對數據的描述 train_data.info() #查看各個類別的比例 print(train_data[784].value_counts() / len(train_data))下面各圖分別是:原始數據10個類別所占的比例、隨機采樣訓練集中10個類別所占比例以及分層采樣訓練集中10個類別所占的比例(當然也可以對測試集進行統計)。
統計對比
通過上面的分析可以看出,分層采樣出的10個類別所占的比例和原數據中的10個類別所占的比例很接近。
2.驗證集
前面說到我們將數據集劃分為訓練集和測試集,我們讓模型在訓練集上進行訓練,然后在測試集上來近似模型的泛化能力。我們如果想要挑選不同的模型的話,可以讓兩個模型分別在訓練集上訓練,然后將兩個訓練好的模型分別在測試集上進行測試,由于我們把測試集上的誤差近似近似為泛化誤差,所以我們自然可以選擇在測試集上誤差小的模型作為最終我們要選擇的泛化能力強的模型。
但是我們要做的不僅是不同的模型與模型之間的對比,很多時候我們需要對模型本身進行選擇,假如我們有兩個模型,線性模型和神經網絡模型,我們知道神經網絡的泛化能力要比線性模型要強,我們選擇了神經網絡模型,但是神經網絡中還有很多的需要人工進行選擇的參數,比如神經網絡的層數和每層神經網絡的神經元個數以及正則化的一些參數等等,我們將這些參數稱為超參數。這些參數不同選擇對模型最終的效果也很重要,我們在開發模型的時候總是需要調節這些超參數。
現在我們需要調節這些超參數來使得模型泛化能力最強。我們使用測試集來作為泛化誤差估計,而我們最終的目的就是選擇泛化能力強的模型,那么我們可以直接通過模型在測試集上的誤差來調節這些參數不就可以了。可能模型在測試集上的誤差為0,但是你拿著這樣的模型去部署到真實場景中去使用的話,效果可能會非常差。
這一現象叫做信息泄露。我們使用測試集作為泛化誤差的近似,所以不到最后是不能將測試集的信息泄露出去的,就好比考試一樣,我們平時做的題相當于訓練集,測試集相當于最終的考試,我們通過最終的考試來檢驗我們最終的學習能力,將測試集信息泄露出去,相當于學生提前知道了考試題目,那最后再考這些提前知道的考試題目,當然代表不了什么,你在最后的考試中得再高的分數,也不能代表你學習能力強。而如果通過測試集來調節模型,相當于不僅知道了考試的題目,學生還都學會怎么做這些題了(因為我們肯定會人為的讓模型在測試集上的誤差最小,因為這是你調整超參數的目的),那再拿這些題考試的話,人人都有可能考滿分,但是并沒有起到檢測學生學習能力的作用。原來我們通過測試集來近似泛化誤差,也就是通過考試來檢驗學生的學習能力,但是由于信息泄露,此時的測試集即考試無任何意義,現實中可能學生的能力很差。所以,我們在學習的時候,老師會準備一些小測試來幫助我們查缺補漏,這些小測試也就是要說的驗證集。我們通過驗證集來作為調整模型的依據,這樣不至于將測試集中的信息泄露。
也就是說我們將數據劃分訓練集、驗證集和測試集。在訓練集上訓練模型,在驗證集上評估模型,一旦找到的最佳的參數,就在測試集上最后測試一次,測試集上的誤差作為泛化誤差的近似。關于驗證集的劃分可以參考測試集的劃分,其實都是一樣的,這里不再贅述。
吳恩達老師的視頻中,如果當數據量不是很大的時候(萬級別以下)的時候將訓練集、驗證集以及測試集劃分為6:2:2;若是數據很大,可以將訓練集、驗證集、測試集比例調整為98:1:1;但是當可用的數據很少的情況下也可以使用一些高級的方法,比如留出方,K折交叉驗證等。
?
參考:1.《Hands-On Machine Learning with Scikit-Learn and TensorFlow》
總結
以上是生活随笔為你收集整理的python划分训练集、验证集和测试集的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android studio x5,an
- 下一篇: websocket python爬虫_p