建立線性迴歸模型的完整步驟(附代碼)


O、簡述

本案例所用數據爲北京市統計局1中的數據,欲瞭解 地區生產總值(因變量)與 全社會固定資產投資、社會消費品零售總額、進出口總值(三個自變量)之間的迴歸關係,即多元線性迴歸問題
模型的建立,都是在一定的假設條件下成立的,線性迴歸自然也不會例外。其五大假設2 前提,具體見【數據診斷】部分。其中部分假設前提可以在數據準備好,也就是 建模前 就可以進行檢驗,包括:誤差項ε服從正態分佈、無多重共線性、線性相關性。來輔助初始模型的建立。當然,通過建模後,再診斷從而根據問題修正模型也是可以的。

像本博文梳理的目錄結構,除了數據預處理環節,最後確定一個線性迴歸模型需要包括:建立模型、模型檢驗、模型診斷 及 針對診斷問題修正模型,不斷重複這個過程,直到符合預期。
暫不對模型預測和部署做考慮,相對來說,建好模型後,預測只需按照建模過程中的數據準備工作,將待預測數據參照處理即可。

一、建立模型

本博文主要針對線性模型的一些主要方法步驟進行梳理,對於建模前的通用工作: 數據探索工作 內容暫不做考慮,後續會整理篇博文彙總這方面的相關要點。
簡單點,直接進入建模環節。使用專門用於統計建模的第三方模塊statsmodels,調用子模塊中的ols函數進行建模。

# 導入第三方模塊
import scipy.stats as stats
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from sklearn import model_selection
import statsmodels.api as sm

# 中文和負號的正常顯示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False

# 讀取數據
gdp_data = pd.read_csv('北京市投資與GDP數據.csv',encoding='gbk',index_col=0)
# data.columns = ['全社會固定資產投資', '社會消費品零售總額', '進出口總值', '地區生產總值']
# 將數據集拆分爲訓練集和測試集
train,test = model_selection.train_test_split(gdp_data ,test_size=0.2,random_state=1234)
# 根據訓練集train進行建模
model = sm.formula.ols('地區生產總值 ~ 全社會固定資產投資 + 社會消費品零售總額 + 進出口總值',data=train).fit()
print('模型的偏回歸係數分別爲:\n',model.params)

# 剔除測試集test中的 地區生產總值 變量,用剩下的自變量進行預測
test_x = test.drop(labels='地區生產總值',axis=1)
pred = model.predict(exog = test_x)
print('\n對比預測值和實際值的差異:\n',pd.DataFrame({'predict_y':pred,'real_y':test['地區生產總值']}))

迴歸模型已經構建完成,該模型的好與壞並沒有相應的結論,也就是我們下一步要做的事情。

二、模型檢驗

模型檢驗包括:模型的顯著性檢驗模型迴歸係數的顯著性檢驗

  • 模型的顯著性檢驗 是指構成因變量的線性組合是否有效,即整個模型中是否至少存在一個自變量能夠真正影響到因變量的波動。該檢驗是用來衡量模型的整體效應。
  • 迴歸係數的顯著性檢驗 是爲了說明單個自變量在模型中是否有效,即自變量對因變量是否具有重要意義。這種檢驗則是出於對單個變量的肯定與否。

1 模型的顯著性檢驗——F檢驗

# 導入模塊
from scipy.stats import f

# 模型的F統計量值
print('模型的F統計量值:',model.fvalue)

# 計算F分佈的理論值
p = model.df_model #統計變量個數
n = train.shape[0] # 觀測個數
F_Theroy = f.ppf(q=0.95,dfn=p,dfd=n-p-1)
print('F分佈的理論值:',F_Theroy)

模型的F統計量值: 478.94788648827745
F分佈的理論值: 3.490294819497605

2 模型迴歸係數的顯著性檢驗——t檢驗

關於係數的顯著性檢驗,需要使用t檢驗法,構造t統計量。
在建立的模型中,其概覽信息中就包含相應的各項指標值。簡便起見,直接調用summary方法

model.summary()

