文章目錄
相關文章:
監督學習 | 線性迴歸 之多元線性迴歸原理及Sklearn實現
監督學習 | 非線性迴歸 之多項式迴歸原理及Sklearn實現
監督學習 | 線性分類 之Logistic迴歸原理及Sklearn實現
1. 正則線性模型
在介紹正則線性模型(Regularized Linear Models)前,我們先來看一下一個例子,假設對於以下數據,我們分別使用多元線性迴歸和多項式迴歸進行擬合分類如下:
可以看到此時線性模型的錯誤分類點數爲2,而多項式迴歸模型的誤差爲0,因此此時計算機將會選擇第二個模型。但是這個模型有一個缺點,那就是過擬合了,但如何讓計算機避免過擬合呢,一個常見的方法就是對模型正則化,它擁有的自由度越低,就越不容易過度擬合。比如,將多項式模型正則化的簡單方法就是降低多項式的階數。
對線性模型來說,正則化通常通過約束模型的權重來實現。如剛纔的例子,如果我們爲模型的成本函數添加一個模型複雜度的話,就可以在挑選模型的時候考慮到模型的複雜度。
按照對模型複雜度的懲罰不同,我們有三種方法:嶺迴歸、套索迴歸和彈性網絡,分別對應三種正則化策略:L2 正則化、L1 正則化和 L1&L2 正則化。
p-範數:如果 那麼向量 x 的 p-範數就是: ,用得最多的還是 範數:
範數: ,即絕對值之和
範數: ,即通常意義上的模
1.1 Ridge Regression(L2)
嶺迴歸
(Ridge Regression,也叫作吉洪諾夫正則化)是線性迴歸的正則化版:在成本函數中添加一個等於 的正則項。這使得學習中的算法不僅需要擬合數據,同時還要讓模型權重保持最小。
嶺迴歸模型成本函數:
注意,正則項只能在訓練的時候添加到成本函數中,一旦訓練完成,就需要使用未經正則化的性能指標來評估模型性能。
超參數 控制的是對模型進行正則化的程度,如果 ,則嶺迴歸就是線性模型。如果 非常大,那麼所有的權重都非常接近於零,結果是一條穿過數據平均值的水平線。
注意,這裏偏置項 沒有正則化。如果我們將 定義爲特徵權重的向量( 到 ),那麼正則項即正與 ,其中 爲權重向量的 範數。而對於梯度下降,只需要在 梯度向量上添加 即可。
在執行嶺迴歸之前,必須對數據進行縮放(例如使用 StandardScaler),因爲它對輸入特徵的大小非常敏感。大多數正則化模型都是如此。
與線性迴歸一樣,我們也可以在計算閉式方程或者執行梯度下降時,執行嶺迴歸。
閉式解的嶺迴歸:
其中 是一個 的單位矩陣,除了左上單元格爲0,其他與偏置項對應。
下面是使用不同 值對某個線性數據進行訓練的幾種嶺迴歸模型,左邊直接對線性模型使用嶺迴歸(即對多元線性模型的成本函數添加模型複雜度),導致預測是線性的。而右邊,首先使用 PolynomialFeatures(degree=10) 對數據進行擴展(多項式迴歸),然後用 StandardScaler() 進行縮放,最後將嶺迴歸模型用於結果特徵:
使得預測更加平坦,這降低了模型的方差,但是也提升了偏差。
代碼如下:
from sklearn.linear_model import Ridge, LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
import matplotlib.pyplot as plt
np.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 1
plt.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 實現
from sklearn.linear_model import Ridge
ridge_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 Ridge
np.random.seed(42)
m = 20
X = 3 * np.random.rand(m, 1)
y = 1 + 0.5 * X + np.random.randn(m, 1) / 1.5
ridge_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]]))
與原迴歸模型 很接近。
1.1.2 Ridge + SDG
利用隨機梯度下降來求解嶺迴歸。
1.1.2.1 Sklearn 實現
from sklearn.linear_model import SGDRegressor
ridge_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 迴歸
,或套索迴歸)。與嶺迴歸一樣,它也是像成本函數添加一個正則項,但是它增加的是權重向量的 範數,而不是 範數的平方的一半。
Lasso 迴歸成本函數:
圖 3 顯示內容與圖 2 相同,但是嶺迴歸模型換成了 Lasso 迴歸模型,同時 值較小。
Lasso 迴歸的一個重要特點是它傾向於完全消除掉最不重要特徵的權重(也就是將它們設置爲零)。例如,在圖 3 中右圖中的虛線()看起來像是二次的,快要接近於線性;因爲所有高階多項式的特徵權重的等於零。換句話說,Lasso 會回會自動執行特徵選擇並輸出一個係數模型(即只有很少的特徵有非零權重)。
代碼如下:
from sklearn.linear_model import Lasso
plt.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 實現
from sklearn.linear_model import Lasso
lasso_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 迴歸,當 ,Lasso 成本函數是不可微的。但是,當任意 時,可以使用次梯度向量
作爲替代,依舊可以讓梯度下降正常運轉。
迴歸次梯度向量:
1.2.2.1 Sklearn 實現
from sklearn.linear_model import SGDRegressor
lasso_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 迴歸的正則項的混合混合比例通過 (L1_ratio)來控制。當 時,彈性網絡即等同於嶺迴歸,而當 時,即相當於 Lasso 迴歸。
彈性網絡成本函數:
1.3.1 Sklearn 實現
sklearn.linear_model.ElasticNet:
from sklearn.linear_model import ElasticNet
elastic_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.