1. 程式人生 > >【尋優演算法】交叉驗證(Cross Validation)引數尋優的python實現:單一引數尋優

【尋優演算法】交叉驗證(Cross Validation)引數尋優的python實現:單一引數尋優

【尋優演算法】交叉驗證(Cross Validation)引數尋優的python實現:單一引數尋優


有關交叉驗證的博文有很多,這裡我會引用幾篇博文【參考資料1,2,3,4】,幫助大家溫習一下。交叉驗證可以用於機器學習訓練模型的效能評價,也可以進行引數尋優,本博文主要介紹交叉驗證用於機器學習引數尋優的方法。

一、交叉驗證的意義

交叉驗證將原始資料集分組,一部分作為訓練集,一本分作為驗證集。訓練集用於訓練模型,驗證集用於評價訓練模型的效能指標。
引數尋優的意義:引數的數值決定著模型的效能。
交叉驗證進行引數尋優的意義:如果訓練和驗證的資料集是相同的,可能驗證的結果特別好,但是對於新的資料集預測效果就差強人意,因為過擬合over-fitting)。採用交叉驗證方法可以保障驗證資料集沒有參與過模型的訓練,可以給出較為準確的引數尋優結果。

二、常用的交叉驗證方法

1、Hold one method

樣本資料被分為兩組,一組作為訓練資料集,用於訓練模型,另一組作為驗證資料集,用於評估模型效能。
優點:容易實現,處理簡單。
缺點:沒有用到交叉的方法,驗證資料集對於模型的訓練沒有任何貢獻。

2、K-flod CV

樣本資料被分為 k k 組,每次將一組作為驗證資料集,其餘的 k 1 k-1

組作為訓練資料集。這樣就會有 k k 個訓練模型,這 k k 個模型的驗證準確率的平均值作為模型的效能指標。
優點:所有的樣本都會被用於模型訓練,評價結果可信。
缺點:相較於Hold one method,處理較為複雜。

3、Leave-One-Out CV(LOO-CV)

設原始資料集中有 K K 個樣本,每次選擇一個樣本作為驗證資料集,其餘的 K 1 K-1 個樣本作為訓練資料集,這樣就會有 K K 個訓練模型,這 K K 個訓練模型的驗證準確率平均值為模型的效能指標。
優點:每次模型訓練,幾乎所有的樣本都會應用到,結果最可信。
缺點:需要訓練的模型較多,且訓練資料集樣本大,計算成本高。

二、交叉驗證引數尋優的python實現

1、訓練模型和待尋優引數

本博文選用的訓練模型為線性的SVM模型(參考資料【5】),模型的數學表達為:

min W , b 1 2 W 2 + C 2 i = 1 m e i 2 s . t . y i ( W x i + b ) 1 e i , i = 1 ,   , m e i 0 , i = 1 ,   , m \begin{array}{l} \mathop {\min }\limits_{W,b} \frac{1}{2}{\left\| W \right\|^2} + \frac{C}{2}\sum\limits_{i = 1}^m {e_i^2} \\ s.t.{y_i}\left( {W \cdot {x_i} + b} \right) \ge 1 - {e_i},i = 1, \cdots ,m\\ {e_i} \ge 0,i = 1, \cdots ,m \end{array}

其中 W W b b 是分隔超平面的權重和偏置,模型的訓練就是為了訓練 W W b b 的值。 C C 是正則化引數,對模型的效能有很大的影響,本博文就是用3-flod交叉驗證方法求引數 C C 值。

2、演算法執行步驟

步驟一、設定引數 C C 的取值範圍
步驟二、從第一個取值開始,將原始資料集分為3個子資料集(3-flod CV),每次將兩個資料子集作為訓練集用於線性SVM模型的訓練,一個數據子集用於模型驗證,共訓練3個模型,取三個模型的驗證準確率的平均值作為評價指標。引數 C C 的取值指標加1,重複步驟二,直到最後一個引數 C C 的取值。
步驟三:畫出引數 C C 與對應評價指標的示意圖。

3、交叉驗證引數尋優的python實現

程式碼及樣本地址 https://github.com/shiluqiang/CV_parameter_optimization

import numpy as np
from sklearn import svm
from sklearn import cross_validation
import matplotlib.pyplot as plt

def load_data(file_name):
    '''匯入資料集和標籤
    input:file_name(string):儲存資料的地址
    output:trainX(array):樣本資料集
           trainY(array):樣本標籤
    '''
    f = open(file_name)
    trainX = []
    trainY = []
    for line in f.readlines():
        X_tmp = []
        Y_tmp = []
        lines = line.strip().split('\t')
        for i in range(len(lines)-1):
            X_tmp.append(float(lines[i]))
            Y_tmp.append(float(lines[-1]))
        trainX.append(X_tmp)
        trainY.append(Y_tmp)
    f.close()
    return np.array(trainX),np.array(trainY)


###1.匯入訓練樣本和標籤
trainX,trainY = load_data('data.txt')
trainY = trainY[:,0]

###2.設定C的取值範圍
c_list = []
for i in range(1,21):
    c_list.append(i * 0.5)

###3.交叉驗證優化引數C
cv_scores = []
for j in c_list:
    linear_svm = svm.SVC( kernel = 'linear', C = j)
    scores = cross_validation.cross_val_score(linear_svm,trainX,trainY,cv =3,scoring = 'accuracy')
    cv_scores.append(scores.mean())

fig = plt.figure().add_subplot(111)
fig.plot(c_list,cv_scores)
fig.set_xlabel('C')
fig.set_ylabel('Average accuracy')
plt.show()

4、引數C與評價指標的關係

在這裡插入圖片描述
由上圖可知,在本實驗中引數 C C 的最優取值為2。

參考資料

1.https://blog.csdn.net/yawei_liu1688/article/details/79138202
2 https://blog.csdn.net/wong2016/article/details/81407927
3. http://www.cnblogs.com/pinard/p/5992719.html
4. https://blog.csdn.net/qq_36523839/article/details/80707678
5. https://blog.csdn.net/google19890102/article/details/35566949