嶺迴歸和LASSO迴歸模型(簡記Logistic迴歸分類模型)

線性迴歸模型的參數估計得到的前提是變量構成的矩陣可逆。在實際問題中,常出現的問題:

  • 可能會出現自變量個數多於樣本
  • 自變量間存在多重共線性的情況

爲解決這類問題,可基於線性迴歸模型擴展的迴歸模型:嶺迴歸和LASSO迴歸模型1進行處理。最後,對Logistic模型的特點做一簡記。

一、嶺迴歸模型

在線性迴歸模型的目標函數之上添加一個 L2 的正則項(也稱爲懲罰項),進而使得模型的迴歸係數有解。
λ\lambdaL2 正則項平方的係數,用來平衡模型的方差(迴歸係數的方差)和偏差(真實值與預測值之間的差異)

目標函數加上L2正則項的示意圖

上圖的示意比常見的示意圖應該更好理解。拋物面與圓面的交點很難發生在軸上,即某個變量的迴歸係數 β\beta 爲0,所以嶺迴歸模型並不能從真正意義上實現變量的選擇

1 λ 值的確定

關於λ值的確定,通常可以使用兩種方法:

  • 一種是可視化方法
  • 另一種是交叉驗證法

1.1 可視化方法確定 λ

通過繪製不同的λ值和對應迴歸係數的折線圖確定合理的λ值。一般而言,當迴歸係數隨着λ值的增加而趨近於穩定的點時就是所要尋找的λ值
在Python中,可以使用sklearn子模塊linear_model中的Ridge類實現模型係數的求解。

Ridge(
alpha=1.0, # 用於指定lambda值的參數,默認該參數爲1。
fit_intercept=True, # bool類型參數,是否需要擬合截距項,默認爲True
normalize=False, # bool類型參數,建模時是否需要對數據集做標準化處理,默認爲False
copy_X=True, # bool類型參數,是否複製自變量X的數值,默認爲True
max_iter=None, # 用於指定模型的最大迭代次數
tol=0.001, # 用於指定模型收斂的閾值
solver=‘auto’, # 用於指定模型求解最優化問題的算法,默認爲’auto’,表示模型根據數據集自動選擇算法
random_state=None # 用於指定隨機數生成器的種子
)

# 導入第三方模塊
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import model_selection
from sklearn.linear_model import Ridge
import warnings
warnings.filterwarnings("ignore")   # 忽略警告信息輸出

# 讀取數據
bingdata = pd.read_excel(r'diabetes.xlsx',sep='')
# 選擇自變量、因變量
X,y = bingdata.ix[:,2:-1],bingdata.ix[:,-1]
# 將數據集拆分爲訓練集、測試集
X_train,X_test,y_train,y_test = model_selection.train_test_split(X,y,test_size=0.2,random_state=123)

# 構造不同的 lambda值
lambds = np.logspace(-5,2,200)
# 構造空列表,用於存儲模型的偏回歸係數
ridge_coffs = []
# 求解不同lambda對應的係數值
for lambd in lambds:
    ridge = Ridge(alpha=lambd,normalize=True)
    ridge.fit(X_train,y_train)
    ridge_coffs.append(ridge.coef_)

# 繪製lambda 的對數與迴歸係數的關係
# 設置繪圖風格
plt.style.use('seaborn')
# 爲了畫圖中文可以正常顯示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] #指定默認字體
plt.rcParams['axes.unicode_minus'] = False  #解決保存圖像時負號'-'顯示爲方塊的問題

plt.plot(lambds,ridge_coffs)
# 對x軸做對數處理
plt.xscale('log')
# 設置x軸和y軸標籤
plt.xlabel('Log($\lambda$)')
plt.ylabel('Cofficients')
plt.title('正則項係數與迴歸係數之間的關係')
# 顯示圖形
plt.show()

在這裏插入圖片描述

使用plotly_express模塊可視化,讓圖表好看點,並且可以互動。

# 加載模塊
import plotly_express as px  

# 正則項係數與迴歸係數之間的關係
p_lam = [lambds] * 8
p_lam = pd.Series(pd.DataFrame(p_lam).values.ravel())
c_s = pd.DataFrame(ridge_coffs,columns=['c'+str(i) for i in range(1,9)])
c_res = pd.Series()
for i in range(8):
    temp = pd.Series(c_s['c'+str(i+1)])
    temp.index=len(lambds)*['c'+str(i+1)]
    c_res = pd.concat([c_res,temp])
c_res = pd.DataFrame(c_res)
c_res = c_res.reset_index()
xy_df= pd.concat([p_lam,c_res],axis=1)
xy_df.columns =['lambda','coef','coef_values']
px.line(xy_df,x="lambda",y='coef_values',log_x=True,color='coef',height=400,width=600)

正則項係數與迴歸係數之間的關係

上圖展現了不同的λ值與迴歸係數之間的折線圖,圖中的每條折線代表了不同的係數,對於比較突出的喇叭形折線,一般代表該變量存在多重共線性

