赞
踩
梯度: 参考同济大学数学系编写的《高等数学》
梯度下降: 参考李航老师的《统计学习方法》
梯度下降法(Gradient Descent, GD), 也称最快速下降法(Steepest Descent)常用于求解无约束最优化问题的一种最常用的方法。
梯度:梯度是一个向量,表示某一函数在该点处的方向导数沿着该方向取的最大值,即函数在该点处沿着该方向变化最快,变化率最大(即该梯度向量的模)
数学中,▽符号表示梯度,其值为函数分别对其各个变量的求导组成的向量。
梯度下降法的优化思想是用当前位置负梯度方向作为搜索方向,因为该方向为当前位置的最快下降方向,所以梯度下降法也被称为“最速下降法”。梯度下降法中越接近目标值,变量变化越小。
损失函数loss:
要使得损失函数最小, 也就是要求函数的极小值。
损失函数关于θ的求导:
可以将上述求导写成矩阵形式,如下:使用矩阵计算, 方便代码的设计。
理解: X^T为输入特征矩阵X的转置,
Y为数据的标签矩阵,
h(X)为预测的标签矩阵.
梯度下降的更新公式如下:
其中,
α被称为步长或者学习率(learning rate),表示自变量x每次迭代变化的大小,可当成一个常数,比较小(比如0.001),可以自己设定。
θk表示本轮的θ值,
▽h(θk)是函数h(θk)的梯度,也就是XT(Y-h(X));
θ(k+1)表示对θk的更新, 其值传入到下一轮更新中。
当目标函数的函数值变化非常小的时候或者达到最大迭代次数的时候,就结束循环。
借用网络上的图片形象的表示其迭代计算过程:
梯度下降法(Gradient Descent, GD)常用于求解无约束情况下凸函数(Convex Function)的极小值,是一种迭代类型的算法,因为凸函数只有一个极值点,故求解出来的极小值点就是函数的最小值点。
这里要注意: 求解的有可能是局部最优解。
所以在使用梯度下降的时候,一般需要进行一些调优策略:
我使用的更多的是:调整学习率和 标准化, 方便!
梯度下降法在具体实现的时候, 分为:
a. 批量梯度下降法(Batch Gradient Descent, BGD):
使用所有样本在当前点的梯度值来对变量参数进行更新操作,所有的样本都有贡献,也就是参与调整θ,求解的参数是使得风险函数最小。但当样本数量极大的时候, 计算量增大, 模型收敛速度慢。不推荐使用该方法。
批量梯度下降法更新公式为:
优点:
(1)一次迭代是对所有样本进行计算,此时利用矩阵进行操作,实现了并行。
(2)由全数据集确定的方向能够更好地代表样本总体,从而更准确地朝向极值所在的方向。当目标函数为凸函数时,BGD一定能够得到全局最优。
缺点:
(1)当样本数目 m 很大时,每迭代一步都需要对所有样本计算,训练过程会很慢。
上个自己实现的梯度下降法代码:
一个简单的线性模型, 未加偏置项, 使用批量梯度下降求解,并将其封装为一个类。
import numpy as np class My_gradient_descent: def __init__(self, alpha=0.0001, max_iterations=10000): self.alpha = alpha # 步长 self.max_iterations = max_iterations # 最大迭代次数 self.train_x = None self.train_y = None self.theta = None # 获取训练数据和标签 def fit(self, train_x, train_y): train_x, train_y = np.array(train_x), np.array(train_y) if len(np.shape(train_x)) == 1: train_x = train_x.reshape((np.shape(train_x)[0], 1)) self.m, self.n = np.shape(train_x) self.train_x = np.c_[train_x, np.ones((self.m, 1))] self.train_y = train_y # 批量梯度下降 def batch_gradient_descent(self): """ 梯度: x^T点乘(h(x)-y), h(x)--预测值, y--样本真实值 w = w - alpha*梯度 """ train_x = self.train_x.T theta = np.ones(self.n+1) # 初始化梯度 for i in range(self.max_iterations): hypothesis = np.dot(self.train_x, theta) # 假设值 loss = hypothesis - self.train_y gradient = np.dot(train_x, loss) / self.m # 梯度 theta = theta - self.alpha * gradient # 梯度下降 self.theta = theta # 预测 def predict(self, test_x): test_x = np.array(test_x) if len(np.shape(test_x)) == 1: test_x = test_x.reshape((np.shape(test_x)[0], 1)) m, n = np.shape(test_x) test_x = np.c_[test_x, np.ones((m, 1))] self.batch_gradient_descent() predict_y = np.dot(test_x, self.theta) return predict_y if __name__ == '__main__': Mgd = My_gradient_descent() train_x = [100, 80, 120, 75, 60, 43, 140, 132, 63, 55, 74, 44, 88] train_y = [120, 92, 143, 87, 60, 50, 167, 147, 80, 60, 90, 57, 99] Mgd.fit(train_x, train_y) test_x = [10,20,30,40] print(Mgd.predict(test_x))
b. 随机梯度下降法(Stochastic Gradient Descent, SGD):
在更新变量参数的时候,选取一个样本的梯度值来更新参数。
SGD只是用一个样本数据参与梯度计算,因此省略了求和以及求平均的过程,降低了计算复杂度,因此提升了计算速度。
但是,SGD伴随的一个问题是噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。
优点:
(1)训练速度快。
缺点:
(1)准确度下降。由于即使在目标函数为强凸函数的情况下,SGD仍旧无法做到线性收敛。
(2)可能会收敛到局部最优,由于单个样本并不能代表全体样本的趋势。
(3)不易于并行实现。
随机梯度下降 和 小批量梯度下降法的代码和批量梯度下降代码几乎一样, 这里就不写了。
c.小批量梯度下降法(Mini-batch Gradient Descent, MBGD):
集合BGD和SGD的特性,从原始数据中,每次选择n个样本来更新参数值,一般n选择10.
优点:
(1)通过矩阵运算,每次在一个batch上优化神经网络参数并不会比单个数据慢太多。
(2)每次使用一个batch可以大大减小收敛所需要的迭代次数,同时可以使收敛到的结果更加接近梯度下降的效果。(比如50W条样本,设置batch_size=100时,需要迭代5000次,远小于SGD的50W次)
(3)可实现并行化。
缺点:
(1)batch_size的不当选择可能会带来一些问题。
小结:
如果样本量比较小,采用批量梯度下降算法。
如果样本太大,或者在线算法,使用随机梯度下降算法。
在实际的一般情况下,采用小批量梯度下降算法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。