# 擬合 Logistic 模型
> 原文:[https://www.textbook.ds100.org/ch/17/classification_sgd.html](https://www.textbook.ds100.org/ch/17/classification_sgd.html)
```
# HIDDEN
# Clear previously defined variables
%reset -f
# Set directory for data loading to work properly
import os
os.chdir(os.path.expanduser('~/notebooks/17'))
```
```
# HIDDEN
import warnings
# Ignore numpy dtype warnings. These warnings are caused by an interaction
# between numpy and Cython and can be safely ignored.
# Reference: https://stackoverflow.com/a/40846742
warnings.filterwarnings("ignore", message="numpy.dtype size changed")
warnings.filterwarnings("ignore", message="numpy.ufunc size changed")
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
%matplotlib inline
import ipywidgets as widgets
from ipywidgets import interact, interactive, fixed, interact_manual
import nbinteract as nbi
sns.set()
sns.set_context('talk')
np.set_printoptions(threshold=20, precision=2, suppress=True)
pd.options.display.max_rows = 7
pd.options.display.max_columns = 8
pd.set_option('precision', 2)
# This option stops scientific notation for pandas
# pd.set_option('display.float_format', '{:.2f}'.format)
```
之前,我們討論了批量梯度下降,這是一種迭代更新$\BoldSymbol \Theta 的算法,以查找損失最小化參數$\BoldSymbol \Theta$。討論了隨機梯度下降和小批量梯度下降,利用統計理論和并行硬件的方法來減少訓練梯度下降算法的時間。在本節中,我們將把這些概念應用到邏輯回歸中,并使用 SciKit 學習函數遍歷示例。
### 批梯度下降
批梯度下降的一般更新公式如下:
$$ \boldsymbol{\theta}^{(t+1)} = \boldsymbol{\theta}^{(t)} - \alpha \cdot \nabla_\boldsymbol{\theta} L(\boldsymbol{\theta}^{(t)}, \textbf{X}, \textbf{y}) $$
在邏輯回歸中,我們使用交叉熵損失作為我們的損失函數:
$$ L(\boldsymbol{\theta}, \textbf{X}, \textbf{y}) = \frac{1}{n} \sum_{i=1}^{n} \left(-y_i \ln \left(f_{\boldsymbol{\theta}} \left(\textbf{X}_i \right) \right) - \left(1 - y_i \right) \ln \left(1 - f_{\boldsymbol{\theta}} \left(\textbf{X}_i \right) \right) \right) $$
交叉熵損失的梯度為$\nabla_ \boldsymbol \theta l(\boldsymbol \theta、\textbf x、\textbf y)=-\frac 1 n \sum i=1 ^n(y \sigma x u i$。把它插入到更新公式中,我們就可以找到特定于邏輯回歸的梯度下降算法。讓$\sigma_i=f_ \boldSymbol \theta(\textbf x u i)=\sigma(\textbf x u i \cdot \boldSymbol \theta)$:
$$ \begin{align} \boldsymbol{\theta}^{(t+1)} &= \boldsymbol{\theta}^{(t)} - \alpha \cdot \left(- \frac{1}{n} \sum_{i=1}^{n} \left(y_i - \sigma_i\right) \textbf{X}_i \right) \\ &= \boldsymbol{\theta}^{(t)} + \alpha \cdot \left(\frac{1}{n} \sum_{i=1}^{n} \left(y_i - \sigma_i\right) \textbf{X}_i \right) \end{align} $$
* $\BoldSymbol \Theta ^(t)$是迭代$t 時當前對$\BoldSymbol \Theta$的估計$
* $\alpha$是學習率
* $-\frac 1 n \ sum i=1 n \ left(y i-\sigma i \ right)textbf x u i$是交叉熵損失的梯度
* $\BoldSymbol \Theta(t+1)$是通過減去\Alpha$的乘積和以\BoldSymbol \Theta(t)計算的交叉熵損失的下一個估計數。$
### 隨機梯度下降
隨機梯度下降使用單個數據點的損失梯度近似所有觀測的損失函數的梯度。一般更新公式如下,其中$\ell(\boldsymbol \theta,\textbf x u i,y_i)$是單個數據點的損失函數:
$$ \boldsymbol{\theta}^{(t+1)} = \boldsymbol{\theta}^{(t)} - \alpha \nabla_\boldsymbol{\theta} \ell(\boldsymbol{\theta}, \textbf{X}_i, y_i) $$
回到我們在邏輯回歸中的例子,我們使用一個數據點的交叉熵損失梯度來近似所有數據點的交叉熵損失梯度。如下所示,其中$\sigma_i=f \boldsymbol \theta(\textbf x u i)=\sigma(\textbf x u i\cdot\boldsymbol \theta)$。
$$ \begin{align} \nabla_\boldsymbol{\theta} L(\boldsymbol{\theta}, \textbf{X}, \textbf{y}) &\approx \nabla_\boldsymbol{\theta} \ell(\boldsymbol{\theta}, \textbf{X}_i, y_i)\\ &= -(y_i - \sigma_i)\textbf{X}_i \end{align} $$
當我們把這個近似值代入隨機梯度下降的一般公式時,我們找到了邏輯回歸的隨機梯度下降更新公式。
$$ \begin{align} \boldsymbol{\theta}^{(t+1)} &= \boldsymbol{\theta}^{(t)} - \alpha \nabla_\boldsymbol{\theta} \ell(\boldsymbol{\theta}, \textbf{X}_i, y_i) \\ &= \boldsymbol{\theta}^{(t)} + \alpha \cdot (y_i - \sigma_i)\textbf{X}_i \end{align} $$
### 小批量梯度下降
同樣,我們可以使用一個隨機的數據點樣本(稱為小批量)來近似所有觀測的交叉熵損失梯度。
$$ \nabla_\boldsymbol{\theta} L(\boldsymbol{\theta}, \textbf{X}, \textbf{y}) \approx \frac{1}{|\mathcal{B}|} \sum_{i\in\mathcal{B}}\nabla_{\boldsymbol{\theta}} \ell(\boldsymbol{\theta}, \textbf{X}_i, y_i) $$
我們將此近似值替換為交叉熵損失的梯度,得出一個特定于邏輯回歸的小批量梯度下降更新公式:
$$ \begin{align} \boldsymbol{\theta}^{(t+1)} &= \boldsymbol{\theta}^{(t)} - \alpha \cdot -\frac{1}{|\mathcal{B}|} \sum_{i\in\mathcal{B}}(y_i - \sigma_i)\textbf{X}_i \\ &= \boldsymbol{\theta}^{(t)} + \alpha \cdot \frac{1}{|\mathcal{B}|} \sum_{i\in\mathcal{B}}(y_i - \sigma_i)\textbf{X}_i \end{align} $$
## SciKit Learn[?](#Implementation-in-Scikit-learn)中的實現
Scikit Learn 的[`SGDClassifier`](http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html)類提供了隨機梯度下降的實現,我們可以通過指定`loss=log`來使用它。由于 SciKit Learn 沒有實現批梯度下降的模型,因此我們將比較`SGDClassifier`與[`LogisticRegression`](http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html)在`emails`數據集上的性能。為了簡潔起見,我們省略了特征提取:
```
# HIDDEN
emails = pd.read_csv('emails_sgd.csv').sample(frac=0.5)
X, y = emails['email'], emails['spam']
X_tr = CountVectorizer().fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X_tr, y, random_state=42)
y_train = y_train.reset_index(drop=True)
y_test = y_test.reset_index(drop=True)
```
```
log_reg = LogisticRegression(tol=0.0001, random_state=42)
stochastic_gd = SGDClassifier(tol=0.0001, loss='log', random_state=42)
```
```
%%time
log_reg.fit(X_train, y_train)
log_reg_pred = log_reg.predict(X_test)
print('Logistic Regression')
print(' Accuracy: ', accuracy_score(y_test, log_reg_pred))
print(' Precision: ', precision_score(y_test, log_reg_pred))
print(' Recall: ', recall_score(y_test, log_reg_pred))
print()
```
```
Logistic Regression
Accuracy: 0.9913793103448276
Precision: 0.974169741697417
Recall: 0.9924812030075187
CPU times: user 3.2 s, sys: 0 ns, total: 3.2 s
Wall time: 3.26 s
```
```
%%time
stochastic_gd.fit(X_train, y_train)
stochastic_gd_pred = stochastic_gd.predict(X_test)
print('Stochastic GD')
print(' Accuracy: ', accuracy_score(y_test, stochastic_gd_pred))
print(' Precision: ', precision_score(y_test, stochastic_gd_pred))
print(' Recall: ', recall_score(y_test, stochastic_gd_pred))
print()
```
```
Stochastic GD
Accuracy: 0.9808429118773946
Precision: 0.9392857142857143
Recall: 0.9887218045112782
CPU times: user 93.8 ms, sys: 31.2 ms, total: 125 ms
Wall time: 119 ms
```
以上結果表明,與`LogisticRegression`相比,`SGDClassifier`能夠在更短的時間內找到解決方案。雖然`SGDClassifier`的評估指標稍差,但我們可以通過調整超參數來提高`SGDClassifier`的性能。此外,這種差異也是數據科學家在現實世界中經常遇到的一種權衡。根據具體情況,數據科學家可能會在較低的運行時或較高的度量標準上賦予更大的價值。
## 摘要[?](#Summary)
隨機梯度下降是數據科學家用來降低計算成本和運行時間的一種方法。我們可以在 logistic 回歸中看到隨機梯度下降的值,因為我們只需要計算每次迭代一次觀測的交叉熵損失梯度,而不需要計算每次批量梯度下降觀測的交叉熵損失梯度。從使用 Scikit Learn 的`SGDClassifier`的示例中,我們觀察到隨機梯度下降可能會實現稍微差一點的評估指標,但會顯著提高運行時。在更大的數據集或更復雜的模型上,運行時的差異可能更大,因此更有價值。
- 一、數據科學的生命周期
- 二、數據生成
- 三、處理表格數據
- 四、數據清理
- 五、探索性數據分析
- 六、數據可視化
- Web 技術
- 超文本傳輸協議
- 處理文本
- python 字符串方法
- 正則表達式
- regex 和 python
- 關系數據庫和 SQL
- 關系模型
- SQL
- SQL 連接
- 建模與估計
- 模型
- 損失函數
- 絕對損失和 Huber 損失
- 梯度下降與數值優化
- 使用程序最小化損失
- 梯度下降
- 凸性
- 隨機梯度下降法
- 概率與泛化
- 隨機變量
- 期望和方差
- 風險
- 線性模型
- 預測小費金額
- 用梯度下降擬合線性模型
- 多元線性回歸
- 最小二乘-幾何透視
- 線性回歸案例研究
- 特征工程
- 沃爾瑪數據集
- 預測冰淇淋評級
- 偏方差權衡
- 風險和損失最小化
- 模型偏差和方差
- 交叉驗證
- 正規化
- 正則化直覺
- L2 正則化:嶺回歸
- L1 正則化:LASSO 回歸
- 分類
- 概率回歸
- Logistic 模型
- Logistic 模型的損失函數
- 使用邏輯回歸
- 經驗概率分布的近似
- 擬合 Logistic 模型
- 評估 Logistic 模型
- 多類分類
- 統計推斷
- 假設檢驗和置信區間
- 置換檢驗
- 線性回歸的自舉(真系數的推斷)
- 學生化自舉
- P-HACKING
- 向量空間回顧
- 參考表
- Pandas
- Seaborn
- Matplotlib
- Scikit Learn