按照λ值的選擇標準,發現λ值在0.01附近時,絕大多數變量的迴歸係數趨於穩定,故認爲λ值可以選擇在0.01附近。

1.2 交叉驗證法確定λ值

可視化方法只能確定λ值的大概範圍,爲了能夠定量地找到最佳的λ值,需要使用k重交叉驗證的方法。該方法的操作思想可以藉助下圖來說明:

交叉驗證的示意圖

實現嶺迴歸模型的k重交叉驗證,可以使用sklearn子模塊linear_model中的RidgeCV類

RidgeCV(
alphas=(0.1, 1.0, 10.0),
fit_intercept=True,
normalize=False,
scoring=None, # 指定用於評估模型的度量方法
cv=None, # 指定交叉驗證的重數
gcv_mode=None, #用於指定執行廣義交叉驗證的方法,取值有:“auto”、“svd”、“engin”
store_cv_values=False # bool類型參數,是否在每一個Lambda值下都保存交叉驗證得到的評估信息,默認爲False,只有當參數cv爲None時有效。
)

使用十折交叉驗證。

# 導入第三方模塊
from sklearn.linear_model import RidgeCV
ridge_cv = RidgeCV(alphas=lambds,normalize=True,scoring='neg_mean_squared_error',cv=10)
# 模型擬合
ridge_cv.fit(X_train,y_train)
# 返回最佳的lambda值
ridge_best_lambda = ridge_cv.alpha_
print('最佳的lambda值爲:',ridge_best_lambda)

最佳的lambda值爲: 0.0013987131026472386
與可視化方法確定的λ值在0.01附近保持一致。該值的評判標準是:對於每一個λ值計算平均均方誤差(MSE),然後從中挑選出最小的平均均方誤差,並將對應的λ值挑選出來,作爲最佳的懲罰項係數λ的值。

2 模型預測

建模的目的就是對未知數據的預測。使用交叉驗證得到的最佳λ值構建嶺迴歸模並進行預測。

# 基於最佳的lambda值建模
ridge = Ridge(alpha=ridge_best_lambda,normalize=True)
ridge.fit(X_train,y_train)
# 返回嶺迴歸模型係數
ridge_coef = pd.Series(data=[ridge.intercept_]+ridge.coef_.tolist(),index =['Intercept']+X_train.columns.to_list())
print('嶺迴歸模型係數:\n',ridge_coef)

# 模型預測
from sklearn.metrics import mean_squared_error # 均方誤差MSE,評估模型效果
y_pred = ridge.predict(X_test)
# 預測效果驗證  :均方根誤差RMSE
rmse = np.sqrt(mean_squared_error(y_test,y_pred))
print("測試集均方根誤差RMSE:",rmse)

嶺迴歸模型係數:

變量名 變量值
Intercept -334.048369
BMI 5.783170
BP 0.878213
S1 -0.859325
S2 0.480118
S3 0.450037
S4 7.609293
S5 58.340168
S6 0.365901

測試集均方根誤差RMSE: 53.64384657387297

二、LASSO模型

嶺迴歸不管怎麼縮減,都會始終保留建模時的所有變量,無法降低模型的複雜度,爲了克服這個缺點,運用而生LASSO迴歸。與嶺迴歸模型類似,LASSO迴歸同樣屬於縮減性估計,而且在迴歸係數的縮減過程中,可以將一些不重要的迴歸係數直接縮減爲0,即達到變量篩選的功能。LASSO迴歸爲在嶺迴歸模型中的懲罰項由平方和改成了絕對值,即懲罰項爲L1正則式

目標函數加上L1正則項的示意圖

相比於圓面,L1正則項的方框頂點更容易與拋物面相交,從而起到變量篩選的效果。對於無法影響因變量的自變量,LASSO迴歸都將其過濾掉。

1 λ 值的確定

1.1 可視化方法確定 λ 值

在Python中,可以使用sklearn子模塊linear_model中的Lasso類實現模型係數的求解。

Lasso(
alpha=1.0,
fit_intercept=True,
normalize=False,
precompute=False, # bool類型參數,是否在建模前通過計算Gram矩陣提升運算速度,默認爲False
copy_X=True,
max_iter=1000,
tol=0.0001,
warm_start=False, # bool類型參數,是否將前一次的訓練結果用作後一次的訓練,默認爲False
positive=False, # bool類型參數,是否將回歸係數強制爲正數,默認爲False
random_state=None,
selection=‘cyclic’ # 指定每次迭代時所選擇的迴歸係數,如果爲’random’,表示每次迭代中將隨機更新迴歸係數;如果爲’cyclic’,則表示每次迭代時迴歸係數的更新都基於上一次運算
)

# 導入模塊中的函數
from sklearn.linear_model import Lasso

# 空列表,用於存儲模型的偏回歸係數
lasso_coffs = []
for lambd in lambds:
    lasso = Lasso(alpha=lambd,normalize=True)
    lasso.fit(X_train,y_train)
    lasso_coffs.append(lasso.coef_)