模型的概覽信息包含三個部分:

  • 第一部分主要是有關模型的信息
    • 模型的判決係數R2,用來衡量自變量對因變量的解釋程度
    • 模型的F統計量值,用來檢驗模型的顯著性
    • 模型的信息準則AIC或BIC,用來對比模型擬合效果的好壞等
  • 第二部分主要包含偏回歸係數的信息
    • 迴歸係數的估計值 coef、t統計量值、迴歸係數的置信區間
  • 第三部分主要涉及模型誤差項 ε\varepsilon 的有關信息
    • 杜賓-瓦特森統計量Durbin-Watson,用於檢驗誤差項獨立性
    • JB統計量,用於衡量誤差項是否服從正態分佈
    • 有關誤差項偏度Skew和峯度Kurtosis的計算值等

三、數據診斷

統計學家在發明線性迴歸模型的時候就提出了一些假設前提,只有在滿足這些假設前提的情況下,所得的模型纔是合理的3。包括:

  • 誤差項ε服從正態分佈
  • 無多重共線性
  • 線性相關性
  • 誤差項ε的獨立性
  • 方差齊性

除此之外,線性迴歸模型對異常值也是非常敏感的,以及缺失值等數據預處理的基礎工作(後續會專門整理篇博文彙總這方面的相關處理手段)

1 正態性檢驗

模型的前提假設是對殘差項要求服從正態分佈,但是其實質就是要求因變量服從正態分佈。關於正態性檢驗通常運用兩類方法:

  • 定性的圖形法(直方圖、PP圖或QQ圖)
  • 定量的非參數法(Shapiro檢驗和K-S檢驗)

1.1 檢驗方法

1.1.1 直方圖法

y = gdp_data['地區生產總值']
X = gdp_data[['全社會固定資產投資', '社會消費品零售總額', '進出口總值']]
# 繪製直方圖
sns.distplot(a= y ,bins = 5, fit=stats.norm,norm_hist=True,
            hist_kws = {'color':'steelblue','edgecolor':'black'},
            kde_kws = {'color':'black','linestyle':'--','label':'核密度曲線'},
            fit_kws = {'color':'red','linestyle':':','label':'正態密度曲線'})
# 顯示圖例
plt.legend()
# 顯示圖形
plt.show()

在這裏插入圖片描述
繪製了因變量地區生產總值的直方圖、核密度曲線和理論正態分佈的密度曲線,添加兩條曲線的目的就是比對數據的實際分佈與理論分佈之間的差異。如果兩條曲線近似或吻合,就說明該變量近似服從正態分佈。

1.1.2 PP圖與QQ圖

  • PP圖的思想是比對正態分佈的累計概率值和實際分佈的累計概率值
  • QQ圖則比對正態分佈的分位數和實際分佈的分位數

判斷變量是否近似服從正態分佈的標準是:如果散點都比較均勻地散落在直線上,就說明變量近似服從正態分佈,否則就認爲數據不服從正態分佈。

# 殘差的正態性檢驗(PP和QQ)
pp_qq_plot = sm.ProbPlot(y)
# 繪製PP圖
pp_qq_plot.ppplot(line = '45')
plt.title('P-P圖')
# 繪製QQ圖
pp_qq_plot.qqplot(line='q')
plt.title('Q-Q圖')
plt.show()
在這裏插入圖片描述 在這裏插入圖片描述

1.1.3 Shapiro檢驗和K-S檢驗

這兩種檢驗方法均屬於非參數方法,它們的原假設被設定爲變量服從正態分佈,兩者的最大區別在於適用的數據量不一樣。

  • 若數據量低於5000,則使用shapiro檢驗法比較合理
  • 若數據量大於5000,則使用K-S檢驗法

scipy的子模塊stats提供了專門的檢驗函數,分別是shapiro函數和kstest函數。
如果使用kstest函數對變量進行正態性檢驗,必須指定args參數,它用於傳遞被檢驗變量的均值和標準差。

# Shapiro檢驗
sp = stats.shapiro(y)
print("shapiro檢驗的統計量值:%.4f,對應的概率值p爲:%.4f"%(sp))

shapiro檢驗的統計量值:0.9255,對應的概率值p爲:0.1263

# K-S檢驗
# 爲了應用K-S檢驗的函數kstest,這裏隨機生成正態分佈變量rnorm和均勻分佈變量runif
rnorm = np.random.normal(loc=5,scale=2,size=15000)
runif = np.random.uniform(low=1,high=50,size=15000)

# 正態性檢驗
ks_rnorm = stats.kstest(rvs=rnorm,args=(rnorm.mean(),rnorm.std()),cdf='norm')
ks_runif = stats.kstest(rvs=runif,args=(runif.mean(),runif.std()),cdf='norm')
print("rnorm 的 K-S檢驗的統計量值:%.4f,對應的概率值p爲:%.4f"%(ks_rnorm))
print("runif 的 K-S檢驗的統計量值:%.4f,對應的概率值p爲:%.4f"%(ks_runif))

rnorm 的 K-S檢驗的統計量值:0.0054,對應的概率值p爲:0.7702
runif 的 K-S檢驗的統計量值:0.0631,對應的概率值p爲:0.0000

1.2 校正方法

如果因變量的檢驗結果不滿足正態分佈時,需要對因變量做某種數學轉換,使用比較多的轉換方法有log(y)log(y)y\sqrt y1y\frac{1}{\sqrt y}1y\frac{1}{y}y2y^21y2\frac{1}{y^2}等。

2 多重共線性檢驗

多重共線性是指模型中的自變量之間存在較高的線性相關關係,它的存在會給模型帶來嚴重的後果。包括:

  • 由“最小二乘法”得到的偏回歸係數無效
  • 增大偏回歸係數的方差
  • 模型缺乏穩定性等

2.1 檢驗方法

2.1.1 方差膨脹因子VIF

關於多重共線性的檢驗可以使用方差膨脹因子VIF來鑑定。

  • 如果VIF大於10,則說明變量間存在多重共線性;
  • 如果VIF大於100,則表名變量間存在嚴重的多重共線性。

方差膨脹因子VIF的計算步驟如下:

  1. 構造每一個自變量與其餘自變量的線性迴歸模型:x1=c0+α2x2+...+αpxp+εx_1 = c_0+\alpha_2 x_2+...+\alpha_p x_p+\varepsilon
  2. 根據如上線性迴歸模型得到相應的判決係數R2R^2,進而計算第一個自變量的方差膨脹因子VIF:VIF1=11R2VIF_1=\frac{1}{1-R^2}
# 導入statsmodels模塊中的VIF函數
from statsmodels.stats.outliers_influence import variance_inflation_factor
# 自變量添加常數列
X = sm.add_constant(X)

# 構造空的數據框,用於存儲VIF值
vif = pd.DataFrame()
vif['features'] = X.columns
vif['VIF Factor'] = [variance_inflation_factor(X.values,i) for i in range(X.shape[1])]
# 查看VIF值
vif

在這裏插入圖片描述

2.2 校正方法

如果發現變量之間存在多重共線性的話,可以考慮刪除變量或者重新選擇模型(如嶺迴歸模型或LASSO模型)。

3 線性相關性檢驗

就是確保用於建模的自變量和因變量之間存在線性關係。

3.1 檢驗方法

關於線性關係的判斷,可以使用Pearson相關係數和可視化方法進行識別。

3.1.1 Pearson相關係數

Pearson相關係數計算公式:
ρx,y=COV(x,y)D(x)D(y)\rho_{x,y} =\frac{COV(x,y)}{\sqrt {D(x)}\sqrt {D(y)}}

Pearson相關係數的計算可以直接使用數據框的corrwith“方法”,該方法最大的好處是可以計算任意指定變量間的相關係數。

# 計算因變量與每個自變量的相關係數
xy_corr = X.corrwith(y)
xy_corr
變量 Pearson相關係數
const NaN
全社會固定資產投資 0.984303
社會消費品零售總額 0.995849
進出口總值 0.869777

3.1.2 可視化的方法——散點圖矩陣

# 繪製散點圖矩陣
sns.pairplot(data)
# 顯示圖形
plt.show()

4 殘差的獨立性檢驗

殘差的獨立性檢驗,實質上也是對因變量y的獨立性檢驗,因爲在線性迴歸模型的等式左右只有y和殘差項ε屬於隨機變量,如果再加上正態分佈,就構成了殘差項獨立同分佈於正態分佈的假設。

4.1 檢驗方法

4.1.1 DW檢驗(Durbin-Watson)

關於殘差的獨立性檢驗通常使用Durbin-Watson統計量值來測試。

  • 如果DW值在2左右,則表明殘差項之間是不相關的;
  • 如果與2偏離的較遠,則說明不滿足殘差的獨立性假設。

對於DW統計量的值,它包含在模型的概覽信息中,因此殘差的獨立性檢驗可以在建模後,通過模型的概覽信息來查看。

model.summary()

5 方差齊性檢驗

方差齊性是要求模型殘差項的方差不隨自變量的變動而呈現某種趨勢,否則,殘差的趨勢就可以被自變量刻畫。如果殘差項不滿足方差齊性(方差爲一個常數),就會導致偏回歸係數不具備有效性,甚至導致模型的預測也不準確。所以,建模後需要驗證殘差項是否滿足方差齊性。
關於方差齊性的檢驗,一般可以使用兩種方法:

  • 圖形法(散點圖)
  • 統計檢驗法(BP檢驗和White檢驗)

5.1 檢驗方法

5.1.1 圖形法-散點圖

方差齊性是指殘差項的方差不隨自變量的變動而變動,所以只需要繪製殘差與自變量之間的散點圖,就可以發現兩者之間是否存在某種趨勢


fig = plt.figure(figsize=(15,5))
tu_num = 3 #子圖數量
for i in range(tu_num):
    # 設置第一張子圖的位置
    ax = plt.subplot2grid(shape=(1,tu_num),loc=(0,i))
    # 繪製散點圖
    temp_x = train.ix[:,i]
    ax.scatter(temp_x,(model.resid-model.resid.mean())/model.resid.std())
    # 添加水平參考線
    ax.hlines(y=0,xmin=temp_x.min(),xmax=temp_x.max(),color='red',linestyles='--')
    #添加x軸和y軸標籤
    ax.set_xlabel(train.columns[i])
    ax.set_ylabel('Std_Residual')
    
# #調整子圖之間的水平間距和高度間距
# plt.subplots_adjust(hspace=0.1,wspace=0.3)
#顯示子圖   
plt.show()

在這裏插入圖片描述
標準化殘差隨自變量的變動而呈現一定趨勢,所有的散點並未均勻的分佈在參考線y=0的附近。可以說明模型的殘差項不滿足方差齊性的前提假設。

5.1.2 統計檢驗法(BP檢驗)

BP檢驗的原假設是殘差的方差爲一個常數,通過構造拉格朗日乘子LM統計量,實現方差齊性的檢驗。該檢驗可以藉助於statsmodels模塊中的het_breuschpagan函數完成。

# BP檢驗
bp_test = sm.stats.diagnostic.het_breuschpagan(model.resid,exog_het=model.model.exog)
                              
print('''
LM統計量:%.4f,
LM統計量對應的概率p值:%.4f,
F統計量:%.4f(用於檢驗殘差平方項與自變量之間是否獨立),
F統計量的概率p值:%.4f(進一步驗證殘差項滿足方差齊性的假設)
'''%(bp_test))

LM統計量:4.8883,
LM統計量對應的概率p值:0.1802,
F統計量:1.7597(用於檢驗殘差平方項與自變量之間是否獨立),
F統計量的概率p值:0.2082(進一步驗證殘差項滿足方差齊性的假設)

5.1.3 統計檢驗法(White檢驗)

# White檢驗
hw_test = sm.stats.diagnostic.het_white(model.resid,exog=model.model.exog)
                              
print('''
LM統計量:%.4f,
LM統計量對應的概率p值:%.4f,
F統計量:%.4f(用於檢驗殘差平方項與自變量之間是否獨立),
F統計量的概率p值:%.4f(進一步驗證殘差項滿足方差齊性的假設)
'''%(hw_test))

LM統計量:14.3086,
LM統計量對應的概率p值:0.1118,
F統計量:5.6398(用於檢驗殘差平方項與自變量之間是否獨立),
F統計量的概率p值:0.0238(進一步驗證殘差項滿足方差齊性的假設)

5.2 校正方法

如果模型的殘差不滿足齊性的話,可以考慮兩類方法來解決:

  1. 模型變換法
    對於模型變換法來說,主要考慮殘差與自變量之間的關係。
    • 如果殘差與某個自變量x成正比,則需將原模型的兩邊同除以x\sqrt x
    • 如果殘差與某個自變量x的平方成正比,則需將原始模型的兩邊同除以x;
  2. “加權最小二乘法”(可以使用statsmodels模塊中的wls函數)
    對於加權最小二乘法來說,關鍵是如何確定權重,一般選擇如下三種權重來進行對比測試:
    • 殘差絕對值的倒數作爲權重
    • 殘差平方的倒數作爲權重
    • 用殘差的平方對數與自變量X重新擬合建模,並將得到的擬合值取指數,用指數的倒數作爲權重

