機器學習2:錯誤與優化

1.錯誤類型

機器學習中常犯的兩個錯誤是,過於簡化模型,過於複雜化模型
e000

2.交叉驗證

之前將數據分爲訓練集和測試集,判定模型效果,實際上犯了一個錯誤,將測試集參與了模型判定。

爲更客觀的反映模型效果,引入一個新的子集,交叉驗證集。

一般複雜模型如下圖,訓練誤差越來越小,測試誤差開始很大,然後逐漸減小,然後再逐漸變大。

e001

左側欠擬合,右側過擬合。

3. K 折交叉驗證

將數據分成K份,然後訓練模型K次,每次輪流取不同的幾分數據作爲測試集,剩餘數據作爲訓練集,然後對結果取平均,得到最終的模型。

從SKLearn庫中調用K折交叉驗證很簡單,創建一個K折交叉驗證對象,其參數分別是數據的大小和測試集的大小,建議每次都隨機化數據,以消除任何偏差暗示,

e002

4.學習曲線

以訓練數據樣本數爲橫軸,誤差爲縱軸,畫出訓練集和交叉驗證集的誤差曲線

e003

在高偏差或欠擬合模型中,兩個曲線彼此逐漸靠近,收斂在高點;

好的模型中,兩個曲線彼此逐漸靠近,並且收斂在低點;

在高方差或過擬合模型中,兩個曲線不會彼此靠近,訓練誤差曲線保持在低位,而交叉驗證誤差曲線保持在高位;

這是區分欠擬合和過擬合的一種方法;

通過學習曲線檢測過擬合和欠擬合實例

做個測驗,我們將使用三個模型來訓練下面的圓形數據集。

決策樹模型,
邏輯迴歸模型,
支持向量機模型。

e004

其中一個模型會過擬合,一個欠擬合,還有一個正常。首先,我們將編寫代碼爲每個模型繪製學習曲線,最後我們將查看這些學習曲線,判斷每個模型對應哪個曲線。

我們將使用函數 learning_curve:

train_sizes, train_scores, test_scores = learning_curve(
    estimator, X, y, cv=None, n_jobs=1, train_sizes=np.linspace(.1, 1.0, num_trainings))

不需要擔心該函數的所有參數(你可以在此處瞭解詳情),這裏,我們將解釋主要參數:

estimator,是我們針對數據使用的實際分類器,例如 LogisticRegression() 或 GradientBoostingClassifier()。

X 和 y 是我們的數據,分別表示特徵和標籤。

train_sizes 是用來在曲線上繪製每個點的數據大小。

train_scores 是針對每組數據進行訓練後的算法訓練得分。

test_scores 是針對每組數據進行訓練後的算法測試得分。

兩個重要的現象:

a.訓練和測試得分是一個包含 3 個值的列表,這是因爲函數使用了 3 折交叉驗證。

b.非常重要:可以看出,我們使用訓練和測試誤差來定義我們的曲線,而這個函數使用訓練和測試得分來定義曲線。二者是相反的,因此誤差越高,得分就越低。因此,當你看到曲線時,你需要自己在腦中將它顛倒過來,以便與上面的曲線對比。

import matplotlib.pyplot as plt

%matplotlib inline

from sklearn.model_selection import learning_curve

# It is good to randomize the data before drawing Learning Curves
def randomize(X, Y):
    permutation = np.random.permutation(Y.shape[0])
    X2 = X[permutation,:]
    Y2 = Y[permutation]
    return X2, Y2

def draw_learning_curves(X, y, estimator, num_trainings,estimator_name):
    
    train_sizes, train_scores, test_scores = learning_curve(
        estimator, X2, y2, cv=None, n_jobs=1, train_sizes=np.linspace(.1, 1.0, num_trainings))

    train_scores_mean = np.mean(train_scores, axis=1)
    train_scores_std = np.std(train_scores, axis=1)
    test_scores_mean = np.mean(test_scores, axis=1)
    test_scores_std = np.std(test_scores, axis=1)

    plt.grid()

    plt.title("Learning Curves")
    plt.xlabel("Training examples_"+estimator_name)
    plt.ylabel("Score")

    plt.plot(train_scores_mean, 'o-', color="g",
             label="Training score")
    plt.plot(test_scores_mean, 'o-', color="y",
             label="Cross-validation score")


    plt.legend(loc="best")
    plt.savefig("./"+estimator_name+".png")
    plt.show()
# Import, read, and split data
import pandas as pd
data = pd.read_csv('data.csv')
import numpy as np


X = np.array(data[['x1', 'x2']])
y = np.array(data['y'])

