当前位置:网站首页>scikit-learn構建模型的萬能模板

scikit-learn構建模型的萬能模板

2022-04-23 13:58:00 白日夢想家_胖七七

前言

這篇文章是我在微信公眾號深度學習初學者上面看到的,《機器學習入門必看|使用scikit-learn構建模型的萬能模板》,感覺十分適合初學者。為防止文章連接失效,特在此記錄文章主要內容,也將該公眾號强烈安利給大家!

機器學習入門必看|使用scikit-learn構建模型的萬能模板

1.明確你需要解决的問題是什麼類型,以及知道解决該類型問題所對應的算法。

常見的問題類型只有三種:分類、回歸、聚類。

分類:如果你需要通過輸入數據得到一個類別變量,那就是分類問題;分成兩類就是二分類,分成兩類以上就是多分類問題。比如,判別一個郵件是否是垃圾郵件、根據圖片分辨圖片裏的是猫還是狗等。

回歸:如果你需要通過輸入數據得到一個具體的連續數值,那就是回歸問題。比如,預測某個區域的房價等。

聚類:如果你的數據集並沒有對應的屬性標簽,你要做的,是發掘這組樣本在空間的分布,比如分析哪些樣本靠的更近,哪些樣本之間離得很遠。

2.調用算法構建模型(萬能模板1.0)

(1) 加載數據集(加載了scikit-learn自帶的鳶尾花數據集)

from sklearn.datasets import load_iris
data = load_iris()
x = data.data
y = data.target

(2) 數據集拆分

from sklearn.model_selection import train_test_split
train_x,test_x,train_y,test_y = train_test_split(x,y,test_size=0.1,random_state=0)

萬能模板1.0 (助你快速構建一個基本的算法模型) 

不同的算法只是改變了名字,以及模型的參數不同而已。

有了這個萬能模板,接下來就是簡單的複制粘貼改名字了:

而且在scikit-learn中,每個包的比特置都是有規律的,比如:隨機森林就是在集成學習文件夾下。

模板1.0應用案例

1、構建SVM分類模型

通過查閱資料,我們知道svm算法在scikit-learn.svm.SVC下,所以:

  1. 算法比特置填入:svm

  2. 算法名填入:SVC()

  3. 模型名自己起,這裏我們就叫svm_model

套用模板得到程序如下:

# svm分類器

from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

svm_model = SVC()

svm_model.fit(train_x,train_y)

pred1 = svm_model.predict(train_x)
accuracy1 = accuracy_score(train_y,pred1)
print('在訓練集上的精確度: %.4f'%accuracy1)

pred2 = svm_model.predict(test_x)
accuracy2 = accuracy_score(test_y,pred2)
print('在測試集上的精確度: %.4f'%accuracy2)

輸出:

在訓練集上的精確度: 0.9810
在測試集上的精確度: 0.9778

2、構建LR分類模型

同理,找到LR算法在sklearn.linear_model.LogisticRegression下,所以:

  1. 算法比特置填入:linear_model

  2. 算法名填入:LogisticRegression

  3. 模型名叫做:lr_model。

程序如下:

套用模板得到程序如下:

# LogisticRegression分類器

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score #評分函數用精確度評估

lr_model = LogisticRegression()

lr_model.fit(train_x,train_y)

pred1 = lr_model.predict(train_x)
accuracy1 = accuracy_score(train_y,pred1)
print('在訓練集上的精確度: %.4f'%accuracy1)

pred2 = lr_model.predict(test_x)
accuracy2 = accuracy_score(test_y,pred2)
print('在測試集上的精確度: %.4f'%accuracy2)

輸出:

在訓練集上的精確度: 0.9429
在測試集上的精確度: 0.8889

3、構建隨機森林分類模型

隨機森林算法在sklearn.ensemble.RandomForestClassifier 下。

3.改進模板(萬能模板2.0)

加入交叉驗證,讓算法模型評估更加科學

在1.0版的模板中,當你多次運行同一個程序就會發現:每次運行得到的精確度並不相同,而是在一定範圍內浮動,這是因為數據輸入模型之前會進行選擇,每次訓練時數據輸入模型的順序都不一樣。所以即使是同一個程序,模型最後的錶現也會有好有壞。

更糟糕的是,有些情况下,在訓練集上,通過調整參數設置使模型的性能達到了最佳狀態,但在測試集上卻可能出現過擬合的情况。這個時候,我們在訓練集上得到的評分不能有效反映出模型的泛化性能。

