1. 程式人生 > >機器學習:線性迴歸、嶺迴歸、Lasso迴歸

機器學習:線性迴歸、嶺迴歸、Lasso迴歸

 轉載自:https://blog.csdn.net/hzw19920329/article/details/77200475

線性迴歸作為一種迴歸分析技術,其分析的因變數屬於連續型變數,如果因變數轉變為離散型變數,將轉換為分類問題。迴歸分析屬於有監督學習問題,本部落格將重點回顧標準線性迴歸知識點,並就線性迴歸中可能出現的問題進行簡單探討,引出線性迴歸的兩個變種嶺迴歸以及Lasso迴歸,最後通過sklearn庫模擬整個迴歸過程。

目錄結構


  • 線性迴歸的一般形式
  • 線性迴歸中可能遇到的問題
  • 過擬合問題及其解決方法
  • 線性迴歸程式碼實現
  • 嶺迴歸與Lasso迴歸
  • 嶺迴歸以及Lasso迴歸程式碼實現

線性迴歸的一般形式

這裡寫圖片描述


線性迴歸中可能遇到的問題

  • 求解損失函式的最小值有兩種方法:梯度下降法以及正規方程,兩者的對比在附加筆記中有列出。
  • 特徵縮放:即對特徵資料進行歸一化操作,進行特徵縮放的好處有兩點,一是能夠提升模型的收斂速度,因為如果特徵間的資料相差級別較大的話,以兩個特徵為例,以這兩個特徵為橫縱座標繪製等高線圖,繪製出來是扁平狀的橢圓,這時候通過梯度下降法尋找梯度方向最終將走垂直於等高線的之字形路線,迭代速度變慢。但是如果對特徵進行歸一化操作之後,整個等高線圖將呈現圓形,梯度的方向是指向圓心的,迭代速度遠遠大於前者。二是能夠提升模型精度。
  • 學習率α的選取:如果學習率α選取過小,會導致迭代次數變多,收斂速度變慢;學習率α選取過大,有可能會跳過最優解,最終導致根本無法收斂。

過擬合問題及其解決方法

  • 問題:以下面一張圖片展示過擬合問題
    這裡寫圖片描述
  • 解決方法:(1):丟棄一些對我們最終預測結果影響不大的特徵,具體哪些特徵需要丟棄可以通過PCA演算法來實現;(2):使用正則化技術,保留所有特徵,但是減少特徵前面的引數θ的大小,具體就是修改線性迴歸中的損失函式形式即可,嶺迴歸以及Lasso迴歸就是這麼做的。

線性迴歸程式碼示例

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model, discriminant_analysis, cross_validation

def load_data():
    diabetes = datasets.load_diabetes()
    return cross_validation.train_test_split(diabetes.data, diabetes.target, test_size=0.25, random_state=0)

def test_LinearRegression(*data):
    X_train, X_test, y_train, y_test = data
    #通過sklearn的linear_model建立線性迴歸物件
    linearRegression = linear_model.LinearRegression()
    #進行訓練
    linearRegression.fit(X_train, y_train)
    #通過LinearRegression的coef_屬性獲得權重向量,intercept_獲得b的值
    print("權重向量:%s, b的值為:%.2f" % (linearRegression.coef_, linearRegression.intercept_))
    #計算出損失函式的值
    print("損失函式的值: %.2f" % np.mean((linearRegression.predict(X_test) - y_test) ** 2))
    #計算預測效能得分
    print("預測效能得分: %.2f" % linearRegression.score(X_test, y_test))

if __name__ == '__main__':
    #獲得資料集
    X_train, X_test, y_train, y_test = load_data()
    #進行訓練並且輸出預測結果
    test_LinearRegression(X_train, X_test, y_train, y_test)

線性迴歸示例輸出

權重向量:[ -43.26774487 -208.67053951  593.39797213  302.89814903 -560.27689824
  261.47657106   -8.83343952  135.93715156  703.22658427   28.34844354], b的值為:153.07
損失函式的值: 3180.20
預測效能得分: 0.36

嶺迴歸與Lasso迴歸


