# 1.5. 隨機梯度下降
校驗者:
[@A](https://github.com/apachecn/scikit-learn-doc-zh)
翻譯者:
[@L](https://github.com/apachecn/scikit-learn-doc-zh)
校驗者:
[@HelloSilicat](https://github.com/HelloSilicat)
[@A](https://github.com/apachecn/scikit-learn-doc-zh)
翻譯者:
[@L](https://github.com/apachecn/scikit-learn-doc-zh)
**隨機梯度下降(SGD)** 是一種簡單但又非常高效的方法,主要用于凸損失函數下線性分類器的判別式學習,例如(線性) [支持向量機](https://en.wikipedia.org/wiki/Support_vector_machine) 和 [Logistic 回歸](https://en.wikipedia.org/wiki/Logistic_regression) 。 盡管 SGD 在機器學習社區已經存在了很長時間, 但是最近在 large-scale learning (大規模學習)方面 SGD 獲得了相當大的關注。
SGD 已成功應用于在文本分類和自然語言處理中經常遇到的大規模和稀疏的機器學習問題。對于稀疏數據,本模塊的分類器可以輕易的處理超過 10^5 的訓練樣本和超過 10^5 的特征。
Stochastic Gradient Descent (隨機梯度下降法)的優勢:
> - 高效。
> - 易于實現 (有大量優化代碼的機會)。
Stochastic Gradient Descent (隨機梯度下降法)的劣勢:
> - SGD 需要一些超參數,例如 regularization (正則化)參數和 number of iterations (迭代次數)。
> - SGD 對 feature scaling (特征縮放)敏感。
## 1.5.1. 分類
Warning
在擬合模型前,確保你重新排列了(打亂))你的訓練數據,或者在每次迭代后用 `shuffle=True` 來打亂。
[`SGDClassifier`](generated/sklearn.linear_model.SGDClassifier.html#sklearn.linear_model.SGDClassifier "sklearn.linear_model.SGDClassifier") 類實現了一個簡單的隨機梯度下降學習例程, 支持不同的 loss functions(損失函數)和 penalties for classification(分類處罰)。
[](../auto_examples/linear_model/plot_sgd_separating_hyperplane.html)
作為另一個 classifier (分類器), 擬合 SGD 我們需要兩個 array (數組):保存訓練樣本的 size 為 \[n\_samples, n\_features\] 的數組 X 以及保存訓練樣本目標值(類標簽)的 size 為 \[n\_samples\] 的數組 Y
```
>>> from sklearn.linear_model import SGDClassifier
>>> X = [[0., 0.], [1., 1.]]
>>> y = [0, 1]
>>> clf = SGDClassifier(loss="hinge", penalty="l2")
>>> clf.fit(X, y)
SGDClassifier(alpha=0.0001, average=False, class_weight=None, epsilon=0.1,
eta0=0.0, fit_intercept=True, l1_ratio=0.15,
learning_rate='optimal', loss='hinge', max_iter=5, n_iter=None,
n_jobs=1, penalty='l2', power_t=0.5, random_state=None,
shuffle=True, tol=None, verbose=0, warm_start=False)
```
擬合后,我們可以用該模型來預測新值:
```
>>> clf.predict([[2., 2.]])
array([1])
```
SGD 通過訓練數據來擬合一個線性模型。成員 `coef_` 保存模型參數:
```
>>> clf.coef_
array([[ 9.9..., 9.9...]])
```
成員 `intercept_` 保存 intercept(截距) (又稱作 offset(偏移)或 bias(偏差)):
```
>>> clf.intercept_
array([-9.9...])
```
模型是否使用 intercept(截距), 即 a biased hyperplane(一個偏置的超平面), 是由參數 `fit_intercept` 控制的。
使用 [`SGDClassifier.decision_function`](generated/sklearn.linear_model.SGDClassifier.html#sklearn.linear_model.SGDClassifier.decision_function "sklearn.linear_model.SGDClassifier.decision_function") 來獲得到此超平面的 signed distance (符號距離)
```
>>> clf.decision_function([[2., 2.]])
array([ 29.6...])
```
具體的 loss function(損失函數) 可以通過 `loss` 參數來設置。 [`SGDClassifier`](generated/sklearn.linear_model.SGDClassifier.html#sklearn.linear_model.SGDClassifier "sklearn.linear_model.SGDClassifier") 支持以下的 loss functions(損失函數):
> - `loss="hinge"`: (soft-margin) linear Support Vector Machine ((軟-間隔)線性支持向量機),
> - `loss="modified_huber"`: smoothed hinge loss (平滑的 hinge 損失),
> - `loss="log"`: logistic regression (logistic 回歸),
> - and all regression losses below(以及所有的回歸損失)。
前兩個 loss functions(損失函數)是懶惰的,如果一個例子違反了 margin constraint(邊界約束),它們僅更新模型的參數, 這使得訓練非常有效率,即使使用了 L2 penalty(懲罰)我們仍然可能得到稀疏的模型結果。
使用 `loss="log"` 或者 `loss="modified_huber"` 來啟用 `predict_proba` 方法, 其給出每個樣本  的概率估計  的一個向量:
```
>>> clf = SGDClassifier(loss="log").fit(X, y)
>>> clf.predict_proba([[1., 1.]])
array([[ 0.00..., 0.99...]])
```
具體的懲罰方法可以通過 `penalty` 參數來設定。 SGD 支持以下 penalties(懲罰):
> - `penalty="l2"`: L2 norm penalty on `coef_`.
> - `penalty="l1"`: L1 norm penalty on `coef_`.
> - `penalty="elasticnet"`: Convex combination of L2 and L1(L2 型和 L1 型的凸組合); `(1 - l1_ratio) * L2 + l1_ratio * L1`.
默認設置為 `penalty="l2"` 。 L1 penalty (懲罰)導致稀疏解,使得大多數系數為零。 Elastic Net(彈性網)解決了在特征高相關時 L1 penalty(懲罰)的一些不足。參數 `l1_ratio` 控制了 L1 和 L2 penalty(懲罰)的 convex combination (凸組合)。
[`SGDClassifier`](generated/sklearn.linear_model.SGDClassifier.html#sklearn.linear_model.SGDClassifier "sklearn.linear_model.SGDClassifier") 通過利用 “one versus all” (OVA)方法來組合多個二分類器,從而實現多分類。對于每一個  類, 可以訓練一個二分類器來區分自身和其他  個類。在測試階段,我們計算每個分類器的 confidence score(置信度分數)(也就是與超平面的距離),并選擇置信度最高的分類。下圖闡釋了基于 iris(鳶尾花)數據集上的 OVA 方法。虛線表示三個 OVA 分類器; 不同背景色代表由三個分類器產生的決策面。
[](../auto_examples/linear_model/plot_sgd_iris.html)
在 multi-class classification (多類分類)的情況下, `coef_` 是 `shape=[n_classes, n_features]` 的一個二維數組, `intercept_` 是 `shape=[n_classes]` 的一個一維數組。 `coef_` 的第 i 行保存了第 i 類的 OVA 分類器的權重向量;類以升序索引 (參照屬性 `classes_` )。 注意,原則上,由于它們允許創建一個概率模型,所以 `loss="log"` 和 `loss="modified_huber"` 更適合于 one-vs-all 分類。
[`SGDClassifier`](generated/sklearn.linear_model.SGDClassifier.html#sklearn.linear_model.SGDClassifier "sklearn.linear_model.SGDClassifier") 通過擬合參數 `class_weight` 和 `sample_weight` 來支持 weighted classes (加權類)和 weighted instances(加權實例)。更多信息請參照下面的示例和 [`SGDClassifier.fit`](generated/sklearn.linear_model.SGDClassifier.html#sklearn.linear_model.SGDClassifier.fit "sklearn.linear_model.SGDClassifier.fit") 的文檔。
示例:
- [SGD: Maximum margin separating hyperplane](../auto_examples/linear_model/plot_sgd_separating_hyperplane.html#sphx-glr-auto-examples-linear-model-plot-sgd-separating-hyperplane-py),
- [Plot multi-class SGD on the iris dataset](../auto_examples/linear_model/plot_sgd_iris.html#sphx-glr-auto-examples-linear-model-plot-sgd-iris-py)
- [SGD: Weighted samples](../auto_examples/linear_model/plot_sgd_weighted_samples.html#sphx-glr-auto-examples-linear-model-plot-sgd-weighted-samples-py)
- [Comparing various online solvers](../auto_examples/linear_model/plot_sgd_comparison.html#sphx-glr-auto-examples-linear-model-plot-sgd-comparison-py)
- [SVM: Separating hyperplane for unbalanced classes](../auto_examples/svm/plot_separating_hyperplane_unbalanced.html#sphx-glr-auto-examples-svm-plot-separating-hyperplane-unbalanced-py) (參見 Note)
[`SGDClassifier`](generated/sklearn.linear_model.SGDClassifier.html#sklearn.linear_model.SGDClassifier "sklearn.linear_model.SGDClassifier") 支持 averaged SGD (ASGD)。Averaging(均值化)可以通過設置 ``average=True`` 來啟用。AGSD 工作原理是在普通 SGD 的基礎上,對每個樣本的每次迭代后的系數取均值。當使用 ASGD 時,學習速率可以更大甚至是恒定,在一些數據集上能夠加速訓練過程。
對于帶 logistic loss(logistic 損失)的分類,在 [`LogisticRegression`](generated/sklearn.linear_model.LogisticRegression.html#sklearn.linear_model.LogisticRegression "sklearn.linear_model.LogisticRegression") 中提供了另一個采取 averaging strategy(平均策略)的 SGD 變體,其使用了隨機平均梯度 (SAG) 算法。
## 1.5.2. 回歸
[`SGDRegressor`](generated/sklearn.linear_model.SGDRegressor.html#sklearn.linear_model.SGDRegressor "sklearn.linear_model.SGDRegressor") 類實現了一個簡單的隨機梯度下降學習例程,它支持用不同的損失函數和懲罰來擬合線性回歸模型。 [`SGDRegressor`](generated/sklearn.linear_model.SGDRegressor.html#sklearn.linear_model.SGDRegressor "sklearn.linear_model.SGDRegressor") 非常適用于有大量訓練樣本(>10.000)的回歸問題,對于其他問題,我們推薦使用 [`Ridge`](generated/sklearn.linear_model.Ridge.html#sklearn.linear_model.Ridge "sklearn.linear_model.Ridge") ,[`Lasso`](generated/sklearn.linear_model.Lasso.html#sklearn.linear_model.Lasso "sklearn.linear_model.Lasso") ,或 [`ElasticNet`](generated/sklearn.linear_model.ElasticNet.html#sklearn.linear_model.ElasticNet "sklearn.linear_model.ElasticNet") 。
具體的損失函數可以通過 `loss` 參數設置。 [`SGDRegressor`](generated/sklearn.linear_model.SGDRegressor.html#sklearn.linear_model.SGDRegressor "sklearn.linear_model.SGDRegressor") 支持以下的損失函數:
> - `loss="squared_loss"`: Ordinary least squares(普通最小二乘法),
> - `loss="huber"`: Huber loss for robust regression(Huber回歸),
> - `loss="epsilon_insensitive"`: linear Support Vector Regression(線性支持向量回歸).
Huber 和 epsilon-insensitive 損失函數可用于 robust regression(魯棒回歸)。不敏感區域的寬度必須通過參數 `epsilon` 來設定。這個參數取決于目標變量的規模。
[`SGDRegressor`](generated/sklearn.linear_model.SGDRegressor.html#sklearn.linear_model.SGDRegressor "sklearn.linear_model.SGDRegressor") 支持 ASGD(平均隨機梯度下降) 作為 [`SGDClassifier`](generated/sklearn.linear_model.SGDClassifier.html#sklearn.linear_model.SGDClassifier "sklearn.linear_model.SGDClassifier")。 均值化可以通過設置 ``average=True`` 來啟用。
對于利用了 squared loss(平方損失)和 l2 penalty(l2懲罰)的回歸,在 [`Ridge`](generated/sklearn.linear_model.Ridge.html#sklearn.linear_model.Ridge "sklearn.linear_model.Ridge") 中提供了另一個采取 averaging strategy(平均策略)的 SGD 變體,其使用了隨機平均梯度 (SAG) 算法。
## 1.5.3. 稀疏數據的隨機梯度下降
Note
由于在截距部分收斂學習速率的差異,稀疏實現與密集實現相比產生的結果略有不同。
在 [scipy.sparse](https://docs.scipy.org/doc/scipy/reference/sparse.html) 支持的格式中,任意矩陣都有對稀疏數據的內置支持方法。但是,為了獲得最高的效率,請使用 [scipy.sparse.csr\_matrix](http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.csr_matrix.html) 中定義的 CSR 矩陣格式.
示例:
- [Classification of text documents using sparse features](../auto_examples/text/document_classification_20newsgroups.html#sphx-glr-auto-examples-text-document-classification-20newsgroups-py)
## 1.5.4. 復雜度
SGD 主要的優勢在于它的高效性,對于不同規模的訓練樣本,處理復雜度基本上是線性的。假如 X 是 size 為 (n, p) 的矩陣,訓練成本為 ,其中 k 是迭代次數,  是每個樣本非零特征的平均數。
但是,最近的理論結果表明,得到期望優化精度的運行時間并不會隨著訓練集規模擴大而增加。
## 1.5.5. 實用小貼士
> - 隨機梯度下降法對 feature scaling (特征縮放)很敏感,因此強烈建議您縮放您的數據。例如,將輸入向量 X 上的每個特征縮放到 \[0,1\] 或 \[- 1,+1\], 或將其標準化,使其均值為 0,方差為 1。請注意,必須將 *相同* 的縮放應用于對應的測試向量中,以獲得有意義的結果。使用 `StandardScaler`: 很容易做到這一點:
>
> > from sklearn.preprocessing import StandardScaler scaler = StandardScaler() scaler.fit(X\_train) # Don’t cheat - fit only on training data X\_train = scaler.transform(X\_train) X\_test = scaler.transform(X\_test) # apply same transformation to test data
>
> 假如你的 attributes (屬性)有一個固有尺度(例如 word frequencies (詞頻)或 indicator features(指標特征))就不需要縮放。
> - 最好使用 `GridSearchCV` 找到一個合理的 regularization term (正則化項)  , 它的范圍通常在 `10.0**-np.arange(1,7)` 。
> - 經驗表明,SGD 在處理約 10^6 訓練樣本后基本收斂。因此,對于迭代次數第一個合理的猜想是 `n_iter = np.ceil(10**6 / n)`,其中 `n` 是訓練集的大小。
> - 假如將 SGD 應用于使用 PCA 做特征提取,我們發現通過某個常數 c 來縮放特征值是明智的,比如使訓練數據的 L2 norm 平均值為 1。
> - 我們發現,當特征很多或 eta0 很大時, ASGD(平均隨機梯度下降) 效果更好。
參考文獻:
- [“Efficient BackProp”](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf)Y. LeCun, L. Bottou, G. Orr, K. Müller - In Neural Networks: Tricks of the Trade 1998.
## 1.5.6. 數學描述
給定一組訓練樣本  ,其中  , , 我們的目標是一個線性 scoring function(評價函數)  ,其中模型參數  ,截距 。為了做預測, 我們只需要看  的符號。找到模型參數的一般選擇是通過最小化由以下式子給出的正則化訓練誤差

其中  衡量模型(mis)擬合程度的損失函數, 是懲罰模型復雜度的正則化項(也叫作懲罰);  是一個非負超平面。
 的不同選擇產生不同的分類器,例如
> - Hinge: (soft-margin) Support Vector Machines.
> - Hinge: (軟-間隔) 支持向量機。
> - Log: Logistic Regression.
> - Log: Logistic 回歸。
> - Least-Squares: Ridge Regression.
> - Least-Squares: 嶺回歸。
> - Epsilon-Insensitive: (soft-margin) Support Vector Regression.
> - Epsilon-Insensitive: (軟-間隔) 支持向量回歸。
所有上述損失函數可以看作是錯誤分類誤差的上限(0 - 1損失),如下圖所示。
[](../auto_examples/linear_model/plot_sgd_loss_functions.html)
比較流行的正則化項  包括:
> - L2 norm: ,
> - L1 norm: , which leads to sparse solutions().
> - Elastic Net: , a convex combination of L2 and L1, where  is given by `1 - l1_ratio`.
下圖顯示當  時參數空間中不同正則項的輪廓。
[](../auto_examples/linear_model/plot_sgd_penalties.html)
### 1.5.6.1. SGD
隨機梯度下降法是一種無約束優化問題的優化方法。與(批量)梯度下降法相反,SGD 通過一次只考慮單個訓練樣本來近似  真實的梯度。
[`SGDClassifier`](generated/sklearn.linear_model.SGDClassifier.html#sklearn.linear_model.SGDClassifier "sklearn.linear_model.SGDClassifier") 類實現了一個 first-order SGD learning routine (一階 SGD 學習程序)。 算法在訓練樣本上遍歷,并且對每個樣本根據由以下式子給出的更新規則來更新模型參數。

其中  是在參數空間中控制步長的 learning rate (學習速率)。 intercept(截距)  的更新類似但不需要正則化。
學習率  可以恒定或者逐漸減小。對于分類來說, 默認的學習率設定方案 (`learning_rate='optimal'`)由下式給出。

其中  是時間步長(總共有 n\_samples \* n\_iter 時間步長),  是由 Léon Bottou 提出的啟發式算法決定的,比如預期的初始更新可以設定為權重的期望大小(假設訓練樣本的范數近似1)。在 `BaseSGD` 中的 `_init_t` 中可以找到確切的定義。
對于回歸來說,默認的學習率是反向縮放 (`learning_rate='invscaling'`),由下式給出

其中  和  是用戶通過 `eta0` 和 `power_t` 分別選擇的超參數。
使用固定的學習速率則設置 `learning_rate='constant'` ,或者設置 `eta0` 來指定學習速率。
模型參數可以通過成員 `coef_` 和 `intercept_` 來獲得:
> - 成員 `coef_` holds the weights(控制權重) 
> - 成員 `intercept_` holds 
參考文獻:
- [“Solving large scale linear prediction problems using stochastic gradient descent algorithms”](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.58.7377)T. Zhang - In Proceedings of ICML ‘04.
- [“Regularization and variable selection via the elastic net”](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.124.4696)H. Zou, T. Hastie - Journal of the Royal Statistical Society Series B, 67 (2), 301-320.
- [“Towards Optimal One Pass Large Scale Learning with Averaged Stochastic Gradient Descent”](http://arxiv.org/pdf/1107.2490v2.pdf)Xu, Wei
## 1.5.7. 實現細節
SGD 的實現受到了 Léon Bottou [Stochastic Gradient SVM](http://leon.bottou.org/projects/sgd) 的影響。類似于 SvmSGD,權重向量表達為一個標量和一個向量的內積,這樣保證在使用L2正則項時可以高效更新權重。 在 sparse feature vectors (稀疏特征向量)的情況下, intercept (截距)是以更小的學習率(乘以 0.01)更新的,這導致了它的更新更加頻繁。訓練樣本按順序選取并且每處理一個樣本就要降低學習速率。我們采用了 Shalev-Shwartz 等人2007年提出的的學習速率設定方案。 對于多類分類,我們使用了 “one versus all” 方法。 我們在 L1 正則化(和 Elastic Net )中使用 Tsuruoka 等人2009年提出的 truncated gradient algorithm (截斷梯度算法)。代碼是用 Cython 編寫的。
參考文獻:
- [“Stochastic Gradient Descent”](http://leon.bottou.org/projects/sgd) L. Bottou - Website, 2010.
- [“The Tradeoffs of Large Scale Machine Learning”](http://leon.bottou.org/slides/largescale/lstut.pdf) L. Bottou - Website, 2011.
- [“Pegasos: Primal estimated sub-gradient solver for svm”](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.74.8513)S. Shalev-Shwartz, Y. Singer, N. Srebro - In Proceedings of ICML ‘07.
- [“Stochastic gradient descent training for l1-regularized log-linear models with cumulative penalty”](http://www.aclweb.org/anthology/P/P09/P09-1054.pdf)Y. Tsuruoka, J. Tsujii, S. Ananiadou - In Proceedings of the AFNLP/ACL ‘09.
- scikit-learn 0.19 中文文檔
- 用戶指南
- 1. 監督學習
- 1.1. 廣義線性模型
- 1.2. 線性和二次判別分析
- 1.3. 內核嶺回歸
- 1.4. 支持向量機
- 1.5. 隨機梯度下降
- 1.6. 最近鄰
- 1.7. 高斯過程
- 1.8. 交叉分解
- 1.9. 樸素貝葉斯
- 1.10. 決策樹
- 1.11. 集成方法
- 1.12. 多類和多標簽算法
- 1.13. 特征選擇
- 1.14. 半監督學習
- 1.15. 等式回歸
- 1.16. 概率校準
- 1.17. 神經網絡模型(有監督)
- 2. 無監督學習
- 2.1. 高斯混合模型
- 2.2. 流形學習
- 2.3. 聚類
- 2.4. 雙聚類
- 2.5. 分解成分中的信號(矩陣分解問題)
- 2.6. 協方差估計
- 2.7. 經驗協方差
- 2.8. 收斂協方差
- 2.9. 稀疏逆協方差
- 2.10. Robust 協方差估計
- 2.11. 新奇和異常值檢測
- 2.12. 密度估計
- 2.13. 神經網絡模型(無監督)
- 3. 模型選擇和評估
- 3.1. 交叉驗證:評估估算器的表現
- 3.2. 調整估計器的超參數
- 3.3. 模型評估: 量化預測的質量
- 3.4. 模型持久化
- 3.5. 驗證曲線: 繪制分數以評估模型
- 4. 數據集轉換
- 4.1. Pipeline(管道)和 FeatureUnion(特征聯合): 合并的評估器
- 4.2. 特征提取
- 4.3. 預處理數據
- 4.4. 無監督降維
- 4.5. 隨機投影
- 4.6. 內核近似
- 4.7. 成對的矩陣, 類別和核函數
- 4.8. 預測目標 (y) 的轉換
- 5. 數據集加載工具
- 6. 大規模計算的策略: 更大量的數據
- 7. 計算性能
- 教程
- 使用 scikit-learn 介紹機器學習
- 關于科學數據處理的統計學習教程
- 機器學習: scikit-learn 中的設置以及預估對象
- 監督學習:從高維觀察預測輸出變量
- 模型選擇:選擇估計量及其參數
- 無監督學習: 尋求數據表示
- 把它們放在一起
- 尋求幫助
- 處理文本數據
- 選擇正確的評估器(estimator)
- 外部資源,視頻和談話