為了解决上述兩個問題,還應該在訓練集上劃分出驗證集(validation set)並結合交叉驗證來解决。首先,在訓練集中劃分出不參與訓練的驗證集,只是在模型訓練完成以後對模型進行評估,接著再在測試集上進行最後的評估。

但這樣大大减少了可用於模型學習的樣本數量,所以還需要采用交叉驗證的方式多訓練幾次。比如說最常用的k-折交叉驗證如下圖所示,它主要是將訓練集劃分為 k 個較小的集合。然後將k-1份訓練子集作為訓練集訓練模型,將剩餘的 1 份訓練集子集作為驗證集用於模型驗證。這樣需要訓練k次,最後在訓練集上的評估得分取所有訓練結果評估得分的平均值。

這樣一方面可以讓訓練集的所有數據都參與訓練,另一方面也通過多次計算得到了一個比較有代錶性的得分。唯一的缺點就是計算代價很高,增加了k倍的計算量。

原理就是這樣,但理想很豐滿,現實很骨幹。在自己實現的時候卻有一個很大的難題擺在面前:怎麼能够把訓練集均勻地劃分為K份?

這個問題不用思考太多,既然別忘了,我們現在是站在巨人的肩膀上,scikit-learn已經將優秀的數學家所想到的均勻拆分方法和程序員的智慧融合在了cross_val_score() 這個函數裏了,只需要調用該函數即可,不需要自己想什麼拆分算法,也不用寫for循環進行循環訓練。

萬能模板V2.0版

把模型、數據、劃分驗證集的個數一股腦輸入函數,函數會自動執行上邊所說的過程。

在求精確度的時候,我們可以簡單地輸出平均精確度:

# 輸出精確度的平均值
# print("訓練集上的精確度: %0.2f " % scores1.mean())

 但是既然我們進行了交叉驗證,做了這麼多計算量,單求一個平均值還是有點浪費了,可以利用下邊代碼捎帶求出精確度的置信度:

# 輸出精確度的平均值和置信度區間
print("訓練集上的平均精確度: %0.2f (+/- %0.2f)" % (scores2.mean(), scores2.std() * 2))

模板2.0應用案例:

1、構建SVM分類模型

程序如下:

### svm分類器

from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC

svm_model = SVC()
svm_model.fit(train_x,train_y)

scores1 = cross_val_score(svm_model,train_x,train_y,cv=5, scoring='accuracy')
# 輸出精確度的平均值和置信度區間
print("訓練集上的精確度: %0.2f (+/- %0.2f)" % (scores1.mean(), scores1.std() * 2))

scores2 = cross_val_score(svm_model,test_x,test_y,cv=5, scoring='accuracy')
# 輸出精確度的平均值和置信度區間
print("測試集上的平均精確度: %0.2f (+/- %0.2f)" % (scores2.mean(), scores2.std() * 2))


print(scores1)
print(scores2)

輸出:

訓練集上的精確度: 0.97 (+/- 0.08)
測試集上的平均精確度: 0.91 (+/- 0.10)
[1. 1. 1. 0.9047619 0.94736842]
[1. 0.88888889 0.88888889 0.875 0.875 ]

2、構建LR分類模型

# LogisticRegression分類器

from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression


lr_model = LogisticRegression()
lr_model.fit(train_x,train_y)

scores1 = cross_val_score(lr_model,train_x,train_y,cv=5, scoring='accuracy')
# 輸出精確度的平均值和置信度區間
print("訓練集上的精確度: %0.2f (+/- %0.2f)" % (scores1.mean(), scores1.std() * 2))

scores2 = cross_val_score(lr_model,test_x,test_y,cv=5, scoring='accuracy')
# 輸出精確度的平均值和置信度區間
print("測試集上的平均精確度: %0.2f (+/- %0.2f)" % (scores2.mean(), scores2.std() * 2))

print(scores1)
print(scores2)

輸出:

訓練集上的精確度: 0.94 (+/- 0.07)
測試集上的平均精確度: 0.84 (+/- 0.14)
[0.90909091 1. 0.95238095 0.9047619 0.94736842]
[0.90909091 0.88888889 0.88888889 0.75 0.75 ]

注: 如果想要一次性評估多個指標,也可以使用可以一次性輸入多個評估指標的 cross_validate()函數。

4.調參改進(萬能模板3.0) 

調參讓算法錶現更上一層樓

以上都是通過算法的默認參數來訓練模型的,不同的數據集適用的參數難免會不一樣,自己設計算法是設計不來的,只能調調參這樣子,調參,是廣大算法工程師最後的尊嚴。再說,若是做算法不調參,豈不是辱沒了算法工程師在江湖上大名鼎鼎的“煉丹工程師”的名聲?

