香港云主机最佳企业级服务商!

ADSL拨号VPS包含了中国大陆(联通,移动,电信,)

中国香港,国外拨号VPS。

当前位置:云主机 > python >

电信ADSL拨号VPS
联通ADSL拨号VPS
移动ADSL拨号VPS

python实现梯度下降算法


时间:2022-01-11 10:32 作者:admin610456


梯度下降(Gradient Descent)算法是机器学习中使用非常广泛的优化算法。当前流行的机器学习库或者深度学习库都会包括梯度下降算法的不同变种实现。

本文主要以线性回归算法损失函数求极小值来说明如何使用梯度下降算法并给出python/' target='_blank'>python实现。若有不正确的地方,希望读者能指出。

梯度下降

梯度下降原理:将函数比作一座山,我们站在某个山坡上,往四周看,从哪个方向向下走一小步,能够下降的最快。

在线性回归算法中,损失函数为

在求极小值时,在数据量很小的时候,可以使用矩阵求逆的方式求最优的θ值。但当数据量和特征值非常大,例如几万甚至上亿时,使用矩阵求逆根本就不现实。而梯度下降法就是很好的一个选择了。

使用梯度下降算法的步骤:

1)对θ赋初始值,这个值可以是随机的,也可以让θ是一个全零的向量。

2)改变θ的值,使得目标损失函数J(θ)按梯度下降的方向进行减少。

其中为学习率或步长,需要人为指定,若过大会导致震荡即不收敛,若过小收敛速度会很慢。

3)当下降的高度小于某个定义的值,则停止下降。

另外,对上面线性回归算法损失函数求梯度,结果如下:

在实际应用的过程中,梯度下降算法有三类,它们不同之处在于每次学习(更新模型参数)使用的样本个数,每次更新使用不同的样本会导致每次学习的准确性和学习时间不同。下面将分别介绍原理及Python实现。

批量梯度下降(Batch gradient descent)  

每次使用全量的训练集样本来更新模型参数,即给定一个步长,然后对所有的样本的梯度的和进行迭代:

梯度下降算法最终得到的是局部极小值。而线性回归的损失函数为凸函数,有且只有一个局部最小,则这个局部最小一定是全局最小。所以线性回归中使用批量梯度下降算法,一定可以找到一个全局最优解。

优点:全局最优解;易于并行实现;总体迭代次数不多
缺点:当样本数目很多时,训练过程会很慢,每次迭代需要耗费大量的时间。

随机梯度下降(Stochastic gradient descent)

随机梯度下降算法每次从训练集中随机选择一个样本来进行迭代,即:

随机梯度下降算法每次只随机选择一个样本来更新模型参数,因此每次的学习是非常快速的,并且可以进行在线更新。

随机梯度下降最大的缺点在于每次更新可能并不会按照正确的方向进行,因此可以带来优化波动(扰动)。不过从另一个方面来看,随机梯度下降所带来的波动有个好处就是,对于类似盆地区域(即很多局部极小值点)那么这个波动的特点可能会使得优化的方向从当前的局部极小值点跳到另一个更好的局部极小值点,这样便可能对于非凸函数,最终收敛于一个较好的局部极值点,甚至全局极值点。

优点:训练速度快,每次迭代计算量不大
缺点:准确度下降,并不是全局最优;不易于并行实现;总体迭代次数比较多。

Mini-batch梯度下降算法

Mini-batch梯度下降综合了batch梯度下降与stochastic梯度下降,在每次更新速度与更新次数中间取得一个平衡,其每次更新从训练集中随机选择b,b<m个样本进行学习,即:

python代码实现

批量梯度下降算法

#!/usr/bin/python#coding=utf-8import numpy as npfrom scipy import statsimport matplotlib.pyplot as plt # 构造训练数据x = np.arange(0., 10., 0.2)m = len(x) # 训练数据点数目print mx0 = np.full(m, 1.0)input_data = np.vstack([x0, x]).T # 将偏置b作为权向量的第一个分量target_data = 2 * x + 5 + np.random.randn(m) # 两种终止条件loop_max = 10000 # 最大迭代次数(防止死循环)epsilon = 1e-3 # 初始化权值np.random.seed(0)theta = np.random.randn(2) alpha = 0.001 # 步长(注意取值过大会导致振荡即不收敛,过小收敛速度变慢)diff = 0.error = np.zeros(2)count = 0 # 循环次数finish = 0 # 终止标志 while count < loop_max: count += 1  # 标准梯度下降是在权值更新前对所有样例汇总误差,而随机梯度下降的权值是通过考查某个训练样例来更新的 # 在标准梯度下降中,权值更新的每一步对多个样例求和,需要更多的计算 sum_m = np.zeros(2) for i in range(m): dif = (np.dot(theta, input_data[i]) - target_data[i]) * input_data[i] sum_m = sum_m + dif # 当alpha取值过大时,sum_m会在迭代过程中会溢出  theta = theta - alpha * sum_m # 注意步长alpha的取值,过大会导致振荡 # theta = theta - 0.005 * sum_m # alpha取0.005时产生振荡,需要将alpha调小  # 判断是否已收敛 if np.linalg.norm(theta - error) < epsilon: finish = 1 break else: error = theta print 'loop count = %d' % count, '\tw:',thetaprint 'loop count = %d' % count, '\tw:',theta # check with scipy linear regressionslope, intercept, r_value, p_value, slope_std_error = stats.linregress(x, target_data)print 'intercept = %s slope = %s' % (intercept, slope) plt.plot(x, target_data, 'g*')plt.plot(x, theta[1] * x + theta[0], 'r')plt.show()

