1. 線性回歸
線性回歸又名普通二成最小法(ordinary least squares, OLS),是回歸問題最簡單也是最經典的線性方法。線性回歸尋找參數w和b,使得對訓練集的預測值與真實的回歸目標值y之間的均方誤差最小。線性回歸沒有參數,這是一個優點,但也因此無法控制模型的復雜度。
線性回歸的用法與近鄰算法相似,如下:
import numpy as np
import pandas as pd
import mglearn
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
# 線性回歸在sklearn的linear_model模塊的LinearRegression類中實現
from sklearn.linear_model import LinearRegression
# 生成數據
X, y = mglearn.datasets.make_wave(n_samples=60)
# 拆分數據集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
# 實例化LinearRegression對象并用fit函數訓練集數據進行模型擬合
lr = LinearRegression().fit(X_train, y_train)
# 調用LinearRegression對象的predict函數對測試集進行預測
print("Test set predictions:\n{}".format(lr.predict(X_test)))
# 調用LinearRegression對象的score函數對模型性能進行評估
print("Test set acurracy:{:.2f}".format(lr.score(X_test, y_test)))
print("Train set acurracy:{:.2f}".format(lr.score(X_train, y_train)))
Test set predictions:
[-0.3283204 -0.84483835 -0.49358667 0.35230624 -0.71167167 0.19957573
1.02910669 0.07859229 0.75390167 -0.75032857 -0.47681266 1.07802761
-0.8104986 0.2013684 1.00692209]
Test set acurracy:0.66
Train set acurracy:0.67
訓練集和測試集上的分數非常相近,且不是太好,說明可能存在欠擬合。
斜率參數w也叫權重或系數被保存在LinearRegression對象的coef_屬性中,偏移或截距(b)被保存在intercept_屬性中:
print("lr.coef_:{}".format(lr.coef_))
print("lr.intercept_:{}".format(lr.intercept_))
lr.coef_:[0.39390555]
lr.intercept_:-0.031804343026759746
注意使用的wave數據是一維數據集,模型的性能不是很好,對于更高維的數據集,線性模型將變動更加強大。
下面使用更復雜的數據集boston房價,數據集有506個樣本和105特征,驗證線性回歸在高維數據集上的表現:
# 加載數據集
X, y = mglearn.datasets.load_extended_boston()
# 拆分數據集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
# 實例化LinearRegression對象并用fit函數訓練集數據進行模型擬合
lr = LinearRegression().fit(X_train, y_train)
# 調用LinearRegression對象的score函數對模型性能進行評估
print("Train set acurracy:{:.2f}".format(lr.score(X_train, y_train)))
print("Test set acurracy:{:.2f}".format(lr.score(X_test, y_test)))
Train set acurracy:0.95
Test set acurracy:0.61
線性回歸在高維數據集上的表象明顯好于一維數據集,但在訓練集和測試集上的得分差異較大,是過擬合的明顯標志。
2. 嶺回歸
嶺回歸也是一種用于回歸的線性模型。在嶺回歸模型中,對系數(w)的選擇不僅要在訓練集上得到較好的效果,而且還要擬合附加約束,使得w盡量小,及w的所有元素都要接近于0。這種約束即是正則化。正則化是指對模型進行顯示約束,以避免過擬合。嶺回歸用到的這種被稱為L2正則化。
嶺回歸在sklearn的linear_model的Ridge類中實現。下面是嶺回歸在boston房價數據集上的效果。
import numpy as np
import pandas as pd
import mglearn
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
# 線性回歸在sklearn的linear_model模塊的Ridge類中實現
from sklearn.linear_model import Ridge
# 加載數據
X, y = mglearn.datasets.load_extended_boston()
# 拆分數據集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
# 實例化Ridge對象并用fit函數訓練集數據進行模型擬合
rg = Ridge().fit(X_train, y_train)
# 調用Ridge對象的score函數對模型性能進行評估
print("Train set acurracy:{:.2f}".format(rg.score(X_train, y_train)))
print("Test set acurracy:{:.2f}".format(rg .score(X_test, y_test)))
Training set scroe:0.89
Test set score:0.75
Ridge在訓練集上的得分低于LinearRegression,但在測試集上的得分要高。
Ridge模型在模型的簡單性(w接近0)與訓練集性能之間做權衡。模型的簡單性和訓練集性能的權衡可通過設置參數alpha來指定。alpha的最佳值取決于具體的數據集。增大alpha的值會使得w更加趨向0,即模型更簡單,從而降低訓練集性能,但可能提高泛化性能。**
rg10 = Ridge(alpha=10).fit(X_train, y_train)
print("Training set scroe:{:.2f}".format(rg10.score(X_train, y_train)))
print("Test set score:{:.2f}".format(rg10.score(X_test, y_test)))
Training set scroe:0.79
Test set score:0.64
減小alpha可以讓w收到的限制更小,對于非常小的alpha,w幾乎沒有收到限制,會得到一個與LinearRegression類似的模型。
rg01 = Ridge(alpha=0.1).fit(X_train, y_train)
print("Training set scroe:{:.2f}".format(rg01.score(X_train, y_train)))
print("Test set score:{:.2f}".format(rg01.score(X_test, y_test)))
Training set scroe:0.93
Test set score:0.77
下面查看不同alpha取值對模型coef_屬性的影響,觀察alpha參數是如何影響模型。
plt.plot(rg.coef_, 's', label="Ridge alpha=1")
plt.plot(rg10.coef_, '^', label="Ridge alpha=10")
plt.plot(rg01.coef_, 'v', label="Ridge alpha=0.1")
plt.plot(lr.coef_, 'o', label="LinearRegression")
plt.xlabel("Cofficient index")
plt.ylabel("Cofficient magnitude")
plt.hlines(0, 0, len(lr.coef_))
plt.ylim(-25, 25)
plt.legend()
從上圖中可以看出alpha越大,w的范圍越集中且趨于0。
另外一種理解正則化的影響,就是固定alpha的值,但是改變訓練數據量。
mglearn.plots.plot_ridge_n_samples()
無論是嶺回歸還是線性回歸,訓練分數都要高于測試分數。由于嶺回歸是正則化的,因此它的訓練分數低于線性回歸,但是測試分數要高于線性回歸。尤其是較小的數據集時,從上圖可看出數據點少于400時,線性回歸學習不到任何內容。隨著模型可用數據的增多,兩個模型的性能都在提升,最終線性回歸的性能會追上嶺回歸。即在有足夠的的訓練數據的情況下,正則化變得不那么重要。
3. lasso
lasso也是一種正則化的線性回歸模型,與Ridge的不同之處在于它使用的是L1正則化,結果是使某些系數剛好為0。這說明某些特征被模型完全忽略,可看作是一種自動化的特征選擇。
import numpy as np
import pandas as pd
import mglearn
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
# lasso 在sklearn的linear_model模塊的Lasso類中實現
from sklearn.linear_model import Lasso
# 加載boston房價數據
X, y = mglearn.datasets.load_extended_boston()
# 拆分數據集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
# 實例化Lasso對象并用測試集數據擬合模型
la = Lasso().fit(X_train, y_train)
# 調用Lasso對象的score函數進行模型評估
print("Training set score:{:.2f}".format(la.score(X_train, y_train)))
print("Test set score:{:.2f}".format(la.score(X_test, y_test)))
# 統計模型使用的特征數,及Lasso對象coef_屬性不為0的
print("Number of features used:{}".format(np.sum(la.coef_!=0)))
Training set score:0.29
Test set score:0.21
Number of features used:4
如上lasso在訓練集和測試集上的得分都很低,標識存在欠擬合,模型只用到了105個特征中的4個。與Ridge相似,lasso也有alpha參數可以控制系數趨向0的強度。上面的代碼中alpha參數使用默認值1.0。下面嘗試減小alpha,降低欠擬合,從而得到一個更復雜的模型。減小alpha的同時需要增大max_iter(運行迭代的最大次數)的值:
# 實例化Lasso對象并用測試集數據擬合模型
la001 = Lasso(alpha=0.01, max_iter=10000).fit(X_train, y_train)
# 調用Lasso對象的score函數進行模型評估
print("Training set score:{:.2f}".format(la001.score(X_train, y_train)))
print("Test set score:{:.2f}".format(la001.score(X_test, y_test)))
# 統計模型使用的特征數,及Lasso對象coef_屬性不為0的
print("Number of features used:{}".format(np.sum(la001.coef_!=0)))
Training set score:0.90
Test set score:0.77
Number of features used:33
alpha值變小后,lasso在訓練集和測試集上的得分都明顯提高。但是如果把alpha設置太小,就會消化正則化的效果,并出現過擬合,得到于LinearRegression類似的結果:
# 實例化Lasso對象并用測試集數據擬合模型
la00001 = Lasso(alpha=0.0001, max_iter=100000).fit(X_train, y_train)
# 調用Lasso對象的score函數進行模型評估
print("Training set score:{:.2f}".format(la00001.score(X_train, y_train)))
print("Test set score:{:.2f}".format(la00001.score(X_test, y_test)))
# 統計模型使用的特征數,及Lasso對象coef_屬性不為0的
print("Number of features used:{}".format(np.sum(la00001.coef_!=0)))
Training set score:0.95
Test set score:0.64
Number of features used:94
from sklearn.linear_model import Ridge
rg01 = Ridge(alpha = 0.1).fit(X_train, y_train)
print("Training set score:{:.2f}".format(rg01.score(X_train, y_train)))
print("Test set score:{:.2f}".format(rg01.score(X_test, y_test)))
Training set score:0.93
Test set score:0.77
下面作圖觀察不同alpha值對模型系數的影響情況:
plt.plot(la.coef_, 's', label="lasso alpha=1")
plt.plot(la001.coef_, '^', label="lasso alpha=0.01")
plt.plot(la00001.coef_, 'v', label="lasso alpha=0.0001")
plt.plot(rg01.coef_, 'o', label="ridge alpha=0.1")
plt.legend(ncol=2, loc=(0, 1.05))
plt.ylim(-25, 25)
plt.xlabel("Coefficient index")
plt.ylabel("Coefficient magnitude")
lasso alpha=1 系數基本都為0,只有幾個不為0且范圍較小
lasso alpha=0.01系數大部分都為0,范圍增大
lasso alpha=0.0001系數很小一部分為0,范圍更大
ridge alpha=0.1所有系數均不為0