# Fix random seed
np.random.seed(55)

### Imports
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.svm import SVC

# TODO: Uncomment one of the three classifiers, and hit "Test Run"
# to see the learning curve. Use these to answer the quiz below.

### Logistic Regression
#estimator = LogisticRegression()
#estimator_name = "LogisticRegression"

### Decision Tree
#estimator = GradientBoostingClassifier()
#estimator_name = "GradientBoostingClassifier"

### Support Vector Machine
estimator = SVC(kernel='rbf', gamma=1000)
estimator_name = "SVC"


num_trainings = len(y)/10
print(len(y),num_trainings)
X2, y2 = randomize(X, y)

draw_learning_curves( X, y,estimator,num_trainings,estimator_name)
100 10.0

output_6_2

分別獲得曲線:

在這裏插入圖片描述

我們可以根據這些曲線得出結論:

對數機率迴歸模型的訓練和測試得分很低。

決策樹模型的訓練和測試得分很高。

支持向量機模型的訓練得分很高,測試得分很低。

\underline{由此可以判斷,邏輯迴歸模型欠擬合,支持向量機模型過擬合,決策樹正常}

同樣,我們可以翻轉這些曲線(因爲它們測量的是得分,而原始曲線測量的是錯誤),並將它們與下面的三條曲線對比,可以看出它們與我們之前看到的三條曲線很像。(注意:我們需要翻轉曲線並不意味着錯誤是 1 減去得分。只是表示模型越來越好的話,錯誤會降低,得分會升高。)

e201

現在我們應該檢測在實際模型中是否這樣。當我們繪製每個模型的界限曲線時,結果如下所示:

e202

當我們查看上述模型時,第一個模型欠擬合,第二個正常,第三個過擬合,這種現象合理嗎?合理吧?我們看到數據由圓圈或方框正確地劃分出來。我們的模型按以下形式劃分數據:

邏輯迴歸模型使用一條直線,這太簡單了。在訓練集上的效果不太好,因此欠擬合。

決策樹模型使用一個方形,擬合的很好,並能夠泛化。因此,該模型效果很好。

支持向量機模型實際上在每個點周圍都畫了一個小圓圈。它實際上是在記住訓練集,無法泛化。因此 過擬合。

最好儘可能進行實際檢查,確保模型的確具有指標所指示的行爲。

5.網格搜索

總結一下機器學習過程:

首先用訓練集訓練一些模型,然後利用交叉驗證集數據在其中選擇一個最好的模型,最後利用測試數據進行檢測來保證這個模型是最好的。

這是一個訓練邏輯迴歸的例子:

e300

它是一條直線,一個二階、三階和四階模型,用訓練集數據來訓練這個多項式的斜率和係數參數等,用交叉驗證集數據來計算F1分數值

然後選擇F1分數最高的模型,最後使用測試數據來確保所選模型是最好的.

同理,看另外一個例子,訓練決策樹,它的超參數是,深度

e301

如果有多個超參數,比如訓練支持向量機,如何在覈參數和C參數之間選擇最佳組合呢?

e302

用網格搜索,做一張有各種可能性的表格,用訓練集數據訓練模型,然後用交叉驗證集計算,選擇F1分數最高值。

e303

6.在sklearn中的網格搜索

假設我們想要訓練支持向量機,並且我們想在以下參數之間做出決定:

kernel:poly或rbf。

C:0.1,1 或 10。

6.1 導入 GridSearchCV

from sklearn.model_selection import GridSearchCV

6.2 選擇參數:

現在我們來選擇我們想要選擇的參數,並形成一個字典。 在這本字典中,鍵 (keys) 將是參數的名稱,值 (values) 將是每個參數可能值的列表。

parameters = {'kernel':['poly', 'rbf'],'C':[0.1, 1, 10]}

6.3 創建一個評分機制 (scorer)

我們需要確認將使用什麼指標來爲每個候選模型評分。 這裏,我們將使用 F1 分數。

from sklearn.metrics import make_scorer
from sklearn.metrics import f1_score
scorer = make_scorer(f1_score)

6.4 使用參數 (parameter) 和評分機制 (scorer) 創建一個 GridSearch 對象。 使用此對象與數據保持一致 (fit the data) 。

# Create the object.
grid_obj = GridSearchCV(clf, parameters, scoring=scorer)
# Fit the data
grid_fit = grid_obj.fit(X, y)

6.5 獲得最佳估算器 (estimator)

best_clf = grid_fit.best_estimator_

現在可以使用這一估算器best_clf來做出預測。

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