線性迴歸模型原理及其應用
前言
最近有在學習網易雲課堂上《吳恩達機器學習》這門課程, 受益匪淺, 然後打算將有關線性迴歸模型的知識點總結下來, 也就有了本文. 若存在錯誤的地方, 還請指正, 謝謝!
目錄
正文
線性迴歸, 是迴歸分析中的一種, 其表示自變數與因變數之間存線上性關係. 迴歸分析是從資料出發, 考察變數之間的數量關係, 並通過一定的數學關係式將這種關係描述出來, 再通過關係式來估計某個變數的取值, 同時給出該估計的可靠程度. 下面我們從一元線性迴歸開始說起.
1. 一元線性迴歸
在迴歸分析中如果只涉及一個自變數(用來預測的變數)和一個因變數(要預測的變數), 這時就稱為一元迴歸, 如果自變數與因變數之間存線上性關係, 那麼此時的迴歸就稱為一元線性迴歸.
1.1 模型
假設自變數x和因變數y存線上性關係, 那麼x和y的線性關係函式可以表示為:
由於該函式是假設x和y存線上性關係, 因此該函式可以稱為假設函式. 我們把描述因變數y和自變數x關係的函式稱為迴歸模型, 故該函式又稱一元線性迴歸模型.其中 和
稱為模型引數, 不同的引數將會構造不同的模型, 因此構建模型的關鍵之處在於選擇引數, 怎麼樣才能算好的引數呢?
由於我們構建模型的最終目的是用來預測, 因此好引數構建的模型應該具備很好的預測能力, 也就是說預測值和實際值差異很小, 我們把預測值h(x)與實際值y之間的差異稱為誤差. 對於某個值來說誤差就是h(x i )-y i , 對於整個模型來說, 則是對所有誤差進行求和, 但由於誤差中有正負之分, 因此會產生誤差相 互抵消, 為了避免存在這種抵消問題, 對誤差進行平方求和, 再對其求平均, 故有平均誤差平方和 , 其表示為
其中, m是樣本量. h(x (i) )表示第i個預測值, 與之對應的實際值則是y (i) .
這種誤差可以認為是實際值或者期望值的損失, 故該誤差函式可以稱為損失函式(有時也稱為代價函式). 我們可以根據損失函式數值最小來選出最優模型(很好的預測能力).
1.2. 演算法
這裡我將介紹兩種基於損失函式最小的演算法: 梯度下降法和最小二乘法.
1. 梯度下降法
什麼是梯度? 引出百度百科定義:
梯度的本意是一個向量(向量),表示某一函式在該點處的方向導數沿著該方向取得最大值,即函式在該點處沿著該方向(此梯度的方向)變化最快,變化率最大(為該梯度的模)。
在單個自變數函式曲線中, 梯度也就是曲線上某點處的斜率, 而對於我們的損失函式來說, 其有兩個自變數 和
, 故這兩個自變數與損失函式
將構成三維曲面.
可以將這三維曲面想象成一座山, 我們現在的目標是山底, 我們要想最快下山, 就需要走最陡峭的方向, 而最陡峭的方向可以看成是當前方向(下山方向)中變化最大的反方向. (其中, 變化最大的方向是指從下山改為上山, 與目標不符, 故取其反方向, 即最大的反方向).
梯度下降法與下山過程類似, 我們的目標是求出使得損失函式數值最小的最優解. 具體過程就是給定一個初始位置 , 沿著梯度的反方向(也就是負的梯度)走一個步長的距離, 更新當前位置
, 如此反覆, 直至找到使得損失函式最小的最優解
, 可以表示為:
其中, 為學習效率, 也稱為步長, 等號右邊的
為每次更新之前的模型引數(j=0,1), 即每走負梯度個步長, 更新一次
和
, 而且這兩者是同步更新. 具體的求解過程如下:
首先是微分的求解, 該部分需要鏈式法則, 公式為
由於在實際中, 往往很難直接求解z對x的微分, 但引入y這個"中介"就可以將問題轉化為求z對y的微分和y對x的微分, 這就相當於分數約分的一個過程.
從計算過程中可以看出, 該演算法在選擇負的梯度方向時考慮到全部訓練資料, 故該演算法又稱為批量(Batch)梯度下降法. 通過以上原理也可得知, 該演算法是一個迭代求最優解的過程, 下面我們介紹一種可以直接一步到位的演算法.
2. 最小二乘法
最小二乘法又稱最小平方法, 即平均誤差平方和最小, 也就是我們的損失函式數值最小. 引出百度百科費馬引理定義:
函式f(x)在點 ξ 的某鄰域U( ξ )內有定義,並且在 ξ 處可導,如果對於任意的x∈U( ξ ),都有f(x)≤f( ξ ) (或f(x)≥f( ξ ) ),那麼f '( ξ )=0。
簡單來說就是可導函式極值點處導數為0, 故分別對 和
求偏導, 並令其為0, 即:
由①式可得: , 故
, 代入②式中, 可得:
又由於 和
, 故有:
我們現在對一元線性迴歸介紹完了, 接下來看看多元線性迴歸.
2. 多元線性迴歸
多元線性迴歸與一元線性迴歸的區別在於自變數的個數, 一元是一個, 多元則是多個.
2.1 模型
假設多元線性迴歸中有多個自變數(x 0 , x 1 , x 2 ,...x n ), 那麼多元線性迴歸模型的假設函式可以寫成:
為了簡化, 我們可以將假設函式寫成矩陣的形式:
其中, x 0 =1
對應的其損失函式表示為(m表示樣本量):
下面便是介紹求解最小損失函式的演算法.
2.2 演算法
同樣介紹兩種演算法: 梯度下降法和最小二乘法.
1. 梯度下降法
與一元的方法類似, 不過這裡需要注意的是對n個自變數 進行同步更新.即:
2. 最小二乘法
我們可以將損失函式轉換為矩陣的形式:
同樣地, 令 對
的偏導為0, 對於矩陣的運算需要用到以下公式:
然後套用公式:
通過以上我們對一元和多元迴歸的模型以及演算法均有所瞭解, 下面我們來看看這兩大演算法的優缺點.
3. 兩大演算法優缺點
3.1. 梯度下降法
優點
1. 在特徵變數很多時, 能夠很有效的執行
缺點
1. 容易依賴於步長和起始位置的選擇, 因此需要多次嘗試尋找合適的步長和起始位置.
2. 由於在每次更新當前位置需要計算全部訓練資料, 因此其迭代速度過慢.
3.2 最小二乘法
優點
1. 直接應用公式計算即可, 學習效率高
缺點
1. 訓練資料擬合的函式非線性的話, 則不能使用最小二乘法.
2. 需要計算 的逆矩陣, 如果逆矩陣不存在, 則沒法應用最小二乘法.
3. 當 的樣本特徵n很大時, 計算
的逆矩陣將會非常耗時, 或者說沒法計算.
4. 演算法優化問題
4.1 梯度下降法
上面我們介紹的梯度下降法是指批量梯度下降法, 即:
在批量梯度下降法中, 每次計算過程都考慮全部資料, 容易找到全域性最優, 但資料量較大時將會非常耗費時間, 因此誕生了隨機梯度下降法
隨機梯度下降法則是每次隨機抽取一個樣本進行計算, 可以大大提高學習效率, 但由於其具有隨機性且僅有一個樣本, 因此往往會導致不是最優解, 鑑於此, 產生了第三種方法: 小批量梯度下降法
這是綜合前兩種方法產生的, 選取其中a個樣本進行求解.
4.2 最小二乘法
若擬合函式非線性, 常常通過對數轉換等方法將其轉換為線性, 而且特徵數量較少時直接運用公式進行計算即可.
4.3 小結
當訓練資料特徵數量較少時, 且擬合函式為線性, 則可以直接採用最小二乘法, 如果擬合函式非線性, 可以先對其進行對數轉換再運用最小二乘法;
當訓練資料特徵數量較多時, 由於其對擬合函式無要求, 若資料量不大, 則可選用批量梯度下降, 若資料量很大, 則可以選用小批量梯度下降.
到這裡, 模型和演算法介紹完畢了, 下面我們介紹多元迴歸模型的應用.
5. 多元迴歸模型應用
5.1 資料來源及背景
資料來源: ofollow,noindex">http://archive.ics.uci.edu/ml/machine-learning-databases/00294/
該資料集是收集於聯合迴圈發電廠的9568個數據點, 共包含5個特徵: 每小時平均環境變數溫度(AT),環境壓力(AP),相對溼度(RH),排氣真空(V)和淨每小時電能輸出(PE), 其中電能輸出PE是我們要預測的變數.
5.2 資料概覽
由於我們的資料是excel格式, 而pandas處理excel檔案依賴xlrd, 因此我們首先需要安裝它.
1. 安裝xlrd
pip install xlrd
2. 讀取資料
excel檔案中共有5個sheet, 我們讀取最後一個
import pandas as pd #第二引數代表要讀取的sheet, 0表示第一個, 1表示第二個..., pandas預設讀取第一個 df = pd.read_excel(r'D:\Data\CCPP.xlsx', 4)
3. 檢視資料前3行/後3行
pd.set_option('display.max_rows', 6) df
資料維度9568行X5列, 均是數值型資料
4. 檢視資料整體資訊
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 9568 entries, 0 to 9567 Data columns (total 5 columns): AT9568 non-null float64 V9568 non-null float64 AP9568 non-null float64 RH9568 non-null float64 PE9568 non-null float64 dtypes: float64(5) memory usage: 373.8 KB
無缺失資料, 且均為浮點型.
5. 描述性統計
pd.set_option('display.max_rows', None) df.describe()
溫度(AT): 範圍1.81--37.11, 均值19.65, 中位數20.35, 左偏分佈
排氣真空(V): 範圍25.36--81.56, 均值54.31, 中位數52.08, 右偏分佈
環境壓力(AP): 範圍992.89--1033.30, 均值1013.26, 中位數1012.94, 右偏分佈
相對溼度(RH): 範圍25.56--100.16, 均值73.31, 中位數74.975, 左偏分佈
電能輸出(PE): 範圍420.26--495.76, 均值454.37, 中位數451.55, 右偏分佈
通過中位數和均值可以大致看出分佈狀況, 但是對於具體的偏斜程度, 就需要用偏態係數去衡量
6. 偏態係數
偏態係數反映的是資料的偏斜程度, 若偏態係數大於1或小於-1, 則稱為高度偏態分佈, 若在0.5~1或-1~-0.5之間, 稱為中度偏態分佈, 否則, 稱為低度偏態分佈
for i in df.columns: print('{}偏態係數: '.format(i), df[i].skew())
AT偏態係數為:-0.1363930494749227 V偏態係數為:0.19852101136676173 AP偏態係數為:0.2654446935825862 RH偏態係數為:-0.4318387491833329 PE偏態係數為:0.3065094354204023
可以看出以上均為低度偏態分佈. 我們來看看分佈形狀的另一個度量--峰態係數
7. 峰態係數
峰態係數反映的是資料的扁平程度, 峰態常常是與標準正態分佈對比, 若峰態係數為0, 則說明服從標準正態分佈, 若大於0, 則說明比標準正態分佈更尖, 稱為尖峰分佈, 若小於0, 則稱為平峰分佈.
for i in df.columns: print('{}峰態係數為: '.format(i), df[i].kurt())
AT峰態係數為:-1.0375491923092457 V峰態係數為:-1.4443366772319615 AP峰態係數為:0.0942371953033132 RH峰態係數為:-0.4445263744874084 PE峰態係數為:-1.0485209686925079
可以看得出: AT, V, AP, PE與正態分佈相比較扁平, AP則略尖峰.
現在我們已經瞭解了資料的大致情況, 下面讓我們進行下一環節: 相關分析
5.3 相關分析
該環節的目的是瞭解特徵與特徵之間的依賴程度, 這種依賴程度可以用相關係數來衡量, 而通常在相關係數計算之前, 會通過散點圖檢視分佈狀況.
1. 散點圖
import seaborn as sns import matplotlib.pyplot as plt #初始化 sns.set() #繪製分佈矩陣 sns.pairplot(df) #儲存圖片 plt.savefig('ccpp.png') plt.show()
可以看得出AT, V, AP, PH分別與PE有不同程度的相關關係, 其中AT, V呈現負相關, AP, PH呈現正相關.
我們可以通過散點圖可以大致看出相關關係, 對於關係強度我們則需要用相關係數去度量.
2. 相關係數
#計算相關係數, 預設為皮爾遜相關係數 correlation = df.corr() correlation
皮爾遜相關係數反映的是線性相關程度, 其取值介於-1~1之間. 若取0, 說明兩變數無關, 若取+1, 說明完全正相關, 若取-1, 說明完全負相關.
可以將相關係數繪製成熱力圖
3. 熱力圖
#繪製熱力圖, 設定線寬, 最大值, 最小值, 線條白色, 顯示數值, 方形 sns.heatmap(correlation, linewidths=0.2, vmax=1, vmin=-1, linecolor='w', annot=True,square=True) plt.savefig('correlation.png') plt.show()
可以根據熱力圖的顏色來判斷關係強度: 自變數中AT和V與因變數PE為高度相關(0.8~1或-1~-0.8), 自變數AP與因變數PE為中度相關(0.5~0.8或-0.8~-0.5), 自變數RH與因變數PE為低度相關(0.3~0.5或-0.5~-0.3). 另外, 自變數中V和AT高度相關.
接下來我們開始迴歸分析
5.4 迴歸分析
相關分析是確定是否存在關係以及關係強度, 而回歸分析則是確定它們到底是什麼樣的關係, 建立具體的關係表示式.
由於我們的自變數有4個且各自變數與因變數均有不同程度的線性相關關係, 因此我們假設全部自變數與因變數滿足多元線性迴歸模型:
迴歸分析的目的就是確定這 ,
,
,
,
5個模型引數, 我們這裡直接採用sklearn庫的線性迴歸模型(基於最小二乘法)去求解這個5引數.
在求解之前, 將資料集劃分為訓練集和測試集.
1. 劃分資料集
from sklearn.model_selection import train_test_split X, y = df[['AT', 'V', 'AP', 'RH']], df['PE'] #按照8:2的比例劃分為訓練資料集和測試資料集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2)
2. 構建模型
from sklearn.linear_model import LinearRegression #模型例項化 LR = LinearRegression() #訓練模型 LR.fit(X_train, y_train) print("截距: ", LR.intercept_) print("迴歸係數: ", LR.coef_ )
截距:445.62291957190826 迴歸係數:[-1.97153297 -0.231885930.07065982 -0.15715584]
因此, 我們的線性迴歸模型為: PE=455.62-1.97153297AT-0.23188593V+0.07065982AP -0.15715584RH
3. 模型評估
對於迴歸模型, 常用的評估方法有: 平均絕對誤差(MAE), 均方誤差(MSE), 均方根誤差(RMSE), 多重判定係數(R 2 ).
1) 平均絕對誤差MAE(mean_absolute_error)
其中, 表示實際值,
表示估計值. 平均絕對誤差可以有效避免誤差相互抵消的問題, 可以更好反映預測誤差的實際情況
from sklearn import metrics #分別對訓練集和測試集進行預測 y_train_pred = LR.predict(X_train) y_test_pred = LR.predict(X_test) #分別計算訓練集和測試集的平均絕對誤差 y_train_mae = metrics.mean_absolute_error(y_train, y_train_pred) y_test_mae = metrics.mean_absolute_error(y_test, y_test_pred) print('訓練集MAE: ', y_train_mae) print("測試集MAE: ", y_test_mae)
訓練集MAE:3.6280382037797847 測試集MAE:3.629089312294724
在測試集上預測值與實際值的平均誤差比訓練集略大.
避免誤差抵消的另外一種方法就是求平方, 也就是均方誤差
2) 均方誤差MSE(mean_square_error)
#分別計算訓練集和測試集的均方誤差 y_train_mse = metrics.mean_squared_error(y_train, y_train_pred) y_test_mse = metrics.mean_squared_error(y_test, y_test_pred) print('訓練集MSE: ', y_train_mse) print("測試集MSE: ", y_test_mse)
訓練集MSE:20.684348049573618 測試集MSE:21.115806888804244
同樣是測試集比訓練集誤差大, 由於其數值的單位也是平方級別, 為了更好地描述對其開根號, 也就是均方根誤差.
3) 均方根誤差RMSE(root_mean_square_error)
from math import sqrt y_train_rmse = sqrt(y_train_mse) y_test_rmse = sqrt(y_test_mse) print('訓練集RMSE: ', y_train_rmse) print("測試集RMSE: ", y_test_rmse)
訓練集RMSE:4.548004842738584 測試集RMSE:4.5951938902296865
這樣就方便去描述了, 即用我們所建立的迴歸模型來預測每小時淨電能輸出時, 平均的預測誤差為4.6MW, 與訓練集相比略大.
4) 多重判定係數R 2 (r2_score)
其中, SST則為總誤差平方和, 即SST=SSR+SSE, SSR為迴歸平方和, 反映的是能被迴歸方程解釋的誤差; SSE為殘差平方和, 反映的是不能被迴歸方程解釋的誤差. 也就是說, 多重判定係數反映的是被迴歸方程解釋的誤差佔總誤差的比例, 迴歸平方和所佔比重越大, 說明迴歸方程擬合程度越好
#分別計算訓練集和測試集的多重判定係數 y_train_r2 = metrics.r2_score(y_train, y_train_pred) y_test_r2 = metrics.r2_score(y_test, y_test_pred) print('訓練集R2: ', y_train_r2) print("測試集R2: ", y_test_r2)
訓練集R2:0.928600622449398 測試集R2:0.9289130339796056
即在訓練集和測試集上總變差中能被迴歸方程所解釋的比例分別為92.86%, 92.89%, 在測試集上比訓練集表現略好.
在sklearn中還有自帶的評估器, 不妨來看看.
#直接用訓練好的模型去評分 y_train_score = LR.score(X_train, y_train) y_test_score = LR.score(X_test, y_test) print('訓練集score: ', y_train_score) print("測試集score: ", y_test_score)
訓練集score:0.928600622449398 測試集score:0.9289130339796056
可以看得出與多重判定係數的結果是一致的, 說明sklearn自帶的評估器採用的是多重判定係數.
由於我們是假設全部自變數與因變數服從線性關係, 那麼到底是否真正服從呢? 這就需要進行檢驗才能得知, 即進入下一步: 模型檢驗
4. 模型檢驗
首先, 我們需要檢驗模型是否服從線性關係,
1) 線性關係檢驗
由於該檢驗統計量是以殘差平方和(SSE)和迴歸平方和(SSR)為基礎, 故除以它們各自的自由度來構造F檢驗統計量,
即服從分子自由度為k, 分母自由度為n-k-1的F分佈, 其中k為自變數個數, n為樣本量. 進行假設檢驗主要分為5個步驟:
① 提出原假設和備擇假設: H 0 : , H 1 : 不全為0
② 確定顯著性水平:
③ 選擇檢驗統計量:
④ 建立決策準則:有兩種方式一種是拒絕域, 一種是P值.
a. 拒絕域: 即拒絕原假設的區域, 該拒絕域通過臨界點 (由於F統計量為二次型, 因此取值非負, 僅有一個拒絕域, 故為α) 來確定, 如果F檢驗統計量落入拒絕域, 則拒絕原假設從而接受備擇假設, 否則不能拒絕原假設.
b. P值: P值表示原假設發生的可能性(概率), 若可能性小於顯著性水平, 即小概率事件, 那麼就拒絕原假設從而接受備擇假設, 否則, 不能拒絕原假設.
⑤ 下結論: 根據決策準則, 做出是否拒絕原假設的結論.
from pandas import Series from scipy.stats import f #將array轉為series格式 y_train_pred = Series(y_train_pred, index=y_train.index) #分別計算訓練資料上的SSR和SSE y_train_ssr = y_train_pred.apply(lambda x: (x - y_train.mean())**2).sum() y_train_sse = y_train.sub(y_train_pred).apply(lambda x: x**2).sum() #dn是SSR的自由度(自變數個數), df則是SSE的自由度 dn, df = 4, y_train.shape[0]-dn-1 #計算F值 y_train_f = (y_train_ssr/dn) / (y_train_sse/df) #計算p值 p = f.sf(y_train_f, dn, df) #計算0.05顯著性水平下臨界值 cr_value = f.isf(0.05, dn, df) print('訓練資料集F值: ', y_train_f) print('0.05顯著性水平下臨界值: ', cr_value) print('訓練資料集P值: %.20f'% p)
訓練資料集F值:24870.196368594174 0.05顯著性水平下臨界值:2.3730935370191646 訓練資料集P值: 0.00000000000000000000
F值大於臨界值, 拒絕原假設H 0 ( P值小於顯著性水平, 同樣可以拒絕原假設), 表明全部自變數與因變數的線性關係是顯著的, 但這並不意味著每個自變數都和因變數的線性關係顯著, 因此還需要進行迴歸係數(自變數)檢驗.
2) 迴歸係數檢驗
對每個迴歸係數構造t檢驗統計量:
其中, 表示第i個迴歸係數的估計值(因為是根據最小二乘法估計的, 而不是真實值),
表示第i個迴歸係數的標準誤差. 則:
其中, MSE表示無偏殘差平方和, 即殘差平方和SSE除以它的自由度(n-k-1), C ii 表示(XX T ) -1 逆矩陣i行第i列的元素. t檢驗過程同樣是五步驟:
① 提出原假設和備擇假設: H 0 : , H 1 : 不為0
② 確定顯著性水平:
③ 選擇檢驗統計量:
④ 建立決策準則: 同樣有兩種方式, 不過t檢驗的拒絕域有兩個.
⑤ 下結論: 根據決策準則做出是否拒絕原假設的結論
from scipy.stats import t def get_tvalue(sse, df, matr, beta, i): '''計算t值''' mse = sse / df sbeta = sqrt(matr[i+1, i+1]* mse) t = beta / sbeta return t limit = t.isf(0.025, df) print('0.05顯著性水平下的臨界值: ', limit) X_train['B'] = 1 X_train = X_train.reindex(columns=['B', 'AT', 'V', 'AP', 'RH']) #轉成矩陣 xm = np.mat(X_train) #計算(X'X)的逆矩陣 xmi = np.dot(xm.T, xm).I index, betas = range(4), LR.coef for i, beta in zip(index, betas): tvalue = get_tvalue(y_train_sse, df, xmi, beta, i) pvalue = t.sf(abs(tvalue), df)*2 print('beta{0}的t值: '.format(i+1), tvalue) print('beta{0}的p值: '.format(i+1), pvalue)
0.05顯著性水平下的臨界值:2.085963447265837 beta1的t值:-5.898890146924707 beta1的p值:9.049074948455422e-06 beta2的t值:-1.4562620735727096 beta2的p值:0.16084038317451793 beta3的t值:0.34176894237398453 beta3的p值:0.7360897563076247 beta4的t值:-1.734158669159414 beta4的p值:0.09827823435663764
從以上結果中可以看到只有beta1(自變數AT)的t值的絕對值大於臨界值, 即只有beta1拒絕原假設, 也就是說4個自變數中只有beta1影響是顯著的, 那麼為什麼其他自變數不呢? 造成這種的原因可能是自變數之間高度相關, 這種問題稱為多重共線性.
5.5 多重共線性
引用百度百科的定義
多重共線性是指線性迴歸模型中的解釋變數之間由於存在精確相關關係或高度相關關係而使模型估計失真或難以估計準確。
根據定義可知, 多重共線性的判別方法是相關係數矩陣, 檢視之前的相關係數矩陣發現在AT和V這兩個解釋變數(自變數)之間存在高度相關關係: 數值為0.84. 因此可以認為變數間存在多重共線性.
對於多重共線性的處理方法有: 刪除共線變數, 轉換模型的形式, 逐步迴歸法, 嶺迴歸法, 主成分分析法. 在這裡我採用前兩種方法.
1. 刪除共線變數: 通常是刪除高度相關的變數, 保留重要的變數. 重要的變數是指通過t檢驗的變數, 於是我們刪除V這個解釋變數.
X1, y1 = df[['AT', 'AP', 'RH']], df['PE'] X1_train, X1_test, y1_train, y1_test = train_test_split(X1, y1, test_size = 0.2) #訓練模型, 預測以及計算均方根誤差和多重判定係數 LR1 = LinearRegression() LR1.fit(X1_train, y1_train) inter, co = LR1.intercept_, LR1.coef_ y1_train_pred = LR1.predict(X1_train) y1_train_rmse = sqrt(metrics.mean_squared_error(y1_train, y1_train_pred)) y1_train_score = LR1.score(X1_train, y1_train) print("迴歸模型: PE={0}+{1}AT+{2}AP+{3}RH".format(inter,co[0], co[1], co[2])) print('訓練集RMSE: ', y1_train_rmse) print('訓練集擬合優度: ', y1_train_score) #計算F檢驗中0.05顯著性水平下的P值 y1_train_pred = Series(y1_train_pred, index=y1_train.index) y1_train_ssr = y1_train_pred.apply(lambda x: (x - y1_train.mean())**2).sum() y1_train_sse = y1_train.sub(y1_train_pred).apply(lambda x: x**2).sum() dn1, df1 = 3, y1_train.shape[0]-3-1 y1_train_f = (y1_train_ssr/dn1) / (y1_train_sse/df1) y1_p = f.sf(y1_train_f, dn1, df1) # cr_value = f.isf(0.05, dn, df) print('F檢驗 0.05顯著性水平下訓練資料的P值: %.20f'% y1_p) #計算t檢驗在0.05顯著性水平下的P值 def get_t1value(sse, df, matr, beta, i): mse = sse / df sbeta = sqrt(matr[i+1, i+1]* mse) t = beta / sbeta return t X1_train['B'] = 1 X1_train = X1_train.reindex(columns=['B', 'AT', 'AP', 'RH']) xm1 = np.mat(X1_train) xmi1 = np.dot(xm1.T, xm1).I index, betas = range(3), LR1.coef_ for i, beta in zip(index, betas): tvalue = get_t1value(y1_train_sse, df1, xmi1, beta, i) pvalue = t.sf(abs(tvalue), df1)*2 print('t檢驗 0.05顯著性水平下beta{0}的p值: '.format(i+1), pvalue) View Code
迴歸模型: PE=485.39627734198206+-2.374833922164532AT+0.030214741968456443AP+-0.20456036084843196RH 訓練集RMSE:4.839764102773314 訓練集擬合優度:0.9195738379930241 F檢驗 0.05顯著性水平下訓練資料的P值: 0.00000000000000000000 t檢驗 0.05顯著性水平下beta1的p值:0.0 t檢驗 0.05顯著性水平下beta2的p值:0.006605096641032901 t檢驗 0.05顯著性水平下beta3的p值:0.0
均方根誤差比之前增大0.3, 擬合優度相比之前減少0.009, F檢驗通過, 且迴歸係數均通過, 可見刪除共線變數還是可以有效解決多重共線性問題, 但是誤差相比之前增大0.2, 因此這種方法還是有一定侷限性. 換另外一種方法試試.
2. 轉換模型形式: 將資料進行對數轉換.
df_log = np.log(df)
迴歸模型: PE=2.8675586960921957+-0.05125235913516803AT+-0.05608345239278856V+0.5268863140584524AP+-0.0059335463238909605RH 訓練集RMSE:0.010378041999902672 訓練集擬合優度:0.9229456762426529 F檢驗 0.05顯著性水平下訓練資料的P值: 0.00000000000000000000 t檢驗 0.05顯著性水平下beta1的p值:0.0 t檢驗 0.05顯著性水平下beta2的p值:0.0 t檢驗 0.05顯著性水平下beta3的p值:8.936059858590797e-108 t檢驗 0.05顯著性水平下beta4的p值:1.7118836102396494e-20
同樣也都通過檢驗, 而且經過對數轉換後的均方根誤差更小. 對比可以發現進行對數轉換比刪除變數的擬合優度更好些. 我們接下來便是用轉換後的模型去預測了.
5.6 測試集預測
import matplotlib.pyplot as plt #用訓練好的模型去預測 y2_test_pred = LR2.predict(X2_test) y2_test_rmse = sqrt(metrics.mean_squared_error(y2_test, y2_test_pred)) # y1_test_rmse = sqrt(metrics.mean_squared_error(y1_test, y1_test_pred)) y2_test_score = LR2.score(X2_test, y2_test) print('測試集RMSE: ', y2_test_rmse) print('測試集擬合優度: ', y2_test_score) #繪製曲線 plt.figure(figsize=(12,8)) plt.plot(range(len(y2_test)), y2_test, 'g', label='test data') plt.plot(range(len(y2_test_pred)), y2_test_pred, 'r', label='predict data', linewidth=2, alpha=0.8) plt.legend() plt.savefig('tp.png') plt.show()
測試集RMSE:0.01038585831215862 測試集擬合優度:0.9223780289364194
可以看到在測試集上表現還是相當不錯的
以上便是對線性迴歸模型學習過程的總結, 若存在問題, 希望指出, 謝謝!
參考
網易雲課堂《吳恩達機器學習》