监督学习 | 线性回归 之正则线性模型原理及Sklearn实现
文章目錄
- 1. 正則線性模型
- 1.1 Ridge Regression(L2)
- 1.1.1 Sklearn 實現
- 1.1.2 Ridge + SDG
- 1.1.2.1 Sklearn 實現
- 1.2 Lasso Regression(L1)
- 1.2.1 Sklearn 實現
- 1.2.2 Lasso + SGD
- 1.2.2.1 Sklearn 實現
- 1.3 Elastic Net(L1&L2)
- 1.3.1 Sklearn 實現
- 1.4 正則線性模型選擇
- 參考資料
相關文章:
機器學習 | 目錄
機器學習 | 回歸評估指標
機器學習 | 梯度下降原理及Python實現
監督學習 | 線性回歸 之多元線性回歸原理及Sklearn實現
監督學習 | 非線性回歸 之多項式回歸原理及Sklearn實現
監督學習 | 線性分類 之Logistic回歸原理及Sklearn實現
1. 正則線性模型
在介紹正則線性模型(Regularized Linear Models)前,我們先來看一下一個例子,假設對于以下數據,我們分別使用多元線性回歸和多項式回歸進行擬合分類如下:
圖1 不同模型對數據的擬合可以看到此時線性模型的錯誤分類點數為2,而多項式回歸模型的誤差為0,因此此時計算機將會選擇第二個模型。但是這個模型有一個缺點,那就是過擬合了,但如何讓計算機避免過擬合呢,一個常見的方法就是對模型正則化,它擁有的自由度越低,就越不容易過度擬合。比如,將多項式模型正則化的簡單方法就是降低多項式的階數。
對線性模型來說,正則化通常通過約束模型的權重來實現。如剛才的例子,如果我們為模型的成本函數添加一個模型復雜度的話,就可以在挑選模型的時候考慮到模型的復雜度。
按照對模型復雜度的懲罰不同,我們有三種方法:嶺回歸、套索回歸和彈性網絡,分別對應三種正則化策略:L2 正則化、L1 正則化和 L1&L2 正則化。
p-范數:如果 X=[x1,x2,..,xn]X=[x_1,x_2,..,x_n]X=[x1?,x2?,..,xn?] 那么向量 x 的 p-范數就是:∣∣x∣∣p=(∣x1∣p+∣x2∣p+?+∣xn∣p)1p||x||_p=(|x_1|^p+|x_2|^p+\cdots+|x_n|^p)^{\frac{1}{p}}∣∣x∣∣p?=(∣x1?∣p+∣x2?∣p+?+∣xn?∣p)p1? ,用得最多的還是 L1,L2L_1,L_2L1?,L2? 范數:
L1L_1L1? 范數:∣∣x∣∣1=(∣x1∣+∣x2∣+?+∣xn∣)||x||_1=(|x_1|+|x_2|+\cdots+|x_n|)∣∣x∣∣1?=(∣x1?∣+∣x2?∣+?+∣xn?∣) ,即絕對值之和
L2L_2L2? 范數:∣∣x∣∣2=(∣x1∣2+∣x2∣2+?+∣xn∣2)12||x||_2=(|x_1|^2+|x_2|^2+\cdots+|x_n|^2)^{\frac{1}{2}}∣∣x∣∣2?=(∣x1?∣2+∣x2?∣2+?+∣xn?∣2)21? ,即通常意義上的模
1.1 Ridge Regression(L2)
嶺回歸(Ridge Regression,也叫作吉洪諾夫正則化)是線性回歸的正則化版:在成本函數中添加一個等于 α∑i=1nθi2\alpha\sum_{i=1}^n\theta_i^2α∑i=1n?θi2? 的正則項。這使得學習中的算法不僅需要擬合數據,同時還要讓模型權重保持最小。
嶺回歸模型成本函數:
(1)J(θ)=MSE(θ)+α12∑i=1nθi2J(\theta)=MSE(\theta)+\alpha\frac{1}{2}\sum_{i=1}^n\theta_i^2 \tag{1}J(θ)=MSE(θ)+α21?i=1∑n?θi2?(1)
注意,正則項只能在訓練的時候添加到成本函數中,一旦訓練完成,就需要使用未經正則化的性能指標來評估模型性能。
超參數 α\alphaα 控制的是對模型進行正則化的程度,如果 α=0\alpha=0α=0 ,則嶺回歸就是線性模型。如果 α\alphaα 非常大,那么所有的權重都非常接近于零,結果是一條穿過數據平均值的水平線。
注意,這里偏置項 θ0\theta_0θ0? 沒有正則化。如果我們將 www 定義為特征權重的向量(θ1\theta_1θ1? 到 θn\theta_nθn?),那么正則項即正與 12(∣∣w∣∣2)2\frac{1}{2}(||w||_2)^221?(∣∣w∣∣2?)2,其中 ∣∣w∣∣2||w||_2∣∣w∣∣2? 為權重向量的 L2L_2L2? 范數。而對于梯度下降,只需要在 MSEMSEMSE 梯度向量上添加 αw\alpha wαw 即可。
在執行嶺回歸之前,必須對數據進行縮放(例如使用 StandardScaler),因為它對輸入特征的大小非常敏感。大多數正則化模型都是如此。
與線性回歸一樣,我們也可以在計算閉式方程或者執行梯度下降時,執行嶺回歸。
閉式解的嶺回歸:
(2)θ^=(XT?X+αA)?1?XT?y\hat{\theta}=(X^T\cdot X+\alpha A)^{-1}\cdot X^T \cdot y \tag{2}θ^=(XT?X+αA)?1?XT?y(2)
其中 AAA 是一個 n×nn \times nn×n 的單位矩陣,除了左上單元格為0,其他與偏置項對應。
下面是使用不同 α\alphaα 值對某個線性數據進行訓練的幾種嶺回歸模型,左邊直接對線性模型使用嶺回歸(即對多元線性模型的成本函數添加模型復雜度),導致預測是線性的。而右邊,首先使用 PolynomialFeatures(degree=10) 對數據進行擴展(多項式回歸),然后用 StandardScaler() 進行縮放,最后將嶺回歸模型用于結果特征:
圖2 不同 alpha 下的 嶺回歸 與 多項式嶺回歸α\alphaα 使得預測更加平坦,這降低了模型的方差,但是也提升了偏差。
代碼如下:
from sklearn.linear_model import Ridge, LinearRegression from sklearn.pipeline import Pipeline from sklearn.preprocessing import PolynomialFeatures, StandardScaler import matplotlib.pyplot as pltnp.random.seed(42) m = 20 X = 3 * np.random.rand(m, 1) y = 1 + 0.5 * X + np.random.randn(m, 1) / 1.5 X_new = np.linspace(0, 3, 100).reshape(100, 1)def plot_model(model_class, polynomial, alphas, **model_kargs):for alpha, style in zip(alphas, ("b-", "g--", "r:")):# 嶺回歸如果alpha為0,就變成了線性回歸model = model_class(alpha, **model_kargs) if alpha > 0 else LinearRegression() # 多項式嶺回歸if polynomial:model = Pipeline([("poly_features", PolynomialFeatures(degree=10, include_bias=False)),("std_scaler", StandardScaler()),("regul_reg", model),])model.fit(X, y)y_new_regul = model.predict(X_new)lw = 2 if alpha > 0 else 1plt.plot(X_new, y_new_regul, style, linewidth=lw, label=r"$\alpha = {}$".format(alpha))plt.plot(X, y, "b.", linewidth=3)plt.legend(loc="upper left", fontsize=15)plt.xlabel("$x_1$", fontsize=18)plt.axis([0, 3, 0, 4])plt.figure(figsize=(8,4)) plt.subplot(121) plot_model(Ridge, polynomial=False, alphas=(0, 10, 100), random_state=42) plt.ylabel("$y$", rotation=0, fontsize=18) plt.subplot(122) plot_model(Ridge, polynomial=True, alphas=(0, 10**-5, 1), random_state=42)plt.show()1.1.1 Sklearn 實現
sklearn.linear_model.Ridge:
from sklearn.linear_model import Ridgeridge_reg = Ridge(alpha=1.0, fit_intercept=True, normalize=False, copy_X=True, max_iter=None, tol=0.001, solver='auto', random_state=None)ridge_reg.fit(X, y) ridge_reg.predict([[X_pred]]) from sklearn.linear_model import Ridgenp.random.seed(42) m = 20 X = 3 * np.random.rand(m, 1) y = 1 + 0.5 * X + np.random.randn(m, 1) / 1.5ridge_reg = Ridge(alpha=1, solver="cholesky", random_state=42) ridge_reg.fit(X, y) ridge_reg.predict([[1.5]]) array([[1.55071465]]) ridge_reg.intercept_, ridge_reg.coef_ (array([1.00650911]), array([[0.36280369]]))與原回歸模型 y=1+0.5×X+εy = 1 + 0.5 \times X + \varepsilony=1+0.5×X+ε 很接近。
1.1.2 Ridge + SDG
利用隨機梯度下降來求解嶺回歸。
1.1.2.1 Sklearn 實現
from sklearn.linear_model import SGDRegressorridge_sgd_reg = SGDRegressor(max_iter=50, tol=-np.infty, penalty="l2", random_state=42) ridge_sgd_reg.fit(X, y.ravel()) ridge_sgd_reg.predict([[1.5]]) array([1.49905184]) ridge_sgd_reg.intercept_, ridge_sgd_reg.coef_ (array([0.63725132]), array([0.57453367]))1.2 Lasso Regression(L1)
線性回歸的另一種正則化,叫作最小絕對收縮和選擇算子回歸(Least Absolute Shrinkage and Selection Operator Regression,簡稱Lasso 回歸,或套索回歸)。與嶺回歸一樣,它也是像成本函數添加一個正則項,但是它增加的是權重向量的 L1L_1L1? 范數,而不是 L2L_2L2? 范數的平方的一半。
Lasso 回歸成本函數:
(3)J(θ)=MSE(θ)+α∑i=1n∣θi∣J(\theta)=MSE(\theta)+\alpha\sum_{i=1}^n|\theta_i| \tag{3}J(θ)=MSE(θ)+αi=1∑n?∣θi?∣(3)
圖 3 顯示內容與圖 2 相同,但是嶺回歸模型換成了 Lasso 回歸模型,同時 α\alphaα 值較小。
Lasso 回歸的一個重要特點是它傾向于完全消除掉最不重要特征的權重(也就是將它們設置為零)。例如,在圖 3 中右圖中的虛線(α=10?7\alpha=10^{-7}α=10?7)看起來像是二次的,快要接近于線性;因為所有高階多項式的特征權重的等于零。換句話說,Lasso 會回會自動執行特征選擇并輸出一個系數模型(即只有很少的特征有非零權重)。
圖3 不同 alpha 下的 Lasso 回歸 與 多項式 Lasso 回歸代碼如下:
from sklearn.linear_model import Lassoplt.figure(figsize=(8,4)) plt.subplot(121) plot_model(Lasso, polynomial=False, alphas=(0, 0.1, 1), random_state=42) plt.ylabel("$y$", rotation=0, fontsize=18) plt.subplot(122) plot_model(Lasso, polynomial=True, alphas=(0, 10**-7, 1), tol=1, random_state=42)plt.show()[外鏈圖片轉存失敗(img-rtHntb2V-1566830619833)(output_18_0.png)]
1.2.1 Sklearn 實現
sklearn.linear_model.Lasso:
from sklearn.linear_model import Lassolasso_reg = Lasso(alpha=1.0, fit_intercept=True, normalize=False, precompute=False, copy_X=True, max_iter=1000, tol=0.0001, warm_start=False, positive=False, random_state=None, selection='cyclic') lasso_reg.fit(X, y) lasso_reg.predict([[X_pred]]) from sklearn.linear_model import Lasso lasso_reg = Lasso(alpha=0.1) lasso_reg.fit(X, y) lasso_reg.predict([[1.5]]) array([1.53788174]) lasso_reg.intercept_, lasso_reg.coef_ (array([1.14537356]), array([0.26167212]))1.2.2 Lasso + SGD
利用隨機梯度下降來求解 Lasso 回歸,當 θi=0(i=1,2,? ,n)\theta_i=0(i=1,2,\cdots,n)θi?=0(i=1,2,?,n) ,Lasso 成本函數是不可微的。但是,當任意 θi=0\theta_i=0θi?=0 時,可以使用次梯度向量 ggg 作為替代,依舊可以讓梯度下降正常運轉。
LassoLassoLasso 回歸次梯度向量:
(4)g(θ,J)=?θMSE?(θ)+α(sign?(θ1)sign?(θ2)?sign?(θn))當sign(θ1)={?1(θi<0)0(θi=0)+1(θi>0)g(\theta, J)=\nabla_{\theta} \operatorname{MSE}(\theta)+\alpha\left(\begin{array}{c}{\operatorname{sign}\left(\theta_{1}\right)} \\ {\operatorname{sign}\left(\theta_{2}\right)} \\ {\vdots} \\ {\operatorname{sign}\left(\theta_{n}\right)}\end{array}\right) 當sign(\theta_1)=\left\{ \begin{aligned} -1 \quad (\theta_i<0) \\ 0 \quad (\theta_i=0) \\ +1 \quad (\theta_i>0) \\ \end{aligned} \right.\tag{4} g(θ,J)=?θ?MSE(θ)+α??????sign(θ1?)sign(θ2?)?sign(θn?)???????當sign(θ1?)=???????1(θi?<0)0(θi?=0)+1(θi?>0)?(4)
1.2.2.1 Sklearn 實現
from sklearn.linear_model import SGDRegressorlasso_sgd_reg = SGDRegressor(max_iter=50, tol=-np.infty, penalty="l1", random_state=42) lasso_sgd_reg.fit(X, y.ravel()) lasso_sgd_reg.predict([[1.5]]) array([1.49903849]) lasso_sgd_reg.intercept_, lasso_sgd_reg.coef_ (array([0.63727982]), array([0.57450578]))1.3 Elastic Net(L1&L2)
彈性網絡是嶺回歸與 Lasso 回歸之間的中間地帶。其正則項就是嶺回歸和 Lasso 回歸的正則項的混合混合比例通過 rrr (L1_ratio)來控制。當 r=0r=0r=0 時,彈性網絡即等同于嶺回歸,而當 r=1r=1r=1 時,即相當于 Lasso 回歸。
彈性網絡成本函數:
(5)J(θ)=MSE(θ)+rα∑i=1n∣θi∣+1?r2α∑i=1nθinJ(\theta)=MSE(\theta)+r\alpha \sum_{i=1}^n|\theta_i|+\frac{1-r}{2}\alpha\sum_{i=1}^n \theta_i^n \tag{5}J(θ)=MSE(θ)+rαi=1∑n?∣θi?∣+21?r?αi=1∑n?θin?(5)
1.3.1 Sklearn 實現
sklearn.linear_model.ElasticNet:
from sklearn.linear_model import ElasticNetelastic_net = ElasticNet(alpha=1.0, l1_ratio=0.5, fit_intercept=True, normalize=False, precompute=False, max_iter=1000, copy_X=True, tol=0.0001, warm_start=False, positive=False, random_state=None, selection='cyclic')[source]elastic_net.fit(X, y) elastic_net.predict([[X_pred]]) from sklearn.linear_model import ElasticNet elastic_net = ElasticNet(alpha=0.1, l1_ratio=0.5, random_state=42) elastic_net.fit(X, y) elastic_net.predict([[1.5]]) array([1.54333232]) elastic_net.intercept_, elastic_net.coef_ (array([1.08639303]), array([0.30462619]))1.4 正則線性模型選擇
應該如何選擇線性、嶺回歸、Lasso 回歸和彈性網絡呢?通常來說,有正則化——哪怕是很小,總是比沒有更可取一些。所以大多數情況下,應該避免使用純線性回歸。
嶺回歸是個不錯的默認選擇,但是如果覺得實際用到的特征只有少數幾個,那就應該更傾向于 Lasso 回歸或是彈性網絡,因為它們會將無用特征的權重降為零。
一般而言,彈性網絡優于 Lasso 回歸,因為當特征數量超過訓練實例數量,又或者是幾個特征強相關時,Lasso 回歸的表現可能非常不穩定。[1]
參考資料
[1] Aurelien Geron, 王靜源, 賈瑋, 邊蕤, 邱俊濤. 機器學習實戰:基于 Scikit-Learn 和 TensorFlow[M]. 北京: 機械工業出版社, 2018: 121-127.
總結
以上是生活随笔為你收集整理的监督学习 | 线性回归 之正则线性模型原理及Sklearn实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高薪招聘生物信息工程师-中国科学院深圳先
- 下一篇: 监督学习 | 决策树之Sklearn实现