機器學習:以分析紅酒口感為例說明交叉驗證的套索模型


     在線性回歸問題中比較常用的一種算法就是最小二乘法(OLS),其核心思想是:通過最小化誤差的平方和尋找數據的最佳函數匹配。

但是普通的OLS最常見的一個問題是容易過度擬合:即在樣本數據集上屬性值(x)和目標值(y)是一一對應的。這樣的結果看似擬合效果

很好,但是在新數據集上的誤差卻會很大。

      解決這個問題,目前主要有兩種思路:前向逐步回歸和懲罰線性回歸。之所以說是兩種思路,而不是兩種算法,是因為以這兩種思想

為基礎,形成了兩種算法族,尤其是后者有多種較出名的算法(例如嶺回歸、套索回歸、最小角度回歸、Glmnet等)。

     前向逐步回歸基本算法思路:遍歷屬性中的每一列,找到均方誤差(MSE)之和最小的一列(即效果最佳的列),然后尋找和這列組合效果

最好的第二列屬性,依次類推直到所有的列。在這個過程中MSE--屬性個數在坐標系中行成的曲線會有明顯的變化,可以通過觀察曲線得到

想要的結果,或者通過打印出來的MES值獲得最終結果。

     懲罰線性回歸基本算法思路:在普通最小二乘法的公式中添加一個懲罰項。如果最小二乘法以下面的數學公式表達:

,那么套索(Lasso)回歸的公式為:.其中,α||W||=α(|w1|+|w2|+...+|Wn|)。

      Lasso通過構造一個懲罰函數得到一個較為精煉的模型,使得它壓縮一些系數,同時設定一些系數為零,也就是說Lasso的系數向量是稀疏的。

Lasso是采用的L1范數正則化(OLS在變量選擇方面的三種擴展方法中的一種,也叫收縮方法): L1范數是指向量中各個元素絕對值之和。

      上面說了關於模型的問題,下面說說模型評估。

      目前主要的模型性能評估方法也有兩種:預留測試集和n折交叉驗證。

      預留測試集就是把樣本數據分成兩類:一類用於訓練模型,另一類用於測試模型。一般情況下測試集可以占所有數據的25%~35%。

      n折交叉驗證就是把數據分成n份不相交的子集,以其中的一份作為測試集,另外n-1份作為訓練集。假如把數據分成5份,依次編號1~5,第一次把1號作為測試集,2、3、4、5號作為訓練集,第二次把2號作為測試集,1、3、4、5作為訓練集,依次類推,直到結束。

      這里的功能核心是:sklearn.linear_model.LassoCV

      LassoCV參數有很多,我們只用用到參數cv:表示使用幾折交叉驗證。

      重點是介紹下相關屬性:

             alpha_: 通過交叉驗證后得到的處罰系數,即公式中的α值

             coef_:  參數向量(公式中的w)

             mse_path_: 每次交叉驗證的均方誤差

             alphas_: 驗證過程中使用過的alpha值

      本次測試相關的理論基礎大概就這么多,下面開始實驗:數據來源

import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn.linear_model import LassoCV
import os

##運行腳本所在目錄
base_dir=os.getcwd()
data=np.loadtxt(base_dir+r"\wine.txt",delimiter=";")

##矩陣的長度:行數
dataLen = len(data)
##矩陣的寬度:列數
dataWid = len(data[0])
##每列的均值
xMeans = []
##每列的方差
xSD = []
##歸一化樣本集
xNorm = []
##歸一化標簽
lableNorm = []

##第一次處理數據:計算每列的均值和方差
for j in range(dataWid):
    ##讀取每列的值
    x = [data[i][j] for i in range(dataLen)]
    ##每列的均值
    mean = np.mean(x)
    xMeans.append(mean)
    ##每列的方差
    sd = np.std(x)
    xSD.append(sd)
    
##第二次處理數據:歸一化樣本集和標簽
for j in range(dataLen):
    ##樣本集歸一化
    xn = [(data[j][i]-xMeans[i])/xSD[i] for i in range(dataWid-1)]      
    xNorm.append(xn)
    ##標簽歸一化
    ln = (data[j][dataWid-1]-xMeans[dataWid-1])/xSD[dataWid-1]
    lableNorm.append(ln)
     
##參數格式是數組形式,所以需要轉換一下
X=np.array(xNorm)
Y=np.array(lableNorm)
##開始做交叉驗證:cv=10表示采用10折交叉驗證
wineModel = LassoCV(cv=10).fit(X,Y)

##打印出最佳解的每項的系數:[ 0,-0.22773828,0,0,-0.09423888,
         ##0.02215153,-0.09903605,0,-0.06787363,0.16804092,0.3750958 ]
print(wineModel.coef_)
##打印出最佳解的懲罰系數:0.013561387701
print(wineModel.alpha_)
##繪圖
plt.figure()
##隨着alpha值的變化,均方誤差的變化曲線
plt.plot(wineModel.alphas_, wineModel.mse_path_, ':')
##驗證過程中,隨着alpha值的變化,均方誤差的平均曲線
plt.plot(wineModel.alphas_, wineModel.mse_path_.mean(axis=-1),
         label='Average MSE Across Folds', linewidth=2)
##每次驗證系統認為的最合適的alpha值
plt.axvline(wineModel.alpha_, linestyle='--',
            label='CV Estimate of Best alpha')
plt.semilogx()
plt.legend()
ax = plt.gca()
ax.invert_xaxis()
plt.xlabel('alpha')
plt.ylabel('Mean Square Error')
plt.axis('tight')
plt.show()

最佳解的懲罰系數和向量系數已經在代碼中以注釋的方式寫了,生成的結果圖如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM