Python數模筆記-Sklearn(4)線性迴歸

youcans發表於2021-05-13

1、什麼是線性迴歸?

  迴歸分析(Regression analysis)是一種統計分析方法,研究自變數和因變數之間的定量關係。迴歸分析不僅包括建立數學模型並估計模型引數,檢驗數學模型的可信度,也包括利用建立的模型和估計的模型引數進行預測或控制。按照輸入輸出變數關係的型別,迴歸分析可以分為線性迴歸和非線性迴歸。

  線性迴歸(Linear regression) 假設樣本資料集中的輸出變數(y)與輸入變數(X)存線上性關係,即輸出變數是輸入變數的線性組合。線性模型是最簡單的模型,也是非常重要和應用廣泛的模型。

  如果模型只有一個輸入變數和一個輸出變數,稱為一元線性模型,可以用一條直線來描述輸出與輸入的關係,其表示式是一元一次方程:

    y = w0 + w1*x1 + e

  如果模型包括兩個或多個輸入變數,則稱為多元線性模型,可以用一個平面或超平面來描述輸出與輸入的關係,其表示式是多元一次方程:

    Y = w0 + w1*x1 + w2*x2+...+ wm*xm + e

  採用最小二乘法(Least square method)可以通過樣本資料來估計迴歸模型的引數,使模型的輸出與樣本資料之間的誤差平方和最小。

  迴歸分析還要進一步分析究竟能不能採用線性迴歸模型,或者說線性關係的假設是否合理、線性模型是否具有良好的穩定性?這就需要使用統計分析進行顯著性檢驗,檢驗輸入與輸出變數之間的線性關係是否顯著,用線性模型來描述它們之間的關係是否恰當。


2、SKlearn 中的線性迴歸方法(sklearn.linear_model)

  以機器學習的角度來看,迴歸是廣泛應用的預測建模方法,線性迴歸是機器學習中重要的基礎演算法。SKlearn 機器學習工具包提供了豐富的線性模型學習方法,最重要和應用最廣泛的無疑是普通最小二乘法(Ordinary least squares,OLS),此外多項式迴歸(Polynomial regression)、邏輯迴歸(Logistic Regression)和嶺迴歸(Ridge regression)也較為常用,將在本文及後續文中介紹。其它方法相對比較特殊,以下根據官網介紹給出簡要說明,普通讀者可以略過。

  1. 普通最小二乘法(Ordinary least squares):
    以模型預測值與樣本觀測值的殘差平方和最小作為優化目標。
  2. 嶺迴歸(Ridge regression)
    在普通最小二乘法的基礎上增加懲罰因子以減少共線性的影響,以帶懲罰項(L2正則化)的殘差平方和最小作為優化目標。在指標中同時考慮了較好的學習能力以及較小的慣效能量,以避免過擬合而導致模型泛化能力差。
  3. Lasso 迴歸(Least absolute shrinkage and selection operator)
    在普通最小二乘法的基礎上增加絕對值偏差作為懲罰項(L1正則化)以減少共線性的影響,在擬合廣義線性模型的同時進行變數篩選和複雜度調整,適用於稀疏係數模型。
  4. 多元 Lasso 迴歸(Multi-task Lasso)
    用於估計多元迴歸稀疏係數的線性模型。注意不是指多執行緒或多工,而是指對多個輸出變數篩選出相同的特徵變數(也即迴歸係數整列為 0,因此該列對應的輸入變數可以被刪除)。
  5. 彈性網路迴歸(Elastic-Net)
    引入L1和L2範數正則化而構成帶有兩種懲罰項的模型,相當於嶺迴歸和 Lasso 迴歸的組合。
  6. Multi-task Elastic-Net
    用於估計多元迴歸稀疏係數線性模型的彈性網路迴歸方法。
  7. 最小角迴歸演算法(Least Angle Regression)
    結合前向梯度演算法和前向選擇演算法,在保留前向梯度演算法的精確性的同時簡化迭代過程。每次選擇都加入一個與相關度最高的自變數,最多 m步就可以完成求解。特別適合於特徵維度遠高於樣本數的情況。
  8. LARS Lasso
    使用最小角迴歸演算法求解 Lasso模型。
  9. 正交匹配追蹤法(Orthogonal Matching Pursuit)
    用於具有非零係數變數數約束的近似線性模型。在分解的每一步進行正交化處理,選擇刪除與當前殘差最大相關的列,反覆迭代達到所需的稀疏程度。
  10. 貝葉斯迴歸(Bayesian Regression)
    用貝葉斯推斷方法求解的線性迴歸模型,具有貝葉斯統計模型的基本性質,可以求解權重係數的概率密度函式。可以被用於觀測資料較少但要求提供後驗分佈的問題,例如對物理常數的精確估計;也可以用於變數篩選和降維。
  11. 邏輯迴歸(Logistic Regression)
    邏輯迴歸是一種廣義線性模型,研究順序變數或屬性變數作為輸出的問題,實際是一種分類方法。通過線性模型加Sigmoid對映函式,將線性模型連續型輸出變換為離散值。常用於估計某種事物的可能性,如尋找危險因素、預測發病概率、判斷患病概率,是流行病學和醫學中最常用的分析方法。
  12. 廣義線性迴歸(Generalized Linear Regression)
    廣義線性迴歸是線性迴歸模型的推廣,實際上是非線性模型。通過單調可微的聯結函式,建立輸出變數與輸入變數的線性關係,將問題簡潔直接地轉化為線性模型來處理。
  13. 隨機梯度下降(Stochastic Gradient Descent)
    梯度下降是一種基於搜尋的最優化方法,用梯度下降法來求損失函式最小時的引數估計值,適用樣本數(和特徵數)非常非常大的情況。隨機梯度下降法在計算下降方向時,隨機選一個資料進行計算,而不是掃描全部訓練資料集,加快了迭代速度。
  14. 感知機(Perceptron)
    感知機是一種適合大規模學習的簡單分類演算法。訓練速度比SGD稍快,並且產生的模型更稀疏。
  15. 被動攻擊演算法(Passive Aggressive Algorithms)
    被動攻擊演算法是一類用於大規模學習的演算法。
  16. 魯棒性迴歸(Robustness regression)
    魯棒性迴歸的目的是在存在損壞資料的情況下擬合迴歸模型,如存在異常值或錯誤的情況。
  17. 多項式迴歸(Polynomial regression)
    多項式迴歸通過構造特徵變數的多項式來擴充套件簡單的線性迴歸模型。例如將特徵變數組合成二階多項式,可以將拋物面擬合到資料中,從而具有更廣泛的靈活性和適應性。

3、SKlearn 中的最小二乘線性迴歸方法

3.1 最小二乘線性迴歸類(LinearRegression )

  SKlearn 包中的 LinearRegression() 方法,不宜從字面理解為線性迴歸方法, LinearRegression() 僅指基於普通最小二乘法(OLS)的線性迴歸方法。

  sklearn.linear_model.LinearRegression 類是 OLS 線性迴歸演算法的具體實現,官網介紹詳見:https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html#sklearn.linear_model.LinearRegression

sklearn.linear_model.LinearRegression()

class sklearn.linear_model.LinearRegression(*, fit_intercept=True, normalize=False, copy_X=True, n_jobs=None, positive=False)

  LinearRegression() 類的引數不多,通常幾乎不需要設定。

  • fit_intercept:bool, default=True  是否計算截距。預設值 True,計算截距。
  • normalize:bool, default=False  是否進行資料標準化,該引數僅在 fit_intercept = True 時有效。
  • n_jobs:int, default=None   計算時設定的任務數,為 n>1和大規模問題提供加速。預設值 任務數為 1。

  LinearRegression() 類的主要屬性:

  • coef_:   線性係數,即模型引數 w1... 的估計值
  • intercept_:  截距,即模型引數 w0 的估計值

  LinearRegression() 類的主要方法:

  • fit(X,y[,sample_weight])  用樣本集(X, y)訓練模型。sample_weight 為每個樣本設權重,預設None。
  • get_params([deep])  獲取模型引數。注意不是指模型迴歸係數,而是指fit_intercept,normalize等引數。
  • predict(X)  用訓練的模型預測資料集 X 的輸出。即可以對訓練樣本給出模型輸出結果,也可以對測試樣本給出預測結果。
  • score(X,y[,sample_weight])  R2 判定係數,是常用的模型評價指標。

3.2 一元線性迴歸

LinearRegression 使用例程:

# skl_LinearR_v1a.py
# Demo of linear regression by scikit-learn
# Copyright 2021 YouCans, XUPT
# Crated:2021-05-12
#  -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error, median_absolute_error

# 生成測試資料:
nSample = 100
x = np.linspace(0, 10, nSample)  # 起點為 0,終點為 10,均分為 nSample個點
e = np.random.normal(size=len(x))  # 正態分佈隨機數
y = 2.36 + 1.58 * x + e  # y = b0 + b1*x1

# 按照模型要求進行資料轉換:輸入是 array型別的 n*m 矩陣,輸出是 array型別的 n*1 陣列
x = x.reshape(-1, 1)  # 輸入轉換為 n行 1列(多元迴歸則為多列)的二維陣列
y = y.reshape(-1, 1)  # 輸出轉換為 n行1列的二維陣列
# print(x.shape,y.shape)

# 一元線性迴歸:最小二乘法(OLS)
modelRegL = LinearRegression()  # 建立線性迴歸模型
modelRegL.fit(x, y)  # 模型訓練:資料擬合
yFit = modelRegL.predict(x)  # 用迴歸模型來預測輸出

# 輸出迴歸結果 XUPT
print('迴歸截距: w0={}'.format(modelRegL.intercept_))  # w0: 截距
print('迴歸係數: w1={}'.format(modelRegL.coef_))  # w1,..wm: 迴歸係數

# 迴歸模型的評價指標 YouCans
print('R2 確定係數:{:.4f}'.format(modelRegL.score(x, y)))  # R2 判定係數
print('均方誤差:{:.4f}'.format(mean_squared_error(y, yFit)))  # MSE 均方誤差
print('平均絕對值誤差:{:.4f}'.format(mean_absolute_error(y, yFit)))  # MAE 平均絕對誤差
print('中位絕對值誤差:{:.4f}'.format(median_absolute_error(y, yFit)))  # 中值絕對誤差

# 繪圖:原始資料點,擬合曲線
fig, ax = plt.subplots(figsize=(8, 6))
ax.plot(x, y, 'o', label="data")  # 原始資料
ax.plot(x, yFit, 'r-', label="OLS")  # 擬合資料

ax.legend(loc='best')  # 顯示圖例
plt.title('Linear regression by SKlearn (Youcans)')
plt.show()  # YouCans, XUPT

程式說明:

  1. 線性迴歸模型 LinearRegression() 類在模型訓練 modelRegL.fit(x, y) 時,要求輸入 x 和輸出 y 資料格式為 array型別的 n*m 矩陣。一元迴歸模型 m=1,也要轉換為 n*1 的 array型別:
x = x.reshape(-1, 1)  # 輸入轉換為 n行 1列(多元迴歸則為多列)的二維陣列
y = y.reshape(-1, 1)  # 輸出轉換為 n行1列的二維陣列
  1. LinearRegression() 類提供的模型評價指標只有 R2指標,但在 sklearn.metrics 包中提供了均方誤差、平均絕對值誤差和中位絕對值誤差,例程中給出了其使用方法。

程式執行結果:

迴歸截距: w0=[2.45152704]
迴歸係數: w1=[[1.57077698]]
R2 確定係數:0.9562
均方誤差:0.9620
平均絕對值誤差:0.7905
中位絕對值誤差:0.6732

3.2 多元線性迴歸

  用 LinearRegression() 解決多元線性迴歸問題與一元線性迴歸的步驟、引數和屬性都是相同的,只是要注意樣本資料的格式要求:輸入資料 X 是 array 型別的 n*m 二維陣列,輸出資料 y 是 array型別的 n*1 陣列(也可以用 n*k 表示多變數輸出)。
  
問題描述:
  資料檔案 toothpaste.csv 中收集了 30個月牙膏銷售量、價格、廣告費用及同期的市場均價。
  (1)分析牙膏銷售量與價格、廣告投入之間的關係,建立數學模型;
  (2)估計所建立數學模型的引數,進行統計分析;
  (3)利用擬合模型,預測在不同價格和廣告費用下的牙膏銷售量。
  需要說明的是,本文例程並不是問題最佳的求解方法和結果,只是使用該問題及資料示範讀取資料檔案和資料處理的方法。

LinearRegression 使用例程:

# skl_LinearR_v1b.py
# Demo of linear regression by scikit-learn
# v1.0d: 線性迴歸模型(SKlearn)求解
# Copyright 2021 YouCans, XUPT
# Crated:2021-05-12

#  -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, mean_absolute_error, median_absolute_error


# 主程式
def main():  # 主程式
    # 讀取資料檔案
    readPath = "../data/toothpaste.csv"  # 資料檔案的地址和檔名
    dfOpenFile = pd.read_csv(readPath, header=0, sep=",")  # 間隔符為逗號,首行為標題行
    dfData = dfOpenFile.dropna()  # 刪除含有缺失值的資料
    print(dfData.head())

    # Model 1:Y = b0 + b1*X1 + b2*X2 + e
    # 線性迴歸:分析因變數 Y(sales) 與 自變數 x1(diffrence)、x2(advertise) 的關係
    # 按照模型要求進行資料轉換:輸入是 array型別的 n*m 矩陣,輸出是 array型別的 n*1 陣列
    feature_cols = ['difference', 'advertise']  # 建立特徵列表
    X = dfData[feature_cols]  # 使用列表選擇樣本資料的特徵子集
    y = dfData['sales']  # 選擇樣本資料的輸出變數
    # print(type(X),type(y))
    # print(X.shape, y.shape)
    # 一元線性迴歸:最小二乘法(OLS)
    modelRegL = LinearRegression()  # 建立線性迴歸模型
    modelRegL.fit(X, y)  # 模型訓練:資料擬合
    yFit = modelRegL.predict(X)  # 用迴歸模型來預測輸出
    # 輸出迴歸結果 # YouCans, XUPT
    print("\nModel1: Y = b0 + b1*x1 + b2*x2")
    print('迴歸截距: w0={}'.format(modelRegL.intercept_))  # w0: 截距
    print('迴歸係數: w1={}'.format(modelRegL.coef_))  # w1,..wm: 迴歸係數
    # 迴歸模型的評價指標
    print('R2 確定係數:{:.4f}'.format(modelRegL.score(X, y)))  # R2 判定係數
    print('均方誤差:{:.4f}'.format(mean_squared_error(y, yFit)))  # MSE 均方誤差
    print('平均絕對值誤差:{:.4f}'.format(mean_absolute_error(y, yFit)))  # MAE 平均絕對誤差
    print('中位絕對值誤差:{:.4f}'.format(median_absolute_error(y, yFit)))  # 中值絕對誤差

    # Model 3:Y = b0 + b1*X1 + b2*X2 + b3*X2**2 + e
    # 線性迴歸:分析因變數 Y(sales) 與 自變數 x1、x2 及 x2平方的關係
    x1 = dfData['difference']  # 價格差,x4 = x1 - x2
    x2 = dfData['advertise']  # 廣告費
    x5 = x2**2  # 廣告費的二次元
    X = np.column_stack((x1,x2,x5))  # [x1,x2,x2**2]
    # 多元線性迴歸:最小二乘法(OLS)
    modelRegM = LinearRegression()  # 建立線性迴歸模型
    modelRegM.fit(X, y)  # 模型訓練:資料擬合
    yFit = modelRegM.predict(X)  # 用迴歸模型來預測輸出
    # 輸出迴歸結果 # YouCans, XUPT
    print("\nModel3: Y = b0 + b1*x1 + b2*x2 + b3*x2**2")
    print('迴歸截距: w0={}'.format(modelRegM.intercept_))  # w0: 截距, YouCans
    print('迴歸係數: w1={}'.format(modelRegM.coef_))  # w1,..wm: 迴歸係數, XUPT
    # 迴歸模型的評價指標
    print('R2 確定係數:{:.4f}'.format(modelRegM.score(X, y)))  # R2 判定係數
    print('均方誤差:{:.4f}'.format(mean_squared_error(y, yFit)))  # MSE 均方誤差
    print('平均絕對值誤差:{:.4f}'.format(mean_absolute_error(y, yFit)))  # MAE 平均絕對誤差
    print('中位絕對值誤差:{:.4f}'.format(median_absolute_error(y, yFit)))  # 中值絕對誤差
    # 計算 F統計量 和 F檢驗的 P值
    m = X.shape[1]
    n = X.shape[0]
    yMean = np.mean(y)
    SST = sum((y-yMean)**2)  # SST: 總平方和
    SSR = sum((yFit-yMean)**2)  # SSR: 迴歸平方和
    SSE = sum((y-yFit)**2)  # SSE: 殘差平方和
    Fstats = (SSR/m) / (SSE/(n-m-1))  # F 統計量
    probFstats = stats.f.sf(Fstats, m, n-m-1)  # F檢驗的 P值
    print('F統計量:{:.4f}'.format(Fstats))
    print('FF檢驗的P值:{:.4e}'.format(probFstats))
    
    # 繪圖:原始資料點,擬合曲線
    fig, ax = plt.subplots(figsize=(8, 6))  # YouCans, XUPT
    ax.plot(range(len(y)), y, 'b-.', label='Sample')  # 樣本資料
    ax.plot(range(len(y)), yFit, 'r-', label='Fitting')  # 擬合資料
    ax.legend(loc='best')  # 顯示圖例
    plt.title('Regression analysis with sales of toothpaste by SKlearn')
    plt.xlabel('period')
    plt.ylabel('sales')
    plt.show()

    return

