python实现梯度下降算法

 更新时间:2020年03月24日 11:51:19   作者:huahuazhu  
这篇文章主要为大家详细介绍了python实现梯度下降算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

本文主要以线性回归算法损失函数求极小值来说明如何使用梯度下降算法并给出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-8
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
 
# 构造训练数据
x = np.arange(0., 10., 0.2)
m = len(x) # 训练数据点数目
print m
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)
 
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:',theta
print 'loop count = %d' % count, '\tw:',theta
 
# check with scipy linear regression
slope, 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-8
import numpy as np
from scipy import stats
import 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 = theta
print 'loop count = %d' % count, '\tw:',theta
 
 
# check with scipy linear regression
slope, 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-8
import numpy as np
from scipy importstats
import matplotlib.pyplot as plt
 
# 构造训练数据
x = np.arange(0.,10.,0.2)
m = len(x) # 训练数据点数目
print m
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)
 
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:',theta
print 'loop count = %d'% count, '\tw:',theta
 
# check with scipy linear regression
slope, 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()

运行结果:

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

相关文章

  • Python使用asyncio包处理并发的实现代码

    Python使用asyncio包处理并发的实现代码

    这篇文章主要介绍了Python使用asyncio包处理并发,asyncio包使用事件循环驱动的协程实现并发,本文通过实例代码给大家介绍的非常详细对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • Python 深入了解opencv图像分割算法

    Python 深入了解opencv图像分割算法

    本文主要介绍了Python通过opencv实现图像分割的详细过程与代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11
  • python解析模块(ConfigParser)使用方法

    python解析模块(ConfigParser)使用方法

    很多软件都有配置文件,今天介绍一下python ConfigParser模块解析配置文件的使用方法
    2013-12-12
  • Python中数组,列表:冒号的灵活用法介绍(np数组,列表倒序)

    Python中数组,列表:冒号的灵活用法介绍(np数组,列表倒序)

    下面小编就为大家分享一篇Python中数组,列表:冒号的灵活用法介绍(np数组,列表倒序),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-04-04
  • 使用Python模拟操作windows应用窗口详解

    使用Python模拟操作windows应用窗口详解

    在日常工作中,我们经常遇到需要进行大量重复性任务的情况,这篇文章将介绍如何使用 Python 模拟操作记事本,感兴趣的小伙伴可以了解下
    2025-02-02
  • python语言线程标准库threading.local解读总结

    python语言线程标准库threading.local解读总结

    在本篇文章里我们给各位整理了一篇关于python threading.local源码解读的相关文章知识点,有需要的朋友们可以学习下。
    2019-11-11
  • 基于Python实现蒙特卡洛法计算圆周率π

    基于Python实现蒙特卡洛法计算圆周率π

    蒙特卡罗法也称统计模拟法、统计试验法,是把概率现象作为研究对象的数值模拟方法,是按抽样调查法求取统计值来推定未知特性量的计算方法,本文我们将介绍如何使用Python来实现蒙特卡洛法计算圆周率π,感兴趣的朋友可以参考下
    2023-06-06
  • Python监测屏幕界面内容变化并发送通知方法详解

    Python监测屏幕界面内容变化并发送通知方法详解

    这篇文章主要为大家介绍了Python监测屏幕界面内容变化并发送通知,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 在pycharm中实现删除bookmark

    在pycharm中实现删除bookmark

    今天小编就为大家分享一篇在pycharm中实现删除bookmark,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-02-02
  • Python反爬实战掌握酷狗音乐排行榜加密规则

    Python反爬实战掌握酷狗音乐排行榜加密规则

    最新的酷狗音乐反爬来袭,本文介绍如何利用Python掌握酷狗排行榜加密规则,本章内容只限学习,切勿用作其他用途!!!!! 有需要的朋友可以借鉴参考下
    2021-10-10

最新评论