1. 程式人生 > 其它 >多重共線性

多重共線性

技術標籤:統計機器學習python機器學習人工智慧資料探勘邏輯迴歸

1.迴歸模型自變數彼此相關稱為多重共線性,它給模型提供重複資訊

2.多重共線性會造成模型不穩定,可能會得到無法解釋的現象

3.檢測共線性的方法通常有相關性分析,顯著性檢驗和方差膨脹因子分析

4.處理共線性的方法通常有提前篩選變數,逐步迴歸選擇,正則化與資料降維

1.多重共線性產生的問題

當迴歸模型(線性迴歸,邏輯迴歸)中兩個或兩個以上的自變數彼此相關時,則稱迴歸模型中存在多重共線性,也就是說共線性的自變數提供了重複的資訊。

它會造成模型不穩定,會造成迴歸係數,截距係數的估計非常不穩定,這種不穩定的具體表現是:很可能迴歸係數原來正,但因為共線性而變為負。這對於一些自變數的可解釋性來講可能是致命的,因為得到錯誤係數無法解釋正常發生的現象。

2.多重共線性檢測方法

多重共線性有很多檢測方法,最簡單直接的就是計算各自變數之間的相關係數,並進行顯著性檢驗。具體的,如果出現以下情況,可能存在多重共線性:

(1)模型中各對自變數之間顯著性相關。

(2)當模型線性關係(F檢驗)顯著時,幾乎所有迴歸係數的t檢驗不顯著。

(3)迴歸係數的正負號與預期的相反。

(4)方差膨脹因子(VIF)檢測,一般認為VIF大於10,則存在嚴重的多重共線性。

前三點在以往的文章(假設檢驗專題,迴歸模型理論分析)都有詳細介紹,這裡我們側重介紹第四點,方差膨脹因子(Variance Inflation Factor,VIF)

先給出方差膨脹因子的表示式:

如果VIF越大,那麼表明可決係數R2越大,說明變數Xi與其他自變數的線性關係強,說明原模型存在多重共線性可能性越大。

經驗判斷方法表明:當0<VIF<10,不存在 多重共線性;當10≤VIF<100,存在較強的多重共線性;當VIF≥100,存在嚴重多重共線性

利用python可以實現方差膨脹因子的計算

fromstatsmodels.stats.outliers_influence importvariance_inflation_factor

defcheckVIF_new(df):
'''

:param df:僅包含所有自變數X的資料集,DataFrame形式
:return: 返回每個變數對於的VIF值
'''
df.insert(0,'constant',1) #新增常數項
name = df.columns
x = np.matrix(df)
VIF_list = [variance_inflation_factor(x,i) fori inrange(x.shape[1])]
VIF = pd.DataFrame({'feature':name,"VIF":VIF_list})

returnVIF

3.多重共線性的處理

多重共線性對於線性迴歸是種災難,並且我們不可能完全消除,而只能利用一些方法來減輕它的影響。對於多重共線性的處理方式,有以下幾種思路:

(1)提前篩選變數:可以利用相關檢驗來或變數聚類的方法。

(2)子集選擇:包括逐步迴歸和最優子集法。常用的是逐步迴歸。

(3)收縮方法:正則化方法。LASSO迴歸可以實現篩選變數的功能。

(4)維數縮減:資料的降維。

第一點在假設檢驗系列有詳細介紹,以後聚類會專門講解;第三點在介紹線性迴歸模型有介紹(傳送門:線性迴歸之原理介紹),第四點在資料降維繫列有介紹,這裡我們側重介紹第二點,逐步迴歸

逐步迴歸分為向前逐步和向後逐步,這裡介紹向後逐步,其思想是:對入模的變數建立模型,從大到小逐步剔除不通過顯著性檢驗p值的變數,再迴圈建立模型,直到所有變數都通過顯著性檢驗。

以邏輯迴歸為例,用python介面statsmodels.api.smf可以實現這個過程:

# 後向逐步法~邏輯迴歸
importstatsmodels.api assmf

defgra_reg(gra_data,X,y,a=0.01):
'''
:param gra_data:要進行逐步迴歸的DataFrame資料集
:param X:自變數列表
:param y:因變數
:param a:顯著性水平,這裡預設為0.01
:return 返回不存在共線性的逐步迴歸結果與變數列表
'''

y_label = gra_data[y]
whileTrue:
X_data = gra_data[X]
# X_data = smf.add_constant(X_data)
anal = smf.Logit(y_label, X_data).fit()
P = anal.pvalues # 得到統計檢驗的P值
P_di = dict(zip(P.keys(), P.values)) # 字典化變數與P值
ifmax(P_di.values()) > a:
X.remove(max(P_di, key=lambdax: P_di[x]))
else:
break
returnanal, X

參考資料:

https://www.zhihu.com/question/270451437