if __name__ == '__main__':
    main()

程式執行結果:

Model1: Y = b0 + b1*x1 + b2*x2
迴歸截距: w0=4.4074933246887875
迴歸係數: w1=[1.58828573 0.56348229]
R2 確定係數:0.8860
均方誤差:0.0511
平均絕對值誤差:0.1676
中位絕對值誤差:0.1187

Model3: Y = b0 + b1*x1 + b2*x2 + b3*x2**2
迴歸截距: w0=17.324368548878198
迴歸係數: w1=[ 1.30698873 -3.69558671  0.34861167]
R2 確定係數:0.9054
均方誤差:0.0424
平均絕對值誤差:0.1733
中位絕對值誤差:0.1570
F統計量:82.9409
F檢驗的P值:1.9438e-13

程式說明:

  1. 用 LinearRegression() 類處理多元線性迴歸問題,模型對訓練樣本資料的格式要求為:輸入資料 X 是 array 型別的 n*m 二維陣列,輸出資料 y 是 array型別的 n*1 陣列(也可以用 n*k 表示多變數輸出)。例程中給出了兩種資料轉換的方式:Model 1 從 Pandas 的 dataframe 資料轉換得到模型要求的 array 型別二維陣列,這在 Pandas 讀取資料檔案時非常方便;Model3 則用 Numpy 的 np.column_stack 陣列拼接獲得 array 型別二維陣列。
  2. 本例程的問題和資料《Python學習筆記-StatsModels 統計迴歸(3)模型資料的準備》中相同,來自:姜啟源、謝金星《數學模型(第 3版)》,高等教育出版社。
  3. 為了便於與 StatsModels 統計迴歸結果進行比較,例程所採用的模型也與該文一致:Model1 中使用特徵變數 'difference', 'advertise' 建立線性迴歸模型,Model3 中使用特徵變數 'difference', 'advertise' 及 'advertise' 的二次項( x2**2)建立線性迴歸模型。SKlearn 與 StatsModels 對這兩個模型的引數估計結果、預測結果和 R2確定係數都完全相同,表明用 SKlearn 與 StatsModels 工具包都可以實現線性迴歸。
  4. StatsModels 工具包提供的模型檢驗的指標非常全面、詳細,對模型檢驗和統計分析非常重要。而 SKlearn 包所提供的統計檢驗指標很少,F檢驗、T 檢驗、相關係數的顯著性檢驗指標都沒有,根本原因在於 SKlearn 是機器學習庫而非統計工具箱,關注點是模型精度和預測效能,而不在於模型的顯著性。
  5. 為了解決缺少模型顯著性檢驗指標的問題,例程中增加了一段 計算 F統計量 和 F檢驗P值 的程式可供參考。

版權說明:
  本文內容及例程為作者原創,並非轉載書籍或網路內容。
YouCans 原創作品
Copyright 2021 YouCans, XUPT
Crated:2021-05-12

相關文章