正如咱們在第一和第二章看到的那樣,下降模型的過擬合的好方法是正則化這個模型(即限制它):模型有越少的自由度,就越難以擬合數據。例如,正則化一個多項式模型,一個簡單的方法就是減小多項式的階數。git
對於一個線性模型,正則化的典型實現就是約束模型中參數的權重。 接下來咱們將介紹三種不一樣約束權重的方法:Ridge迴歸,Lasso迴歸和Elastic Net。算法
嶺迴歸(也稱爲Tikhonov正則化)是線性迴歸的正則化版:注意到這個正則項只有在訓練過程當中纔會被加到代價函數。當獲得完成訓練的模型後,咱們應該使用沒有正則化的測量方法去評價模型的表現網絡
通常狀況下,訓練過程使用的代價函數和測試過程使用的評價函數不同樣的。除了正則化,還有一個不一樣:訓練時的代價函數應該在優化過程當中易於求導,而在測試過程當中,評價函數更應該接近最後的客觀表現。一個好的例子:在分類訓練中咱們使用對數損失(立刻咱們會討論它)做爲代價函數,可是咱們卻使用精確率/召回率來做爲它的評價函數。
嶺迴歸(L2正則)代價函數:
$$J(\theta)=MSE(\theta)+\alpha\frac{1}{2}\sum\limits_{i=1}^n\theta_i^2$$函數
超參數$\alpha$ 決定了你想正則化這個模型的強度,正則化強度越大,模型會越簡單。若是$\alpha$=0 那此時的嶺迴歸便變爲了線性迴歸。若是alpha很是的大,全部的權重最後都接近與零,最後結果將是一條穿過數據平均值的水平直線學習
(公式4-6:代價函數的梯度向量,加上$\alpha w$是$1/2*\alpha*w^2$求偏導的結果 )
測試
在使用嶺迴歸前,對 數據進行放縮(可使用StandardScaler)是很是重要的,算法對於輸入特徵的數值尺度(scale)很是敏感。 大多數的正則化模型都是這樣的。
下圖展現了在相同線性數據上使用不一樣$\alpha$ 值的嶺迴歸模型最後的表現。左圖中,使用簡單的嶺迴歸模型,最後獲得了線性的預測。右圖中的數據首先使用10 階的PolynomialFearuresj進行擴展,而後使用StandardScaler進行縮放,最後將嶺模型應用在處理事後的特徵上。這就是帶有嶺正則項的多項式迴歸。注意當$\alpha$ 增大的時候,致使預測曲線變得扁平(即少了極端值,多了通常值),這樣減小了模型的方差,去增長了模型的誤差優化
對線性迴歸來講,對於嶺迴歸,咱們可使用封閉方程去計算,也可使用梯度降低去處理。它們的缺點和優勢是同樣的。公式4-9表示封閉方程的解(矩陣$\mathbf{A}$ 是一個除了左上角有一個0的$n \times n$的單位矩,這個0表明誤差項。譯者注:誤差$\theta_0$ 不被正則化的)。編碼
嶺迴歸的封閉方程的解(公式4-6:代價函數的梯度向量,加上$\alpha w$是$1/2*\alpha*w^2$求偏導的結果 ):
$$\hat{\theta} =({\mathbf{X}}^T\cdot\mathbf{X}+\alpha\mathbf{A})^{-1}\cdot{\mathbf{X}}^T\cdot\mathbf{y}$$spa
下面是如何使用Scikit-Learn來進行封閉方程的求解(使用Cholesky法進行矩陣分解對上面公式行變形)code
>>> from sklearn.linear_model import Ridge >>> ridge_reg = Ridge(alpha=1, solver="cholesky") >>> ridge_reg.fit(X, y) >>> ridge_reg.predict([[1.5]]) array([[ 1.55071465]]
使用隨機梯度法進行求解:
>>> sgd_reg = SGDRegressor(penalty="l2") >>> sgd_reg.fit(X, y.ravel()) >>> sgd_reg.predict([[1.5]]) array([[ 1.13500145]])
penalty參數指的是正則項的懲罰類型。指定「l2」代表你要在代價函數上添加一項:權重向量$\ell_2$ 範數平方的一半,這就是簡單的嶺迴歸。
Lasso迴歸(也稱Least Absolute Shrinkage,或者Selection Operator Regression)是另外一種正則化版的線性迴歸:就像嶺迴歸那樣,它也在代價函數上添加了一個正則化項,可是它使用權重向量的$\ell_1$ 範數而不是權重向量$\ell_2$ 範數平方的一半。
Lasso迴歸的代價函數:
$$J(\theta)=MSE(\theta)+\alpha\sum\limits_{i=1}^n\left|\theta_i \right|$$
下圖展現了和以前相同的事情,僅僅是用Lasso模型代替了Ridge模型,同時調小了$\alpha$ 的值
Lasso迴歸的一個重要特徵是它傾向於徹底消除最不重要的特徵的權重(即將它們設置爲零)。例如,右圖中的虛線所示($\alpha=10^{-7}$ ),曲線看起來像一條二次曲線,並且幾乎是線性的,這是由於全部的高階多項特徵都被設置爲零
下面是一個使用Lasso類的小Scikit-Learn示例。你也可使用SGDRegressor(penalty="l1")來代替它
>>> 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]
彈性網絡介於Ridge迴歸和Lasso迴歸之間。它的正則項是Ridge迴歸和Lasso迴歸正則項的簡單混合,同時你能夠控制它們的混合率r,當r=0時,彈性網絡就是Ridge迴歸,當r=1時,其就是Lasso迴歸
彈性網絡代價函數:
$$J(\theta)=MSE(\theta)+r\alpha\sum\limits_{i=1}^n\left|\theta_i \right|+\frac{1-r}{2}\alpha\sum\limits_{i=1}^n\theta_i^2$$
那麼咱們該如何選擇線性迴歸,嶺迴歸,Lasso迴歸,彈性網絡呢?通常來講有一點正則項的表現更好,所以一般你應該避免使用簡單的線性迴歸。嶺迴歸是一個很好的首選項,可是若是你的特徵僅有少數是真正有用的,你應該選擇Lasso和彈性網絡。就像咱們討論的那樣,它兩可以將無用特徵的權重降爲零。通常來講,彈性網絡的表現要比Lasso好,由於當特徵數量比樣例的數量大的時候,或者特徵之間有很強的相關性時,Lasso可能會表現的不規律。下面是一個使用Scikit-Learn 彈性網絡ElasticNet(l1_ratio指的就是混合率r)的簡單樣例:
>>> from sklearn.linear_model import ElasticNet >>> elastic_net = ElasticNet(alpha=0.1, l1_ratio=0.5) >>> elastic_net.fit(X, y) >>> elastic_net.predict([[1.5]]) array([ 1.54333232])
隨着訓練的進行,算法一直學習,它在訓練集上的預測偏差(RMSE)天然而然的降低。然而一段時間後,驗證偏差中止降低,並開始上升。這意味着模型在訓練集上開始出現過擬合。一旦驗證錯誤達到最小值,便提前中止訓練.
隨機梯度和小批量梯度降低不是平滑曲線,你可能很難知道它是否達到最小值。 一種解決方案是,只有在驗證偏差高於最小值一段時間後(你確信該模型不會變得更好了),才中止,以後將模型參數回滾到驗證偏差最小值。
下面是一個早期中止法的基礎應用
from sklearn.base import clone sgd_reg = SGDRegressor(n_iter=1, warm_start=True, penalty=None,learning_rate="constant", eta0=0.0005) minimum_val_error = float("inf") best_epoch = None best_model = None for epoch in range(1000): sgd_reg.fit(X_train_poly_scaled, y_train) # 訓練多項式的新特徵,擬合非線性 y_val_predict = sgd_reg.predict(X_val_poly_scaled) val_error = mean_squared_error(y_val_predict, y_val) if val_error < minimum_val_error: minimum_val_error = val_error best_epoch = epoch best_model = clone(sgd_reg)
注意:當warm_start=True時,調用fit()方法後,訓練會從停下來的地方繼續,而不是從頭從新開始
Logistic迴歸模型計算輸入特徵的加權和(加上誤差項),但它不像線性迴歸模型那樣直接輸出結果,而是把結果輸入logistic()函數進行二次加工後進行輸出
邏輯迴歸模型的機率估計(向量形式):
$$\hat{p}=h_\theta(\mathbf{x})=\sigma(\theta^T \cdot \mathbf{x})$$
Logistic函數(也稱爲logit),用$\sigma()$ 表示,其是一個sigmoid函數(圖像呈S型),它的輸出是一個介於0和1之間的數字
邏輯函數(S函數)
$$\sigma(t)=\frac{1}{1+exp(-t)}$$
邏輯迴歸預測模型($\sigma()$ 機率輸出以0.5做爲二分類門檻):
單個樣例的代價函數:
這個代價函數是合理的,由於當t接近0時,-log(t)變得很是大,因此若是模型估計一個正例機率接近於0,那麼代價函數將會很大,同時若是模型估計一個負例的機率接近1,那麼代價函數一樣會很大。 另外一方面,當t接近於1時, -log(t)接近0,因此若是模型估計一個正例機率接近於0,那麼代價函數接近於0,同時若是模型估計一個負例的機率接近0,那麼代價函數一樣會接近於0, 這正是咱們想的.(簡單來講,y=1時,機率p越接近1損失越小;相反y=0時,機率p越接近0時損失越小)
整個訓練集的代價函數只是全部訓練實例的平均值。能夠用一個表達式(你能夠很容易證實)來統一表示,稱爲對數損失
邏輯迴歸的代價函數(對數損失):
$$J(\theta)=-\frac{1}{m}\sum\limits_{i=1}^m\left[y^{(i)}log\left(\hat{p}^{(i)}\right)+\left(1-y^{(i)}\right)log\left(1-\hat{p}^{(i)}\right)\right]$$
可是這個代價函數對於求解最小化代價函數的$\theta$ 是沒有公式解的(沒有等價的正態方程)。 但好消息是,這個代價函數是凸的,因此梯度降低(或任何其餘優化算法)必定可以找到全局最小值(若是學習速率不是太大,而且你等待足夠長的時間)。下面公式給出了代價函數關於第j個模型參數$\theta_j$ 的偏導數
邏輯迴歸代價函數的偏導數:
$$\frac{\partial}{\partial \theta_j}J(\theta_j)=\frac{1}{m} \sum\limits_{i=1}^m{\left(\sigma\left(\theta^T \cdot \mathbf{x}^{(i)}\right)-y^{(i)}\right)}{x_j}^{(i)}$$
這個公式首先計算每一個樣例的預測偏差,而後偏差項乘以第j項特徵值,最後求出全部訓練樣例的平均值。 一旦你有了包含全部的偏導數的梯度向量,你即可以在梯度向量上使用批量梯度降低算法。 也就是說:你已經知道如何訓練Logistic迴歸模型。 對於隨機梯度降低,你固然只須要每一次使用一個實例,對於小批量梯度降低,你將每一次使用一個小型實例集。
咱們使用鳶尾花數據集來分析Logistic迴歸。 這是一個著名的數據集,其中包含150朵三種不一樣的鳶尾花的萼片和花瓣的長度和寬度。這三種鳶尾花爲:Setosa,Versicolor,Virginica
讓咱們嘗試創建一個分類器,僅僅使用花瓣的寬度特徵來識別Virginica,首先讓咱們加載數據:
>>> from sklearn import datasets >>> iris = datasets.load_iris() >>> list(iris.keys()) ['data', 'target_names', 'feature_names', 'target', 'DESCR'] >>> X = iris["data"][:, 3:] # petal width >>> y = (iris["target"] == 2).astype(np.int)
接下來,咱們訓練一個邏輯迴歸模型:
from sklearn.linear_model import LogisticRegression log_reg = LogisticRegression() log_reg.fit(X, y) # 訓練模型
咱們來看看模型估計的花瓣寬度從0到3釐米的機率估計
X_new = np.linspace(0, 3, 1000).reshape(-1, 1) # 構造花瓣寬度從0到3釐米的全部特徵 y_proba = log_reg.predict_proba(X_new) # 預測機率 plt.plot(X_new, y_proba[:, 1], "g-", label="Iris-Virginica") plt.plot(X_new, y_proba[:, 0], "b--", label="Not Iris-Virginica"
Virginica花的花瓣寬度(用三角形表示)在1.4釐米到2.5釐米之間,而其餘種類的花(由正方形表示)一般具備較小的花瓣寬度,範圍從0.1釐米到1.8釐米。注意,它們之間會有一些重疊。在大約2釐米以上時,分類器很是確定這朵花是Virginica花(分類器此時輸出一個很是高的機率值),而在1釐米如下時,它很是確定這朵花不是Virginica花(不是Virginica花有很是高的機率)。在這兩個極端之間,分類器是不肯定的。可是,若是你使用它進行預測(使用predict()方法而不是predict_proba()方法),它將返回一個最可能的結果。所以,在1.6釐米左右存在一個決策邊界,這時兩類狀況出現的機率都等於50%:若是花瓣寬度大於1.6釐米,則分類器將預測該花是Virginica,不然預測它不是(即便它有可能錯了):
>>> log_reg.predict([[1.7], [1.5]]) array([1, 0])
下圖的線性決策邊界表示相同的數據集,可是此次使用了兩個特徵進行判斷:花瓣的寬度和長度。 一旦訓練完畢,Logistic迴歸分類器就能夠根據這兩個特徵來估計一朵花是Virginica的可能性。 虛線表示這時兩類狀況出現的機率都等於50%:這是模型的決策邊界。 請注意,它是一個線性邊界。每條平行線都表明一個分類標準下的兩兩個不一樣類的機率,從15%(左下角)到90%(右上角)。越過右上角分界線的點都有超過90%的機率是Virginica花
就像其餘線性模型,邏輯迴歸模型也能夠$\ell_1$或者$\ell_2$ 懲罰使用進行正則化。Scikit-Learn默認添加了$\ell_2$ 懲罰
在Scikit-Learn的LogisticRegression模型中控制正則化強度的超參數不是$\alpha$ (與其餘線性模型同樣),而是是它的逆:C. C的值越大,模型正則化強度越低
Logistic迴歸模型能夠直接推廣到支持多類別分類,沒必要組合和訓練多個二分類器, 其稱爲Softmax迴歸或多類別Logistic迴歸.
這個想法很簡單:當給定一個實例$\mathbf{x}$ 時,Softmax迴歸模型首先計算k類的分數$s_k(\mathbf{x})$ ,而後將分數應用在Softmax函數(也稱爲歸一化指數)上,估計出每類的機率。 計算$s_k(\mathbf{x})$ 的公式看起來很熟悉,由於它就像線性迴歸預測的公式同樣
k類的Softmax得分: $s_k(\mathbf{x})= \theta^T \cdot \mathbf{x}$
注意,每一個類都有本身獨一無二的參數向量$\theta_k$ 。 全部這些向量一般做爲行放在參數矩陣$\Theta$ 中
一旦你計算了樣例$\mathbf{x}$ 的每一類的得分,你即可以經過Softmax函數估計出樣例屬於第k類的機率$\hat{p}_k$ :經過計算e的$s_k(\mathbf{x})$ 次方,而後對它們進行歸一化(除以全部分子的總和)。
和Logistic迴歸分類器同樣,Softmax迴歸分類器將估計機率最高(它只是得分最高的類)的那類做爲預測結果,如公式4-21所示
Softmax迴歸分類器一次只能預測一個類(即它是多類的,但不是多輸出的),所以它只能用於判斷互斥的類別,如不一樣類型的植物。 你不能用它來識別一張照片中的多我的。
如今咱們知道這個模型如何估計機率並進行預測,接下來將介紹如何訓練。咱們的目標是創建一個模型在目標類別上有着較高的機率(所以其餘類別的機率較低),最小化公式4-22能夠達到這個目標,其表示了當前模型的代價函數,稱爲交叉熵,當模型對目標類得出了一個較低的機率,其會懲罰這個模型。 交叉熵一般用於衡量待測類別與目標類別的匹配程度(咱們將在後面的章節中屢次使用它)
交叉熵源於信息論。假設你想要高效地傳輸天天的天氣信息。若是有八個選項(晴天,雨天等),則可使用3位對每一個選項進行編碼,由於2^3=8。可是,若是你認爲幾乎天天都是晴天,更高效的編碼「晴天」的方式是:只用一位(0)。剩下的七項使用四位(從1開始)。交叉熵度量每一個選項實際發送的平均比特數。 若是你對天氣的假設是完美的,交叉熵就等於天氣自己的熵(即其內部的不肯定性)。 可是,若是你的假設是錯誤的(例如,若是常常下雨)交叉熵將會更大,稱爲Kullback-Leibler散度(KL散度)。
如今你能夠計算每一類的梯度向量,而後使用梯度降低(或者其餘的優化算法)找到使得代價函數達到最小值的參數矩陣$\Theta$ 。
讓咱們使用Softmax迴歸對三種鳶尾花進行分類。當你使用LogisticRregression對模型進行訓練時,Scikit_Learn默認使用的是一對多模型,可是你能夠設置multi_class參數爲「multinomial」來把它改變爲Softmax迴歸。你還必須指定一個支持Softmax迴歸的求解器,例如「lbfgs」求解器(有關更多詳細信息,請參閱Scikit-Learn的文檔)。其默認使用$\ell_12$ 正則化,你可使用超參數C控制它。
X = iris["data"][:, (2, 3)] # petal length, petal width y = iris["target"] softmax_reg = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10) softmax_reg.fit(X, y)
因此下次你發現一個花瓣長爲5釐米,寬爲2釐米的鳶尾花時,你能夠問你的模型你它是哪一類鳶尾花,它會回答94.2%是Virginica花(第二類),或者5.8%是其餘鳶尾花
>>> softmax_reg.predict([[5, 2]]) array([2]) >>> softmax_reg.predict_proba([[5, 2]]) array([[ 6.33134078e-07, 5.75276067e-02, 9.42471760e-01]])是
圖4-25用不一樣背景色表示告終果的決策邊界。注意,任何兩個類之間的決策邊界是線性的。 該圖的曲線表示Versicolor類的機率(例如,用0.450標記的曲線表示45%的機率邊界)。注意模型也能夠預測一個機率低於50%的類。 例如,在全部決策邊界相遇的地方,全部類的估計機率相等,分別爲33%。