6 異常值檢驗

如果在建模過程中發現異常數據,需要對數據集進行整改,如刪除異常值或衍生出是否爲異常值的啞變量。對於線性迴歸模型來說,通常利用:

  • 帽子矩陣
  • DFFITS準則
  • 學生化殘差
  • Cook距離
    進行異常點檢測。

6.1 檢驗方法

6.1.1 帽子矩陣

帽子矩陣的設計思路就是考察第i個樣本對預測值y^\hat{y}的影響大小。
帽子矩陣:H=X(XX)X1XH=X(X'X)X^{-1}X'
判斷樣本是否爲異常值的準則:hii2(p+1)nh_{ii}\ge \frac{2(p+1)}{n}
其中hiih_{ii}爲帽子矩陣H的第i個主對角線元素,p爲自變量個數,n爲用於建模數據集的樣本量。如果對角線元素滿足上面的公式,則代表第i個樣本爲異常觀測。

6.1.2 DFFITS準則

DFFITS準則藉助於帽子矩陣,構造了另一個判斷異常點的統計量:
Di(σ)=hii1hiiεiσ1hiiD_i(\sigma)=\sqrt{\frac{h_{ii}}{1-h_{ii}}} \frac{\varepsilon_i}{\sigma \sqrt{1-h_{ii}}}
其中εi\varepsilon_i爲第i個樣本點的預測誤差,σ\sigma爲誤差項的標準差。在DFFITS準則的公式中,乘積的第二項實際上是學生化殘差。
判斷樣本爲異常值的準則:Di(σ)>2p+1n\mid D_i(\sigma)\mid>2\sqrt{\frac{p+1}{n}}

6.1.3 學生化殘差

判斷樣本爲異常值的準則:γi=εiσ1hii>2\gamma_i = \frac{\varepsilon_i}{\sigma \sqrt{1-h_{ii}}} > 2

6.1.4 Cook距離

Cook距離是一種相對抽象的判斷準則,無法通過具體的臨界值判斷樣本是否爲異常點,對於該距離,Cook統計量越大的點,其成爲異常點的可能性越大。公式如下:
Distancei=1p+1(hii1hii)γi2Distance_i = \frac{1}{p+1}(\frac{h_{ii}}{1-h_{ii}}){\gamma_i}^2

如果使用如上四種方法判別數據集的第i個樣本是否爲異常點,前提是已經構造好一個線性迴歸模型,然後基於get_influence方法獲得四種統計量的值。

# 異常值檢驗
outliers = model.get_influence()

# 帽子矩陣
hat_mat = outliers.hat_matrix_diag
# DFFITS值
dffits = outliers.dffits[0]
# 學生化殘差
resid_stu = outliers.resid_studentized_external
# cook距離
cook = outliers.cooks_distance[0]

# 合併四種異常值檢驗的統計量值
concat_four_out = pd.concat([pd.Series(hat_mat,name='帽子矩陣'),pd.Series(dffits,name='DFFITS值'),
                            pd.Series(resid_stu,name='學生化殘差'),pd.Series(cook,name='Cook距離')],axis=1)

# 計算異常值比例,以學生會殘差爲例
outliers_ratio = sum(np.where(np.abs(resid_stu>2),1,0))/resid_stu.shape[0]
print("計算異常值比例,以學生會殘差爲準則,異常值比例爲:",outliers_ratio)

# 挑選出無異常的觀測點
none_outliers = train.ix[np.abs(resid_stu<=2),:]
none_outliers                  

計算異常值比例,以學生會殘差爲準則,異常值比例爲: 0.0625。
之後可根據無異常值再進行建模過程。

四、小結

如你所看到的,很多診斷結果我們只是列了結果,沒有給出相應的結論或者說明。這是因爲小編想着重記錄的是線性迴歸模型建模過程中,應該包括的一些必不可少的步驟及對應的python實現方法。如有不明之處,我們可評論區交流學習。


  1. 北京市統計局 ↩︎

  2. 計量經濟學 / 張曉峒著. —北京:清華大學出版社,2017(2018.9重印) ↩︎

  3. 從零開始學Python數據分析與挖掘/劉順祥著.—北京:清華大學出版社,2018ISBN 978-7-302-50987-5 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章