玩命加载中...
## 一、全批量梯度下降法 全批量梯度下降(full-batch gradient descent)是梯度下降法在机器学习中的直接应用。 下文我们都将以**[练习赛“问答网站问题、回答数量预测”中的数据集](http://sofasofa.io/competition.php?id=4#c2)**为例。 先载入数据集`train.csv`。 ```python import pandas as pd train = pd.read_csv('train.csv') ``` 这个问题是一个回归问题,自变量为`id`,预测目标为`questions`和`answers`。我们可以分开预测`questions`和`answers`。以`questions`为例,我们建立如下的最小二乘线性回归模型 $$y=\beta_0+\beta_1x,$$ 其中$y$表示问题数(`questions`),$x$表示变量`id`,$\beta=({\beta}_0,\beta_1)$为回归系数。 最小二乘法的目标函数$L(&#92;beta)$为 $$L(&#92;beta)=&#92;frac{1}{N}&#92;sum\_{j=1}^N{(y\_j - &#92;hat y\_j)^2} &#61; \sum\_{j=1}^N &#92;frac{1}{N}(&#92;beta\_0+&#92;beta\_1 x\_j - &#92;hat y\_j)^2$$ 其中$\hat y_j$为第$j$个样本的真实值,$y_j$是根据回归系数$\beta_0,\beta_1$得到的第$j$个样本的预测值。 为了下面计算的方便,我们可以先算出损失函数$L(\beta)$的梯度。 $$\nabla L = \left(\frac{\partial L}{\partial \beta\_0}, \frac{\partial L}{\partial \beta\_1}\right) =\left(\frac{2}{N}\sum\_{j=1}^N(\beta\_0+\beta\_1x\_j-\hat y\_j), \frac{2}{N}\sum\_{j=1}^Nx\_j(\beta\_0+\beta\_1x\_j-\hat y\_j)\right)$$ 下面我们来回顾以下梯度下降法的步骤: * (1)当$i=0$,自己设置初始点$\beta^0=(\beta\_0^0,\beta\_1^0)$,设置步长(也就是学习率)$\alpha$,设置迭代终止的误差忍耐度$tol$。 * (2)计算目标函数$L(\beta)$在点$(\beta\_0^i,\beta\_1^i)$上的梯度$\nabla L\_{\beta^i}$ * (3)计算$\beta^{i+1}$,公式如下 $$\beta^{i+1} = \beta^{i} - \alpha \nabla L\_{\beta^i}$$ * (4)计算梯度$\nabla L\_{\beta^{i+1}}$,如果梯度的二范数$&#92;|\nabla L\_{\beta^{i+1}}&#92;|_2$小于等于 $tol$,则迭代停止,最优解的取值为$\beta^{i+1}$;如果它大于$tol$,那么$i=i+1$,并返回第(3)步。 <br> **接下来,我们按步骤用python来实现上面的算法。** (1)设置初始点`beta = [1, 1]`,学习率`alpha = 0.2`。当然你可以选择不同的初始设置。对于`tol`,更切合实际的作法是设置对于损失函数的变动的阈值$tol_L$,这一点会在第(4)步中具体解释。 ```python beta = [1, 1] alpha = 0.2 tol_L = 0.1 ``` (2)计算目标函数$L(\beta)$在点$(\beta\_0^i,\beta\_1^i)$上的梯度$\nabla L\_{\beta^i}$ $$\nabla L = \left(\frac{\partial L}{\partial \beta\_0^i}, \frac{\partial L}{\partial \beta\_1^i}\right)=\left(\frac{2}{N}\sum\_{j=1}^N(\beta\_0^i+\beta\_1^ix\_j-\hat y\_j), \frac{2}{N}\sum\_{j=1}^Nx\_j(\beta\_0^i+\beta\_1^ix\_j-\hat y\_j)\right).$$ 为了后面程序调用方便,我们可以把梯度写成函数`compute_grad(beta, x, y)`的形式。 ```python import numpy as np def compute_grad(beta, x, y): grad = [0, 0] grad[0] = 2. * np.mean(beta[0] + beta[1] * x - y) grad[1] = 2. * np.mean(x * (beta[0] + beta[1] * x - y)) return np.array(grad) ``` (3)计算$\beta^{i+1}$,公式如下 $$\beta^{i+1} = \beta^{i} - \alpha \nabla L_{\beta^i}$$ 我们把这一步写成函数`update_beta(beta, alpha, grad)`。 ```python def update_beta(beta, alpha, grad): new_beta = np.array(beta) - alpha * grad return new_beta ``` (4)计算$\nabla L\_{\beta^{i+1}}$,如果$&#92;|\nabla L\_{\beta^{i+1}}&#92;|\_2\leq tol$,则迭代停止,最优解的取值为$\beta^{i+1}$;如果$&#92;|\nabla L\_{\beta^{i+1}}&#92;|\_2>tol$,那么$i=i+1$,并返回第(3)步。 在实际问题中(特别是针对下文的随机梯度下降和小批量梯度下降),我们常常用$\left|L(\beta^{i+1})-L(\beta^{i})\right|$的大小来判断程序是否收敛,也就是设定$tol\_L$,若$\left|L(\beta^{i+1})-L(\beta^{i})\right|\leq tol\_L$则认为收敛。 这一步我们可以用`while`循环来实现。 <ul class="pagination"> <li><a href="index.php">第1页</a></li> <li class="active"><a href="#">第2页</a></li> <li><a href="3.php">第3页</a></li> <li><a href="4.php">第4页</a></li> <li><a href="5.php">第5页</a></li> <li><a href="6.php">第6页</a></li> </ul> <ul class="pager"> <li class="previous"><a href="index.php"><b>&larr; 返回前一页</b></a></li> <li class="next"><a href="3.php"><b>进入下一页 &rarr;</b></a></li> </ul>