【Python機器學習及實踐】進階篇:模型實用技巧(模型檢驗與超參數搜索)

 Python機器學習及實踐——進階篇:模型實用技巧

(模型檢驗與超參數搜索)


1.模型檢驗

在真正實踐機器學習任務的時候,我們並不可能直到正確答案。這就要求我們充分利用現有數據,並且通常的做法依然是對現有數據進行採樣分割:一部分用於模型參數訓練,叫做訓練集(Training set);另一部分數據集合用於調優模型配置和特徵選擇,並且對未知的測試性能做出評估,叫做開發集(Development set)或者驗證集(Validation set)。

1.1留一驗證

留一驗證(Leave-one-out cross validation)就是從任務提供的數據中,隨機採樣一定比例作爲訓練集,剩下的"留做"驗證。通常,這個比例爲7:3,即70%作爲訓練集,30%作爲驗證集。但是,這一方法的模型性能不穩定,原因在於對驗證集合隨機採樣的不確定性。

1.2交叉驗證

交叉驗證(K-fold cross-validation)可理解爲多次留一驗證的過程。需要強調的是,每次檢驗所使用的驗證集之間是互斥的,並且要保證每一條可用數據都被模型驗證過。以5折交叉驗證(5-fold cross-validation)爲例,全部可用數據被隨機分割爲平均數量的5組,每次迭代都選取其中的1組數據作爲驗證集,其他4組作爲訓練集。

交叉驗證的好處在於,可以保證所有數據都有被訓練和驗證的機會,也盡最大可能讓優化的模型性能表現得更加可信。

2.超參數搜索

前面提到的模型參數,一般統稱爲模型的超參數(Hyperparameters),如K近鄰算法中的K值,SVM中的核函數等。多數情況先,超參數的選擇是無限的。因此在有限的時間內,除了可以驗證預設幾種超參數組合以外,也可以通過啓發式的搜索方式對超參數組合進行調優(網格搜索),同時由於超參數的驗證過程之間彼此獨立,因此爲並行計算提供了可能(並行搜索)

2.1網格搜索

由於超參數的空間是無盡的,因此超參數的組合配置只能是"更優"解,沒有最優解。通常情況下,依靠網格搜索(GridSearch)對多種超參數組合的空間進行暴力搜索。每一套超參數組合被代入到學習函數中作爲新的模型,並且爲了比較新模型之間的性能,每個模型都會採用交叉驗證的方法在多組相同的訓練和開發數據集下進行評估。