# 繪製lambda與迴歸係數的折線圖
plt.plot(lambds,lasso_coffs)
# 對x軸取對數
plt.xscale('log')
plt.xlabel('$\lambda$')
plt.ylabel('cofficients')
plt.show()

在這裏插入圖片描述

與嶺迴歸模型繪製的折線圖類似,出現了喇叭形折線,說明該變量存在多重共線性。當λ值落在0.05附近時,絕大多數變量的迴歸係數趨於穩定,所以,基本可以鎖定合理的λ值範圍,接下來需要通過定量的交叉驗證方法獲得準確的λ值。

1.2 交叉驗證法確定λ值

Python的sklearn模塊提供了現成的接口,只需調用子模塊linear_model中的LassoCV類

LassoCV(
eps=0.001, # 指定正則化路徑長度,默認爲0.001,指代Lambda的最小值與最大值之商
n_alphas=100, # 指定正則項係數Lambda的個數,默認爲100個
alphas=None, # 指定具體的Lambda值列表用於模型的運算
fit_intercept=True,
normalize=False,
precompute=‘auto’,
max_iter=1000,
tol=0.0001,
copy_X=True,
cv=‘warn’, # 指定交叉驗證的重數
verbose=False, # bool類型參數,是否返回模型運行的詳細信息,默認爲False
n_jobs=None, # 指定交叉驗證過程中使用的CPU數量,即是否需要並行處理,默認爲1表示不併行運行,如果爲-1,表示將所有的CPU用於交叉驗證的運算
positive=False,
random_state=None,
selection=‘cyclic’,
)

# 導入第三方模塊
from sklearn.linear_model import LassoCV
# 交叉驗證
lasso_cv = LassoCV(alphas=lambds,normalize=True,cv=10)
lasso_cv.fit(X_train,y_train)
# 輸出最佳的lambda值
lasso_best_alpha = lasso_cv.alpha_
print("最佳lambda值:",lasso_best_alpha)

2 模型預測

使用交叉驗證得到的最佳λ值構建LASSO迴歸模並進行預測。

# 基於最佳的lambda值建模
lasso = Lasso(alpha=lasso_best_alpha,normalize=True)
lasso.fit(X_train,y_train)
# 返回LASSO迴歸模型係數
lasso_coef = pd.Series(data=[lasso.intercept_]+lasso.coef_.tolist(),index =['Intercept']+X_train.columns.to_list())
print('lasso迴歸模型係數:\n',lasso_coef)

# 模型預測
from sklearn.metrics import mean_squared_error # 均方誤差MSE,評估模型效果
y_pred = lasso.predict(X_test)
# 預測效果驗證  :均方根誤差RMSE
rmse = np.sqrt(mean_squared_error(y_test,y_pred))
print("測試集均方根誤差RMSE:",rmse)

lasso迴歸模型係數:

Intercept -346.957063
BMI 5.780151
BP 0.880328
S1 -0.985588
S2 0.593059
S3 0.600946
S4 8.039360
S5 61.497785
S6 0.362785

測試集均方根誤差RMSE: 53.628899177363714

三、Logistic迴歸分類模型

1 模型特點

  • 屬於非線性模型,專門用來解決二分類的離散問題。又和線性迴歸模型有關,屬於廣義的線性迴歸分析模型;
  • 該模型的一個最大特色,具有很強的解釋性。

2 模型用途

可以藉助該模型實現兩大用途

  • 一個是尋找“危險”因素,例如,醫學界通常使用模型中的優勢比尋找影響某種疾病的“壞”因素;
  • 另一個用途是判別新樣本所屬的類別,例如根據手機設備的記錄數據判斷用戶是處於行走狀態還是跑步狀態。

3 模型參數的解釋

  • 發生比的作用只能解釋爲在同一組中事件發生與不發生的倍數。
  • 使用發生比之比就可以解釋模型參數的含義了。

4 模型的構建

可以藉助於sklearn的子模塊linear_model,調用LogisticRegression類

LogisticRegression(
penalty=‘l2’,
dual=False, # bool類型參數,是否求解對偶形式,默認爲False,只有當penalty參數爲’l2’、solver參數爲’liblinear’時,纔可使用對偶形式
tol=0.0001,
C=1.0, #值越小,正則化項越大
fit_intercept=True,
intercept_scaling=1, # 當solver參數爲’liblinear’時該參數有效,主要是爲了降低X矩陣中人爲設定的常數列1的影響
class_weight=None, # 用於指定因變量類別的權重,如果爲字典,則通過字典的形式{class_label:weight}傳遞每個類別的權重;如果爲字符串’balanced’,則每個分類的權重與實際樣本中的比例成反比,當各分類存在嚴重不平衡時,設置爲’balanced’會比較好;如果爲None,則表示每個分類的權重相等
random_state=None,
solver=‘warn’,
max_iter=100,
multi_class=‘warn’,
verbose=0,
warm_start=False,
n_jobs=None,
l1_ratio=None,
)


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

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