scikit-learn對於不同的算法也提供了不同的參數可以自己調節。如果細說起來,又能寫好幾篇文章,本文目的是構建一個萬能算法框架構建模板,所以,這裏只介紹一下一個通用的自動化調參方法,至於更細節的每個算法對應參數的含義以及手動調參方法,會在以後的文章中結合實例具體慢慢介紹。

首先要明確的是,scikit-learn提供了算法().get_params()方法來查看每個算法可以調整的參數,比如說,我們想查看SVM分類器算法可以調整的參數,可以:

SVC().get_params()

輸出的就是SVM算法可以調節的參數以及系統默認的參數值。每個參數的具體含義會在以後的文章中介紹。

{'C': 1.0,
'cache_size': 200,
'class_weight': None,
'coef0': 0.0,
'decision_function_shape': 'ovr',
'degree': 3,
'gamma': 'auto',
'kernel': 'rbf',
'max_iter': -1,
'probability': False,
'random_state': None,
'shrinking': True,
'tol': 0.001,
'verbose': False}

接著,就可以引出我們的V3.0版萬能模板了。

萬能模板3.0

參數的形式如下:

程序就會按照順序測試這幾個參數的組合效果,根本不需要自己辛辛苦苦實現。寫到這裏,感謝各為大佬編寫了scikit-learn這麼方便的機器學習包。忽然就想到了一句話:哪有什麼歲月靜好,只是因為有人替你負重前行。

看到這裏,可能有人會有疑惑:為什麼要采用列錶、字典、列錶三層嵌套的方式呢?params直接是字典的形式不行嗎?答案是:行,但是不好。

讓我們先算一個小的數學題:假如我們要調節n個參數,每個參數有4個備選值。那麼程序就會訓練  。當n為10的時候, ,這是一個對於計算機來說龐大的計算量。而當我們將這10個參數拆分成5組,每次只調節兩個參數,其他參數采用默認值,那麼計算量就是  ,計算量會大大减少。

列錶的作用這是如此,保證了每次只調節列錶中的一個字典中的參數。

運行之後,best_model就是我們得到的最優模型,可以利用這個模型進行預測。

當然,best_model 還有好多好用的屬性:

  • best_model.cv_results_:可以查看不同參數情况下的評價結果。

  • best_model.param_ :得到該模型的最優參數

  • best_model.best_score_: 得到該模型的最後評分結果

    模板3.0應用案例

    實現SVM分類器

    ###1、svm分類器
    from sklearn.model_selection import cross_val_score,GridSearchCV
    from sklearn.svm import SVC
    
    svm_model = SVC()
    
    params = [
            {'kernel': ['linear'], 'C': [1, 10, 100, 100]},
            {'kernel': ['poly'], 'C': [1], 'degree': [2, 3]},
            {'kernel': ['rbf'], 'C': [1, 10, 100, 100], 'gamma':[1, 0.1, 0.01, 0.001]}
            ]
    
    
    best_model = GridSearchCV(svm_model, param_grid=params,cv = 5,scoring = 'accuracy')
    best_model.fit(train_x,train_y)
    

    1)查看最優得分:

    best_model.best_score_
    

    輸出:

    0.9714285714285714

    2)查看最優參數:

    best_model.best_params_ 
    

    輸出:

    {'C': 1, 'kernel': 'linear'}

    3)查看最優模型的所有參數:

    best_model.best_estimator_ 
    

    這個函數會顯示出沒有調參的參數,便於整體查看模型的參數。

    4)查看每個參數的交叉驗證結果:

    best_model.cv_results_
    
    注:
    1、以前版本是best_model.grid_scores_,現在已經移除
    2、這個函數輸出很多數據,不方便查看,一般不用
    

    在實際使用中,如果計算資源够用,一般采用第三種萬能公式。如果,為了節約計算資源盡快算出結果,也會采用以後介紹的手動調參方式。

    當然,本文為了說明萬能模板的使用方法,在Iris數據集上將所有算法都實現了一遍,在實際應用中,如果項目時間緊急,根據自己的需求和數據量級選擇一個合適的算法使用即可。具體怎麼選擇,scikit-learn官方非常貼心地畫了一個圖,供大家根據數據量和算法類型選擇合適的模型,這副圖建議收藏:

    來源:https://zhuanlan.zhihu.com/p/88729124 

     

 

 

 

版权声明
本文为[白日夢想家_胖七七]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231358008257.html