使用單線程對文本分類的樸素貝葉斯模型的超參數組合執行網格搜素

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@File  : GridSearch.py
@Author: Xinzhe.Pang
@Date  : 2019/7/24 23:48
@Desc  : 
"""
import numpy as np
# 從sklearn.datasets中導入20類新聞文本抓取器
from sklearn.datasets import fetch_20newsgroups
# 分割數據集
from sklearn.model_selection import train_test_split
# 導入支持向量機分類模型
from sklearn.svm import SVC
# 導入TfidfVectorizer文本抽取器
from sklearn.feature_extraction.text import TfidfVectorizer
# 導入Pipeline
from sklearn.pipeline import Pipeline
# 從sklearn.grid_search中導入網格搜索模塊GridSearchCV
from sklearn.model_selection import GridSearchCV

# 使用新聞抓取器從互聯網上下載所有數據
news = fetch_20newsgroups(subset='all')

# 對前3000條新聞文本進行數據分割,25%文本用於測試
X_train, X_test, y_train, y_test = train_test_split(news.data[:3000], news.target[:3000], test_size=0.25,
                                                    random_state=33)
# 使用Pipline 簡化系統搭建流程 將文本抽取與分類器模型串聯起來
clf = Pipeline([('vect', TfidfVectorizer(stop_words='english', analyzer='word')), ('svc', SVC())])

# 超參數svc_gamma有4個 svc_C有3個 超參數組合一共有12種  使用np.logspace函數來選取超參數
parameters = {'svc__gamma': np.logspace(-2, 1, 4), 'svc__C': np.logspace(-1, 1, 3)}
gs = GridSearchCV(clf, parameters, verbose=2, refit=True, cv=3)

gs.fit(X_train, y_train)
gs.best_params_, gs.best_score_

print(gs.score(X_test, y_test))

在交叉驗證獲取最佳的超參數過程中,如果設定refit=True,那麼程序將會以交叉訓練集得到的最佳超參數,重新對所有可用的訓練集和開發集進行,作爲最終用於性能評估的最佳模型的參數。

2.2並行搜索

由於各個新模型在執行交叉驗證的過程中間是相互獨立的,所以可以充分利用多核處理器(Multicore processor)甚至是分佈式計算資源來從事並行搜索(Parallel Grid Search),這樣能夠成倍地節省運算時間。

使用多個線程對文本分類的樸素貝葉斯模型的超參數組合執行並行化的網格搜索

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@File  : ParallelGridSearch.py
@Author: Xinzhe.Pang
@Date  : 2019/7/25 0:39
@Desc  : 
"""
import numpy as np
# 從sklearn.datasets中導入20類新聞文本抓取器
from sklearn.datasets import fetch_20newsgroups
# 分割數據集
from sklearn.model_selection import train_test_split
# 導入支持向量機分類模型
from sklearn.svm import SVC
# 導入TfidfVectorizer文本抽取器
from sklearn.feature_extraction.text import TfidfVectorizer
# 導入Pipeline
from sklearn.pipeline import Pipeline
# 從sklearn.grid_search中導入網格搜索模塊GridSearchCV
from sklearn.model_selection import GridSearchCV

# 使用新聞抓取器從互聯網上下載所有數據
news = fetch_20newsgroups(subset='all')

# 選取前3000條數據
X_train, X_test, y_train, y_test = train_test_split(news.data[:3000], news.target[:3000], test_size=0.25,
                                                    random_state=33)

# 使用Pipline 簡化系統搭建流程 將文本抽取與分類器模型串聯起來
clf = Pipeline([('vect', TfidfVectorizer(stop_words='english', analyzer='word')), ('svc', SVC())])

# 超參數svc_gamma有4個 svc_C有3個 超參數組合一共有12種  使用np.logspace函數來選取超參數
parameters = {'svc__gamma': np.logspace(-2, 1, 4), 'svc__C': np.logspace(-1, 1, 3)}
# 初始化配置並行網格搜索 n_jobs=-1代表使用該計算機的全部CPU
gs = GridSearchCV(clf, parameters, verbose=2, refit=True, cv=3, n_jobs=-1)

gs.fit(X_train, y_train)
gs.best_params_, gs.best_score_

print(gs.score(X_test, y_test))

報錯:ImportError: [joblib] Attempting to do parallel computing without protecting your import on a system that does not support forking. To use parallel-computing in a script, you must protect your main loop using "if __name__ == '__main__'". Please see the joblib documentation on Parallel for more information

解決方法:

# 超參數svc_gamma有4個 svc_C有3個 超參數組合一共有12種  使用np.logspace函數來選取超參數
if __name__ == '__main__':
    parameters = {'svc__gamma': np.logspace(-2, 1, 4), 'svc__C': np.logspace(-1, 1, 3)}
    # 初始化配置並行網格搜索 n_jobs=-1代表使用該計算機的全部CPU
    gs = GridSearchCV(clf, parameters, verbose=2, refit=True, cv=3, n_jobs=-1)
    gs.fit(X_train, y_train)
    gs.best_params_, gs.best_score_
    print(gs.score(X_test, y_test))

使用多線程並行搜索技術對樸素貝葉斯模型在文本分類任務中的超參數組合進行調優,可以有效地利用過核心計算機資源,節省了最佳超參數組合的搜索時間。 

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