本文作者:王 歌
文字編輯:孫曉玲
在《基於廣義線性模型的機器學習算法——線性回歸》中我們介紹了如何使用線性回歸算法來擬合學習器,但有時使用線性回歸可能會產生過擬合的現象,此時我們通常有兩種途徑解決:一是對特徵進行選擇,減少特徵數量,二是使用正則化的方法,這樣可以保留所有的特徵,而在正則化時我們通常會採用嶺回歸或LASSO回歸,今天我們就來介紹一下這兩種正則化方法。
在介紹嶺回歸與LASSO回歸之前,首先我們考慮這樣一個問題。在線性回歸中我們求解使得損失函數即均方誤差最小的w和b作為回歸中參數的估計值,求解的過程在於對損失函數中的w求偏導,此時我們會得到:
由此可以得到w的值並且是唯一解。但當X的列數多於行數、不滿秩時,此時可以解出多個w,它們都能使損失函數最小,這是我們該如何選擇最優解呢?
在機器學習中通常會選擇正則化的方法來解決這一問題,即在損失函數中加入正則項(懲罰約束)來防止模型過擬合。其防止過擬合的原理,從本質上來說屬於數學上的特徵縮減(shrinkage),由於過擬合過分追求「小偏差」使模型過於複雜,導致擬合的數據分布與真實分布偏差很小但方差很大,此時擬合出的曲線斜率的絕對值大,也就是函數的偏導數大,因而要避免偏導數過大就要減小參數,即通過設置懲罰算子α,使得影響較小的特徵的係數衰減到0,只保留重要特徵從而減少模型複雜度進而達到避免過擬合的目的。這裡的模型複雜度並非是冪次上的數值大,而是模型空間中可選模型的數量多。所以上面問題中加入αI,此時滿秩可求逆。
正則化的優化目標函數一般為:
其中α≥0,對於線性回歸模型,當時的回歸稱為LASSO回歸,稱為L1正則化(或L1範數);當時的回歸稱為嶺回歸,稱為L2正則化(或L2範數)。
1.2嶺回歸
嶺回歸的求解與一般的線性回歸求解方法是類似的。加入了懲罰項後,在求解參數時仍然要求偏導,此時若採用最小二乘法,則
而若採用梯度下降法求解,則
其中,該式為w的一個迭代更新公式,β為步長(學習率)。嶺回歸保留了所有的變量,縮小了參數,所以也就沒有信息的損失,但相應的模型的變量過多解釋性會降低。
LASSO回歸的損失函數完整表達為
2 類參數介紹
在sklearn中進行嶺回歸和LASSO回歸的類分別是Ridge()和Lasso(),首先我們介紹一下這兩個類中用到的參數。
·alpha:即上面講到的正則化懲罰算子α,接受浮點型,默認為1.0。取值越大對共線性的魯棒性越強;
·copy_X:默認為True,表示是否複製X數組,為True時將複製X數組,否則將覆蓋原數組X;
·fit_intercept:默認為True,表示是否計算此模型的截距;
·max_iter:最大迭代次數,接受整型,默認為None;
·normalize:默認為False,表示是否先進行歸一化,當fit_intercept設置為False時,將忽略此參數;
·solver:選擇計算時的求解方法,默認為『auto』,主要有幾種選擇:(1)auto根據數據類型自動選擇求解器;(2)svd使用X的奇異值分解來計算Ridge係數;(3)cholesky使用標準的scipy.linalg.solve函數來獲得閉合形式的解;(4)sparse_cg使用在scipy.sparse.linalg.cg中找到的共軛梯度求解器;(5)lsqr使用正則化最小二乘常數scipy.sparse.linalg.lsqr;(6)sag使用隨機平均梯度下降;
·tol:接受浮點型,用於選擇解的精度;
·random_state:默認為None,用於設置種子,接受整型。
2.2 LASSO()
這個類中有部分參數用法是與Ridge()類相同的,即alpha、fit_intercept 、normalize、copy_X、max_iter、random_state。除此之外,還有以下參數:·precompute:默認=False ,表示是否使用預計算的Gram矩陣(特徵間未減去均值的協方差陣)來加速計算;
·warm_start : 選擇為 True 時,重複使用上一次學習作為初始化,否則直接清除上次方案;
·positive : 選擇為 True 時,強制使係數為正;
·tol:優化容忍度,接受浮點型;
·selection :默認為'cyclic',若設置為'random',表示每次循環隨機更新參數,按照默認設置則會依次更新。
3 算法實例
這裡我們使用的數據仍然是上次介紹過的sklearn庫中自帶的波士頓房價數據。首先我們分別使用嶺回歸和LASSO回歸進行擬合,並輸出回歸係數和截距,程序如下:from sklearn.datasets import load_bostonfrom sklearn.model_selection import train_test_splitfrom sklearn.linear_model import Ridge, Lassoboston_sample = load_boston()x_train, x_test, y_train, y_test = train_test_split( boston_sample.data, boston_sample.target, test_size=0.25,random_state=123)ridge = Ridge()ridge.fit(x_train, y_train)print('嶺回歸係數:', ridge.coef_)print('嶺回歸截距:', ridge.intercept_)y_ridge_pre = ridge.predict(x_test)lasso = Lasso()lasso.fit(x_train, y_train)print('LASSO回歸係數:', lasso.coef_)print('LASSO回歸係數:', lasso.intercept_)y_lasso_pre = lasso.predict(x_test)輸出結果如下:
而後我們分別輸出兩個模型回歸的擬合優度和均方誤差,程序如下:
from sklearn.metrics import mean_squared_error,r2_scoreprint('嶺回歸的r2為:', r2_score(y_test, y_ridge_pre))print('嶺回歸的均方誤差為:', mean_squared_error(y_test,y_ridge_pre))print('LASSO回歸的r2為:', r2_score(y_test, y_lasso_pre))print('LASSO回歸的均方誤差為:', mean_squared_error(y_test,y_lasso_pre))結果如下:
我們將線性回歸、嶺回歸和LASSO的預測結果與真實值畫在一張圖上對比一下,程序如下:
import matplotlib.pyplot as pltplt.plot(y_test, label='True')plt.plot(y, label='linear')plt.plot(y_ridge_pre, label='Ridge')plt.plot(y_lasso_pre, label='LASSO')plt.legend()plt.show()結果如下圖:
可以看到在這個例子中用這三種回歸方法得到的結果差別不太大,當然,這裡由於篇幅所限,我們在嶺回歸和LASSO回歸中使用了默認的α值,其實還可以通過調參對模型進行優化。同時,我們也要注意,嶺回歸和LASSO都是使用特徵縮減的思想,因此得到的結果是有偏的,所以在選擇方法時要注意自己的需求。以上就是我們對線性回歸進一步的延伸,大家快去練習一下吧!
對我們的推文累計打賞超過1000元,我們即可給您開具發票,發票類別為「諮詢費」。用心做事,不負您的支持!微信公眾號「Stata and Python數據分析」分享實用的stata、python等軟體的數據處理知識,歡迎轉載、打賞。我們是由李春濤教授領導下的研究生及本科生組成的大數據處理和分析團隊。
此外,歡迎大家踴躍投稿,介紹一些關於stata和python的數據處理和分析技巧。投稿郵箱:statatraining@163.com投稿要求:
1)必須原創,禁止抄襲;
2)必須準確,詳細,有例子,有截圖;
注意事項:
1)所有投稿都會經過本公眾號運營團隊成員的審核,審核通過才可錄用,一經錄用,會在該推文裡為作者署名,並有賞金分成。
2)郵件請註明投稿,郵件名稱為「投稿+推文名稱」。
3)應廣大讀者要求,現開通有償問答服務,如果大家遇到有關數據處理、分析等問題,可以在公眾號中提出,只需支付少量賞金,我們會在後期的推文裡給予解答。