第06章:OpenMIT-优化器
- author: zhouyongsdzh@foxmail.com
- date: 2017-04-08
- weibo: @周永_52ML
内容列表
写在前面
随机优化算法(Stochastic Optimization)是指每次随机采样一个或少量几个(Mini-batch)训练样本对模型更新的优化方法。因其有内存消耗低、单次迭代计算复杂度低等优点,被广泛应用于大规模机器学习模型训练中,包括绝大多数深度学习模型的训练。本章要介绍的优化器(Optimizer)涵盖了大规模机器学习和深度学习最常用的优化算法。大致可将其分为以下3类:
- 一阶随机优化。如SGD,AdaGrad,RMSProp,AdaDelta,Adam,FTRL,FTML等;
- 二阶随机优化。如LBFGS等;
- 非凸随机优化。
此外,针对机器学习中的无监督学习,很多无法转化为非优化问题,需要应用概率推理算法求解,比如MCMC,EM等,在本章的后面也会介绍。
随机优化算法
Gradient Descent
梯度下降算法(简称GD)是求解机器学习问题(尤其是凸优化问题)最常用的求解算法。其中,随机梯度下降和批量梯度下降时两种常见的迭代优化思路。
假如优化目标是平方损失函数,以《第01章:深入浅出ML之Regression家族》公式$(ml.1.1.3)$为例:
$$
\min_{w} \quad J(w) = \frac{1}{2m} \sum_{i=1}^{m} \left(h_{w}(x^{(i)}) - y^{(i)} \right)^2
$$
看几类梯度下降算法是如何求解的?
Batch Gradient Descent
参数的每一轮迭代是基于所有数据集,对目标函数$J(w)$求偏导,得到每个$w_i$对应的梯度:
$$
\nabla_{w_j} = \frac{\partial{J(w)}}{\partial{w_j}} = \frac{1}{m} \sum_{i=1}^{m} \left(h_w(x^{(i)}) - y^{(i)}\right) \cdot x_{j}^{(i)}
$$
BGD算法的特点很明显:每次学习都使用整个训练集,即先计算损失函数在整个训练集上的梯度方向,着该方向search下一个迭代点。
优点:在于每次更新都会朝着正确的方向进行,最后能够保证收敛于极值点
凸函数收敛于全局极值点,非凸函数可能会收敛于局部极值点
缺点:在于每次学习时间过长,并且如果训练集很大以至于需要消耗大量的内存,并且全量梯度下降不能用于Online模型参数更新。
Stochastic Gradient Descent
区别于批量梯度下降,这里损失函数对应的训练集中每个样本的粒度,每个样本的损失函数如下:
$$
J\left(w; (x^{(i)}, y^{(i)})\right) = \frac{1}{2} \left(y^{(i)} - h_w(x^{(i)}) \right)^2
$$
求每个参数$w_j$的梯度:
$$
\nabla_{w_j} = \frac{\partial J(w; (x^{(i)}, y^{(i)}))} {\partial w_j} = \left(h_w(x^{(i)}) - y^{(i)}\right) \cdot x_j^{(i)}
$$
Mini-Batch Gradient Descent
BGD的参数更新方式计算复杂度要比SGD高很多,大规模机器学习任务一般不采用BGD来训练模型(主要原因是效率低,以我们的CTR预估模型来说,每次训练时的样本量在10亿级别);而SGD求解时带来的波动较大。这里的mini-batch方式综合了BGD和SGD之间的优点,在参数更新速度和更新次数之间取一个tradeoff。
这里假设每个mini-batch有b个样本,训练集被划分为$K$个batch数据。对应的梯度计算公式与BGD相同,只是样本集有变化,即:
$$
\nabla_{w_j} = \frac{\partial J(w)}{\partial w} = \frac{1}{b} \sum_{i=1}^{b} \left(h_w(x^{(i)}) - y^{(i)}\right) \cdot x_j^{(i)}
$$
相对于随机梯度下降,mini-batch梯度下降降低了收敛波动性,即降低了参数更新的方差,使得更新更加稳定。相对于全量梯度下降,其提高了每次学习的速度。不用担心内存瓶颈从而可以利用矩阵运算进行高效计算。
Online Gradient Descent
Online GD是把梯度下降算法应用到了在线学习(Online Learning)领域。互联网很多应用场景都是实时的,以我们的推荐广告业务系统来说,首先request和response是实时的,过程中不断的产生新数据。而Online Learning要解决的就是充分利用实时数据来更新模型,进而捕捉实时行为用于实时反馈,这也是Online Learning的优势。
Online Learning是实时更新模型,因此训练数据只用一次,然后就丢弃。并且他与基于批量数据集训练模型不同,它不需要样本满足独立同分布(IID)的假设。
Online GD参数更新方式与SGD相同,不再赘述。
GD参数更新
不管是BGD、BGD、mini-batch GD还是Online GD,最小化优化目标,都需要按照每个参数的梯度负方向来更新参数,即:
$$
w_j \leftarrow w_j - \Delta{w_j}; \qquad \Delta{w_j} = \eta \cdot \nabla_{w_j}
$$
其中$\eta$为学习率(又称步长)。
GD问题与挑战
虽然梯度下降算法效果很好,并且应用广告,但同时也存在一些问题待解决:
如何选择一个比较合理的学习率?如果学习速率过小,则会导致收敛速度很慢。如果学习速率过大,那么其会阻碍收敛,即在极值点附近会振荡。
如何调整学习率? 可以尝试在每次更新过程中,改变学习速率。这种一般需要使用某种事先设定的策略抑或在每次迭代中衰减一个较小的阈值。无论如何调整,都需要事先进行固定设置,这边便无法自适应每次学习的数据集特点。
所有模型参数每次更新都是使用相同的学习率。如果数据特征是稀疏的或者每个特征的分布或统计特征有差异,那么就不能在更新时每个参数使用相同的学习速率,对于很少出现的特征应该使用一个相对较大的学习速率。
如何避免在求解非凸优化问题时,容易陷入到次优的局部极值点? 比如深度神经网路优化问题。
Adaptive Gradient Descent
自适应梯度下降算法,简称AdaGrad。与GD不同的是,AdaGrad在更新参数时,学习率不在设定为固定值。每次迭代过程中,每个参数更新时使用不同的学习率。
假设在第$k$轮迭代,$\nabla_{k,w_j}$表示目标函数对参数$w_j$的梯度。普通的GD算法,对于所有的$w_j$使用相同的学习率,因此在第$k$次迭代时,参数$w_j$的变化过程如上述公式GD参数更新.
而AdaGrad更新参数的规则,学习率$\eta$会随着迭代过程并根据历史梯度的变化而变化。如下所示:
$$
w_{j} \leftarrow w_j - \frac{\eta}{\sqrt{n_{k,w_j} + \epsilon}} \cdot \nabla_{k, w_j}
$$
$n_{k,w_j} = \sum_{i=1}^{k} \nabla_{i,w_j}$表示参数$w_j$在1到第$k$次梯度平方的累加和。$\epsilon$用于平滑,保证分母不为0,一般取较小值(如1e-8)。
AdaGrad算法总结如下:
开始时$\sqrt{n_{k,w_j}}$较小,学习率较大,相当于放大梯度,加快寻找最优解的步伐;后期$\sqrt{n_{k,w_j}}$越来越大,学习率越来越小,能够约束梯度。
仍然需要依赖于人工设置的一个全局学习率$\eta$用于初始化。$\eta$如果初始过大,会使整个学习率变大,对梯度的调节也大;
随着迭代进行,分母上梯度平方累加和将会越来越大,使$w_j$的更新量$\rightarrow 0$,导致学习率急剧下降,训练提前结束。
更新$w_j$时,左右两边的单位不同一。
RMSProp
均方根传播算法(Root Mean Square Propagationd,简称RMSProp)是由Hinton在2012年的文章《RmsProp: divide the gradient by a running average of its recent magnitude》中提出。他是针对AdaGrad算法在迭代后期学习率下降过快给出的改进版本。RMSProp通过引入一个衰减系数$\gamma$(又称遗忘因子,forgetting factor),每次计算的梯度平方都按照$\gamma$衰减一定比例来计算梯度累计量$n$。
$$
n_{k,w_j} = \gamma \cdot n_{k-1,w_j} + (1 - \gamma) \cdot \nabla_{k, w_j} \cdot \nabla_{k,w_j}
$$
参数的更新方式与AdaGrad算法相同。
RMSProp算法总结如下:
- 相比AdaGrad,该算法很好的解决了模型训练过早结束的问题(尤其在深度学习模型中较常见);
- 引入了新的超参数:衰减稀疏$\gamma$ (默认值可设置为0.95,但本人试验发现接近于1效果更好,比如0.99);
- 算法依然依赖于全局学习率;
AdaDelta
除了RMSProp算法外,Adadelta算法也是针对Adagrad算法在迭代后期比较难找到有用解的问题作了改进。该算法由Matthew D. Zeiler在2012年的论文ADADELTA: An Adaptive Learning Rate Method中提出。有意思的是Adadelta算法没有学习率这一超参数。
AdaDelta算法也像RMSProp算法一样,使用了batch随机梯度信息$\nabla_{k, w_j}$按元素平方的指数加权移动平均变量$n_{k,w_j}$:
$$
n_{k,w_j} = \rho \cdot n_{k-1,w_j} + (1 - \rho) \cdot \nabla_{k, w_j} \cdot \nabla_{k,w_j}
$$
这里$\rho$是衰减系数,通过这个衰减系数,我们令每一个时刻的$g_t$随之时间按照$\rho$指数衰减,这样就相当于我们仅使用离当前时刻比较近的梯度信息,从而使得还很长时间之后,参数仍然可以得到更新。
与RMSProp不同的是,AdaDelta算法还维护一个额外的状态变量$\Delta w_k$,其元素同样在时间步0时被初始化为0。我们使用$\Delta w_{k-1}$来计算参数的变化量:
$$
g_{k}^’ \leftarrow \sqrt{\frac{\Delta w + \epsilon}{n_{k,w_j} + \epsilon}} \cdot g_k
$$
接着更新参数:
$$
w_j \leftarrow w_j - g’
$$
最后,使用$\Delta w$来记录参数变化量$g’$按元素平方的指数加权移动平均:
$$
\Delta w_k \leftarrow \rho \cdot \Delta w_{k-1} + (1-\rho) g’ \cdot g’
$$
可以看到,如果不考虑$\epsilon$的影响,AdaDelta与RMSProp的不同之处在于使用$\sqrt{\Delta w_{k-1}}$来替代超参数$\eta$。
Adam
自适应矩估计算法(Adaptive Moment Estimation,简称Adam)是另外一种计算自适应学习率的随机优化算法,由Diederik P. Kingma发表在2015年ICLR会议的论文《Adam: A Method for Stochastic Optimization》中提出。除了像RMSProp和AdaDelta一样计算过去梯度平方的$v_k$指数衰减均值(二阶矩估计),也会计算过去梯度$m_k$的指数衰减均值(一阶矩估计)。算法更新过程如下:
$$
m_k = \beta_1 \dot m_{k-1} + (1 - \beta_1) \cdot \nabla_k \quad(1) \\\
v_k = \beta_2 \dot m_{k-1} + (1 - \beta_2) \cdot \nabla_k \cdot \nabla_k \quad(2) \\\
\hat{m_t} = \frac{m_k}{1 - \beta_1} \quad(3) \\\
\hat{v_t} = \frac{v_t}{1 - \beta_2} \quad(4) \\\
w_k = w_{k-1} - \frac{\eta}{\sqrt{v_t + \epsilon}} \cdot m_k \quad(5)
$$
其中,$(3)$和$(4)$是为了做偏差校正:如果$m_k$和$v_k$被初始化为0向量,那它们就会向0偏置,这里通过计算偏差校正后的$m_k$和$v_k$来抵消这些偏差。$(5)$是参数更新规则。
$(3), (4), (5)$步等价于:
$$
\hat{\eta} = \eta \cdot \frac{\sqrt{1 - \beta_2}} {1 - \beta_1} \\\
\hat{\epsilon} = \epsilon \cdot \sqrt{1 - \beta_2} \\\
w_k = w_{k-1} - \frac{w_k} {\sqrt{v_t + \hat{\epsilon}}}
$$
超参数取值:论文中给出了建议的超参数取值($\beta_1 = 0.9, \; \beta_2=0.999, \; \epsilon=10e-8$)。在实验中发现$\beta_1$为0.99效果更好(仅仅是在我们的数据场景中的表现,不一定具有普世性)。
Follow The Regularized Leader-Proximal
FTRL-Proximal算法是Google在2013年的一篇论文《Ad Click Prediction: a View from the Trenches》中提到的参数在线学习算法,论文中提到该算法用在了Google的搜索广告在线学习系统中。因为算法比较容易理解且工程实现不复杂,业内诸多公司都有尝试并取得了不错的收益。
FTRL-Proximal算法不仅可用于在线学习(不要求数据IID,样本序列学习),同时也可以用于离线基于batch数据的参数求解。所以这里也把该算法作为“优化器”的一种,用于大规模机器学习任务的参数求解(该算法本身就是为了很好的求解大规模在线学习任务而提出的)。
FTRL-Proximal演化进程
Online Gradient Descent (OGD, 在线梯度下降)
可以有非常好的预估准确性,并且占用较少的资源。但是它不能得到有效的稀疏模型(非零参数),即便优化目标添加L1惩罚项也不能产生严格意义上的稀疏解(会使参数接近于0,而不是0)。
这里OGD其实就是随机梯度下降,之所以强调Online是因为这里不适用于解决batch数据问题的,而是用于样本序列化问题求解的,后者不要求样本是独立同分布(IID))的。
Truncated Gradient and FOBOS
参数\(w_j\)设定阈值,当参数小雨阈值时置为0,可得稀疏解。Regularized Dual Averaging(RDA, 正则化对偶平均)
RDA可以得到稀疏解,在预估准确性和模型稀疏性方面优于FOBOS算法。
有没有既能结合RDA获得模型稀疏性,同时又具备OGD的精度的学习算法呢?答案是肯定的,那就是:”Follow The (Proximal) Regularized Leader”算法。
FTRL-Proximal工作原理
为了更容易的理解FTRL的工作原理,这里以学习LR模型参数为例,看FTRL是如何求解的:
首先,对于一个实例\(\mathbf{x}^{(i)} \in R^n\)预测其标签$y=1$的概率$p$(第$i$次迭代的模型参数\(\mathbf{w}^{(i)}\))。公式\(p^{(i)} = \sigma(\mathbf{w}^{(i)} \cdot \mathbf{x}^{(i)}), \; \sigma(a) = \frac{1}{1 + \exp(-a)}\).
然后,观测标签\(y^{(i)} \in \{0,1\}\),LR模型的损失函数(Logistic Loss)为:
$$
\mathcal{l} \; (w^{(i)}) = -y^{(i)} \log p^{(i)} - (1 - y^{(i)}) \log (1- p^{(i)}) \qquad (1)
$$梯度方向:
$$
\mathbf{g}_i = \nabla_i = \frac{\partial l \;(w)} {\partial w} = (\sigma(w \cdot x^{(i)}) - y^{(i)}) = (p^{(i)} - y^{(i)}) \cdot \mathbf{x}^{(i)} \qquad(2)
$$OGD算法迭代公式:
$$
w_{i+1} = w_i - \eta_i \mathbf{g}_i \qquad(3)
$$其中\(\eta_i\)表示非递增的学习率,如\(\eta_i=\frac{1}{\sqrt{i}}\),\(\mathbf{\nabla}_i\)表示当前梯度值。
FTRL-Proximal
$$
\mathbf{w}_{i+1} = \text{arg} \min_w \left( \underline{ \sum_{s=1}^{i} \mathbf{g}_s} \cdot \mathbf{w} + \frac{1}{2} \sum_{s=1}^{i} \sigma_s {\Vert \mathbf{w} - \mathbf{w}_s \Vert}_2^2 + \lambda_1 {\Vert \mathbf{w} \Vert}_1 \right) \qquad(4)
$$\(\sigma_s\)为学习率参数,有\(\sigma_{1:i} = \frac{1}{\eta_i}\)。上式等价于:
$$
\left( \sum_{s=1}^{i} \mathbf{g}_s - \sum_{s=1}^{i} \sigma_s \mathbf{w}_s \right) \cdot \mathbf{w} + \frac{1}{\eta_i} {\Vert \mathbf{w} \Vert}_2^2 + \lambda_1 {\Vert \mathbf{w} \Vert}_1 + (\text{const}) \qquad(5)
$$如果我们存储\(\mathbf{z}_{i-1} = \sum_{s=1}^{i-1} \mathbf{g}_s - \sum_{s=1}^{i-1} \sigma_s \mathbf{w}_s\),在第\(i\)轮迭代时,\(\mathbf{z}_i = \mathbf{z}_{i-1} + \mathbf{g}_i + \left(\frac{1}{\eta_i} - \frac{1}{\eta_{i-1}} \right) \mathbf{w}_i\)。求\(\mathbf{w}_{i+1}\)每一维参数的闭式解为:
$$
w_{i+1, j} =
\left \{
\begin{array}{ll}
0, & \text{if} \; |z_{i,j}| \le \lambda_1 \\\
-\eta_i \left(z_{i,j} - \text{sgn}(z_{i,j}) \lambda_1 \right) & \text{otherwise}.
\end{array}
\right. \qquad(6)
$$每一维特征的学习率计算公式(与对应特征维度梯度累加和 && 梯度平方和相关):
$$
\eta_{i,j} = \frac{\alpha}{\beta + \sqrt{\sum_{s=1}^{i} g_{s,j}^2}} = \frac{1}{\sqrt{n_{i+1,j}}}
\qquad(7)
$$\(n_i = \sum_{s=1}^{i-1} g_{s}^2\)表示梯度平方累加和,参数\(\mathbf{z} \in R^n\)在内存存储。
FTRL-Proximal伪代码
\(\{ \\\
\quad01. \;\text{Per-Coordinate FTRL-Proximal with L}_1 \text{ and L}_2 \text{ Regularization for Logistic Regression. } \\\
\quad02. \;\text{// 支持} L_1 \text{与} L_2 \text{正则项的FTRL-Proximal算法. Per-Coordinate学习率为公式(7). } \\\
\quad03. \;\text{Input: parameters } \alpha, \beta, \lambda_1, \lambda_2. 初始化z_i = 0 和n_i=0.\quad // 参数 \alpha, \beta 用于\text{Per-Coordinate}计算学习率 \\\
\quad04. \;\mathbf{\text{for}} \; t=1 \; to \; T; do \\\
\quad05. \quad 接受特征向量\mathbf{x}_t, \; I = \{i| x_i \neq 0 \}. \quad //取非0特征index集合。 \\\
\quad06. \quad\text{For i} \in I, 计算 \\\
\quad07. \quad\qquad w_{t, i} =
\; \left \{
\; \begin{array}{ll}
0, & \text{if} \; |z_{i}| \le \lambda_1 \\\
-\left( \frac{\beta + \sqrt{n_i}}{\alpha} + \lambda_2 \right)^{-1} \cdot \left(z_{i} - \text{sign}(z_{i}) \lambda_1 \right) & \text{otherwise}
\end{array}
\right. 。\\\
\quad08. \quad 预测 p_t = \sigma(\mathbf{x}_t \cdot \mathbf{w}) 使用w_{t,i}计算。\\\
\quad09. \quad \text{For} \; i \in I; 更新参数 \\\
\quad10. \qquad g_i = (p_t - y_t) \cdot x_i \qquad // 第i维特征的梯度(libsvm格式数据,x_i多为1.)\\\
\quad11. \qquad \sigma_i = \frac{1}{\alpha} \left(\sqrt{n_i + g_i^2} - \sqrt{n_i} \right) \qquad // n_i表示第i维梯度(前t-1次)的平方累加和 \\\
\quad12. \qquad z_i \leftarrow z_{i-1} + g_i - \sigma_i w_{t,i} \qquad // 更新\text{FTRL}目标函数的梯度公式 \\\
\quad13. \qquad n_i \leftarrow n_i + g_i^2 \qquad // 更新第i维梯度平方累加和值。\\\
\}
\)
FTRL算法添加了per-coordinate学习率,目标函数支持L2正则。
解释per-coordinate
FTRL学习过程是对参数向量\(\mathbf{w}\)每一维分开训练更新的,每一维使用不同的学习率。与\(n\)个特征维度使用统一的学习率相比,此种方法考虑到了训练样本本身在不同特征维度上分布不均匀的特点。
如果包含\(w\)某一个维度特征的训练样本很少,每一个样本都很珍贵,那么该特征维度对应的训练速率可以独自保持比较大的值,每来一个包含该特征的样本,就可以在该样本的梯度上前进一大步,而不需要与其他特征维度的前进步调强行保持一致。
FTRL实验经验
参数 | 变化 | $\mathcal{\sigma}$变化 | $z$变化 | $n$变化 | lrate变化 | $w$变化 | 备注 |
---|---|---|---|---|---|---|---|
$\alpha$ | $\uparrow$ | $\downarrow$ | 振幅变小 | $-$ | $\uparrow$ | 振幅不确定 | |
$\beta$ | $\uparrow$ | $-$ | $-$ | $-$ | $\downarrow$ | 振幅变大 | 实践$\beta$从0.1调至2,效果正向 |
$\mathcal{l_1}$ | $\uparrow$ | $-$ | $-$ | $-$ | $-$ | 稀疏性增加,绝对值变小 | 从0.5调到0.01效果正向 |
$\mathcal{l_2}$ | |||||||
$\nabla_g$ | $\downarrow$ | $\downarrow$ | 振幅变小 | 变小$\downarrow$ | 变大 |
alpha持续调大,训练集拟合越好越好,测试集表现变差,原因分析:
alpha变大,sigma变小,z的振幅变小
Follow the Moving Leader
FTML算法是2017年香港科技大学发表在ICML会议上的一篇论文《Follow the Moving Leader in Deep Learning》提到的。论文中主要为解决深度学习中参数学习收敛效率问题而出来的新算法。
在深度学习中,参数以及数据分布都会随着迭代进行不断变化,这使得深度学习模型的训练一直是一个具有挑战性的问题。针对这一问题,本文提出了全新的 FTML 算法,具有更快收敛速度。与已有优化算法(如 FTRL)不同的是,本文的 FTML 算法迭代中,越新样本具有越大权重,这使算法更能适应数据分布变化,有更快收敛速度。论文的最后,通过在多个数据集上训练深度学习模型训练实验结果做对比,得出FTML 比其他已有算法收敛更快的结论。
$
\{ \\\
\quad//\;\text{Follow the Moving Leader (FTML)} \\\
\quad01. \;\text{Input: parameters } \eta; \; \beta_1,\beta_2 \in [0, 1); \epsilon > 0; \qquad //\; \eta:初始化学习率,\epsilon:防止分母为0,\\\
\quad02. \;\mathbf{w}; d \leftarrow 0; v \leftarrow 0; z \leftarrow 0; \qquad\qquad // 初始化中间变量和参数 \\\
\quad03. \;\mathbf{\text{for}} \; t=1 \; to \; T; do \\\
\quad04. \quad 特征向量\mathbf{x}_t, \; I = \{i| x_i \neq 0 \}. \quad //取非0特征index集合。 \\\
\quad05. \quad p_t = predict(\mathbf{w_t}, \mathbf{x_t}) \qquad // \;预测\\\
\quad06. \quad \text{for} \; i \in I; \; do \qquad\qquad\; //\; 更新参数 \\\
\quad07. \qquad g_i = (p_t - y_t) \cdot x_i \qquad\qquad\qquad // 计算梯度 \\\
\quad08. \qquad v_t \leftarrow \beta_2 \cdot v_{t-1} + (1-\beta_2) \cdot g_i^2 \qquad // 二阶距估计 \\\
\quad09. \qquad d_t \leftarrow \frac{1 - \beta_1^t} {\eta_t} \cdot \left(\sqrt{\frac{v_t} {1 - \beta_2^t}} + \epsilon \cdot \mathbf{1} \right) \qquad // \\\
\quad10. \qquad \sigma_t \leftarrow d_t - \beta_1 \cdot d_{t-1}; \qquad // 中间变量 \\\
\quad11. \qquad z_t \leftarrow \beta_1 z_{t-1} + (1 - \beta_1) g_t - \sigma_t w_{t-1}; \qquad // \\\
\quad12. \qquad w \leftarrow \prod_{W}^{\text{diag} \left(\frac{d_t}{(1 - \beta_1^t)}\right)} \left(-\frac{z_t}{d_t}\right) \quad // \\\
\quad13. \quad \text{end for} \\\
\quad14.\; \mathbf{end \;for} \\\
\quad15.\; \mathbf{Output:\; w}. \\\
\}
$
参考资料
- 《An overview of gradient descent optimization algorithms》
- 《Follow the Moving Leader in Deep Learning》
- 验证梯度计算是否正确:http://cs231n.github.io/neural-networks-3/
- 技术博客:http://www.cnblogs.com/ranjiewen/p/5938944.html
- 优化算法总结文档:http://sebastianruder.com/optimizing-gradient-descent/
- 优化算法:http://www.cnblogs.com/neopenx/p/4768388.html