运行结果截图:

随机梯度下降算法

#!/usr/bin/python#coding=utf-8import numpy as npfrom scipy import statsimport matplotlib.pyplot as plt # 构造训练数据x = np.arange(0., 10., 0.2)m = len(x) # 训练数据点数目x0 = np.full(m, 1.0)input_data = np.vstack([x0, x]).T # 将偏置b作为权向量的第一个分量target_data = 2 * x + 5 + np.random.randn(m) # 两种终止条件loop_max = 10000 # 最大迭代次数(防止死循环)epsilon = 1e-3 # 初始化权值np.random.seed(0)theta = np.random.randn(2)# w = np.zeros(2) alpha = 0.001 # 步长(注意取值过大会导致振荡,过小收敛速度变慢)diff = 0.error = np.zeros(2)count = 0 # 循环次数finish = 0 # 终止标志######-随机梯度下降算法while count < loop_max: count += 1  # 遍历训练数据集,不断更新权值 for i in range(m): diff = np.dot(theta, input_data[i]) - target_data[i] # 训练集代入,计算误差值  # 采用随机梯度下降算法,更新一次权值只使用一组训练数据 theta = theta - alpha * diff * input_data[i]  # ------------------------------终止条件判断----------------------------------------- # 若没终止,则继续读取样本进行处理,如果所有样本都读取完毕了,则循环重新从头开始读取样本进行处理。  # ----------------------------------终止条件判断----------------------------------------- # 注意:有多种迭代终止条件,和判断语句的位置。终止判断可以放在权值向量更新一次后,也可以放在更新m次后。 if np.linalg.norm(theta - error) < epsilon: # 终止条件:前后两次计算出的权向量的绝对误差充分小 finish = 1 break else: error = thetaprint 'loop count = %d' % count, '\tw:',theta  # check with scipy linear regressionslope, intercept, r_value, p_value, slope_std_error = stats.linregress(x, target_data)print 'intercept = %s slope = %s' % (intercept, slope) plt.plot(x, target_data, 'g*')plt.plot(x, theta[1] * x + theta[0], 'r')plt.show()

运行结果截图:

Mini-batch梯度下降

#!/usr/bin/python#coding=utf-8import numpy as npfrom scipy importstatsimport matplotlib.pyplot as plt # 构造训练数据x = np.arange(0.,10.,0.2)m = len(x) # 训练数据点数目print mx0 = np.full(m, 1.0)input_data = np.vstack([x0, x]).T # 将偏置b作为权向量的第一个分量target_data = 2 *x + 5 +np.random.randn(m) # 两种终止条件loop_max = 10000 #最大迭代次数(防止死循环)epsilon = 1e-3 # 初始化权值np.random.seed(0)theta = np.random.randn(2) alpha = 0.001 #步长(注意取值过大会导致振荡即不收敛,过小收敛速度变慢)diff = 0.error = np.zeros(2)count = 0 #循环次数finish = 0 #终止标志minibatch_size = 5 #每次更新的样本数while count < loop_max: count += 1  # minibatch梯度下降是在权值更新前对所有样例汇总误差,而随机梯度下降的权值是通过考查某个训练样例来更新的 # 在minibatch梯度下降中,权值更新的每一步对多个样例求和,需要更多的计算  for i inrange(1,m,minibatch_size): sum_m = np.zeros(2) for k inrange(i-1,i+minibatch_size-1,1):  dif = (np.dot(theta, input_data[k]) - target_data[k]) *input_data[k]  sum_m = sum_m + dif #当alpha取值过大时,sum_m会在迭代过程中会溢出  theta = theta- alpha * (1.0/minibatch_size) * sum_m #注意步长alpha的取值,过大会导致振荡  # 判断是否已收敛 if np.linalg.norm(theta- error) < epsilon: finish = 1 break else: error = theta print 'loopcount = %d'% count, '\tw:',thetaprint 'loop count = %d'% count, '\tw:',theta # check with scipy linear regressionslope, intercept, r_value, p_value,slope_std_error = stats.linregress(x, target_data)print 'intercept = %s slope = %s'% (intercept, slope) plt.plot(x, target_data, 'g*')plt.plot(x, theta[1]* x +theta[0],'r')plt.show()

运行结果:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

(责任编辑:admin)






帮助中心
会员注册
找回密码
新闻中心
快捷通道
域名登录面板
虚机登录面板
云主机登录面板
关于我们
关于我们
联系我们
联系方式

售前咨询:17830004266(重庆移动)

企业QQ:383546523

《中华人民共和国工业和信息化部》 编号:ICP备00012341号

Copyright © 2002 -2018 香港云主机 版权所有
声明:香港云主机品牌标志、品牌吉祥物均已注册商标,版权所有,窃用必究

云官方微信

在线客服

  • 企业QQ: 点击这里给我发消息
  • 技术支持:383546523

  • 公司总台电话:17830004266(重庆移动)
  • 售前咨询热线:17830004266(重庆移动)