批量梯度+随机梯度+小批量梯度下降法实现

it2022-05-05  117

本篇是对本人之前写的线性回归方法实现的改良版本。

梯度下降法理解

       数学原理请移步相关搜索。

       梯度下降法的总体思想,是按照连续函数的一阶微分的集合方向(梯度方向)进行不断递减,取极限到该店的梯度为<0>为止。(这里要注意一点,梯度方向是该点处下降最快的方向)        在迭代求解的过程中,通过计算该点处的梯度值乘上步长,进行不断的迭代寻找梯度为<0>时候的值。

       梯度下降法在目前算是比较常用的迭代求解方法。下表为几种常见迭代方法比较:

梯度下降法: 优势:只要求函数一阶可微,函数收敛性较强,对初始点位置不敏感,实现简单直观。 缺点:收敛速度慢,而且步长也不好确定。

牛顿法: 优势:二阶收敛,比梯度下降法收敛更快。 缺点:hessian矩阵计算量较大,对初值敏感,可能导致函数不收敛。

高斯牛顿法: 优势:同样二次收敛,相比牛顿法,不需要计算hessian矩阵。 缺点:同样对初值敏感,可能导致函数不收敛或者收敛速度很慢。

阻尼最小二乘法: 优势:加入了阻尼因子,能兼顾高斯牛顿法的二阶收敛特性,也可在阻尼因子较大时,兼顾梯度下降法的初值不敏感特性。 缺点:存在矩阵求逆的操作,对于输入维度过大时,计算量也不小。

信赖域法: 优势:具有全局收敛特性,兼顾阻尼最小二乘法的优点。 缺点:(可能比较难,哈哈哈)

本次线性回归的例子采用了梯度下降法的三种方式进行实现。

三种梯度下降法

图片引用自:https://www.cnblogs.com/pinard/p/5970503.html

三种梯度下降法的实现

批量梯度下降

# 批量梯度下降法 def BGD(x1, x2, w, eta=0.02, n_iter=1000): # 将输入的数列,列表等强制转化为np数列 x1 = np.array(x1) x2 = np.array(x2) w = np.array(w) # 计算输入数列的维度,并添加上偏置值b m = x1.shape[0] add_one_row = np.ones(m) x1 = np.row_stack((x1, add_one_row)) # 批量梯度迭代过程 for i in range(n_iter): w = w - eta * np.sum(-2*np.dot((x2-np.dot(w, x1)), x1.T), axis=0) / m return w

       该方法把向量和偏置b结合到一起,进行梯度运算,每次对梯度方向上的点进行求和,然后返回给w进行迭代。(为上一篇的改良版本。)

随机梯度下降

# 随机梯度下降法 def SGD(x1, x2, w=10, b=10, eta=0.02, n_iter=100): x1 = np.array(x1) x2 = np.array(x2) m = x1.shape[0] for i in range(n_iter): for j in range(m): w = w - eta * (-2 * x1[j] * (x2[j] - w * x1[j] - b)) b = b - eta * (-2 * (x2[j] - w * x1[j] - b)) return w, b

       这里其实可以通过import random.randint模块进行一个随机化的操作。但在操作过程中,我发现随机的效果不好,所以使用了一个for循环。

       可以看到,这个计算次数明显要比批量少了很多。

小批量梯度下降

# 小批量梯度下降法 def MGD(x1, x2, w=10, b=10, eta=0.02, batch_size=10, n_iter=10000): x1 = np.array(x1) x2 = np.array(x2) m = x1.shape[0] for i in range(n_iter): for j in range(m // batch_size): batched_x1 = x1[batch_size*j:batch_size*(j+1)] batched_x2 = x2[batch_size*j:batch_size*(j+1)] w = w - eta * np.sum(-2*batched_x1.T*(batched_x2-w*batched_x1-b)) / m b = b - eta * np.sum(-2*(batched_x2-w*batched_x1-b)) / m return w, b

       根据根据代码可以观察到,该计算量介于批量和随机的中间。而且根据结论来看,小批量的训练水平也不错。

运行结果

       从结果可以看到,批量和小批量的训练结果都不错,而随机的方法好像线型整体偏上面一点。好像结果不那么尽如人意。

       就好像上面的几个点被加权了一样。或者计算了多次。该问题有待进一步的完善。

       批量和小批量方法在训练结果上都比较良好,在Iris数据集较小的时候,批量的计算时间也能控制在0.8秒左右,而小批量的计算时间能控制在0.7秒左右。可以想象,当数据量比较大的时候,小批量的方法能够大大减少计算量。

       相关代码可以在本人的github库中找到:ML-In-Python

       谢谢阅读!


最新回复(0)