嶺迴歸與Lasso迴歸的出現是為了解決線性迴歸出現的過擬合以及在通過正規方程方法求解θ的過程中出現的x轉置乘以x不可逆這兩類問題的,這兩種迴歸均通過在損失函式中引入正則化項來達到目的,具體三者的損失函式對比見下圖:
這裡寫圖片描述
其中λ稱為正則化引數,如果λ選取過大,會把所有引數θ均最小化,造成欠擬合,如果λ選取過小,會導致對過擬合問題解決不當,因此λ的選取是一個技術活。
嶺迴歸與Lasso迴歸最大的區別在於嶺迴歸引入的是L2範數懲罰項,Lasso迴歸引入的是L1範數懲罰項,Lasso迴歸能夠使得損失函式中的許多θ均變成0,這點要優於嶺迴歸,因為嶺迴歸是要所有的θ均存在的,這樣計算量Lasso迴歸將遠遠小於嶺迴歸。
嶺迴歸
這裡寫圖片描述
可以看到,Lasso迴歸最終會趨於一條直線,原因就在於好多θ值已經均為0,而嶺迴歸卻有一定平滑度,因為所有的θ值均存在。

嶺迴歸以及Lasso迴歸程式碼實現


嶺迴歸程式碼示例

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model, discriminant_analysis, cross_validation

def load_data():
    diabetes = datasets.load_diabetes()
    return cross_validation.train_test_split(diabetes.data, diabetes.target, test_size=0.25, random_state=0)

def test_ridge(*data):
    X_train, X_test, y_train, y_test = data
    ridgeRegression = linear_model.Ridge()
    ridgeRegression.fit(X_train, y_train)
    print("權重向量:%s, b的值為:%.2f" % (ridgeRegression.coef_, ridgeRegression.intercept_))
    print("損失函式的值:%.2f" % np.mean((ridgeRegression.predict(X_test) - y_test) ** 2))
    print("預測效能得分: %.2f" % ridgeRegression.score(X_test, y_test))

#測試不同的α值對預測效能的影響
def test_ridge_alpha(*data):
    X_train, X_test, y_train, y_test = data
    alphas = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000]
    scores = []
    for i, alpha in enumerate(alphas):
        ridgeRegression = linear_model.Ridge(alpha=alpha)
        ridgeRegression.fit(X_train, y_train)
        scores.append(ridgeRegression.score(X_test, y_test))
    return alphas, scores

def show_plot(alphas, scores):
    figure = plt.figure()
    ax = figure.add_subplot(1, 1, 1)
    ax.plot(alphas, scores)
    ax.set_xlabel(r"$\alpha$")
    ax.set_ylabel(r"score")
    ax.set_xscale("log")
    ax.set_title("Ridge")
    plt.show()

if __name__ == '__main__':
    #使用預設的alpha
    #獲得資料集
    #X_train, X_test, y_train, y_test = load_data()
    #進行訓練並且預測結果
    #test_ridge(X_train, X_test, y_train, y_test)

    #使用自己設定的alpha
    X_train, X_test, y_train, y_test = load_data()
    alphas, scores = test_ridge_alpha(X_train, X_test, y_train, y_test)
    show_plot(alphas, scores)

Lasso迴歸程式碼示例

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model, discriminant_analysis, cross_validation

def load_data():
    diabetes = datasets.load_diabetes()
    return cross_validation.train_test_split(diabetes.data, diabetes.target, test_size=0.25, random_state=0)

def test_lasso(*data):
    X_train, X_test, y_train, y_test = data
    lassoRegression = linear_model.Lasso()
    lassoRegression.fit(X_train, y_train)
    print("權重向量:%s, b的值為:%.2f" % (lassoRegression.coef_, lassoRegression.intercept_))
    print("損失函式的值:%.2f" % np.mean((lassoRegression.predict(X_test) - y_test) ** 2))
    print("預測效能得分: %.2f" % lassoRegression.score(X_test, y_test))

#測試不同的α值對預測效能的影響
def test_lasso_alpha(*data):
    X_train, X_test, y_train, y_test = data
    alphas = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000]
    scores = []
    for i, alpha in enumerate(alphas):
        lassoRegression = linear_model.Lasso(alpha=alpha)
        lassoRegression.fit(X_train, y_train)
        scores.append(lassoRegression.score(X_test, y_test))
    return alphas, scores

def show_plot(alphas, scores):
    figure = plt.figure()
    ax = figure.add_subplot(1, 1, 1)
    ax.plot(alphas, scores)
    ax.set_xlabel(r"$\alpha$")
    ax.set_ylabel(r"score")
    ax.set_xscale("log")
    ax.set_title("Ridge")
    plt.show()

if __name__=='__main__':
    X_train, X_test, y_train, y_test = load_data()
    # 使用預設的alpha
    #test_lasso(X_train, X_test, y_train, y_test)
    # 使用自己設定的alpha
    alphas, scores = test_lasso_alpha(X_train, X_test, y_train, y_test)
    show_plot(alphas, scores)

附上學習筆記

這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述這裡寫圖片描述

參考文獻