关于梯度下降与Momentum通俗易懂的解释

2024-01-30 23:18

本文主要是介绍关于梯度下降与Momentum通俗易懂的解释,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

sgd与momentum都是常见的梯度优化方法。本文想从代码方面对这两种方法进行总结。

关于理论。建议参考:
https://www.cnblogs.com/jungel24/p/5682612.html
这篇博文写的很好。很形象。本文也是建立在它的基础上写的,同时代码参考:
https://github.com/hsmyy/zhihuzhuanlan
?。交代完毕,开始学习之旅。
之前在学习无论是ML,DL的时候,总是理论优先,很多都是知道是那么回事,但是从没想过如何用代码实现。随着学习的深入,越来越觉得越是基础的东西,越要注意。所以这篇博客就是我的一个学习方法的改进,本文会在上面代码的基础上代码总结。

我写的和原链接不同。手法方面没有那么好看,但是更容易理解,特别是momentum部分,很不一样,很适合初学者,因为没有太多的包装。也是因为我没有养成好的coding习惯导致的。。。但是正确性是可以保证的,我都亲自运行过。

1.gd

import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5,7,500)
y = (x-1)**2
#g(x)为导数
def g(x):return 2*x-2
plt.plot(x,y)

在这里插入图片描述

def gradient_descent(x0,step,epoch):x = x0for i in range(epoch):print('epoch:{},x= {},gradient={}'.format(i,x,g(x)))x-=step*g(x)if abs(g(x))<=1e-6:#注意这里别忘了取绝对值了,我一开始就忘了。return xreturn x

主体构建完毕。接下来:

gradient_descent(4,0.1,20)

初始点选为4,学习率为。0.1,迭代20次:
在这里插入图片描述
可以看到,最后已经十分接近于解析解1了,同时梯度也很接近于0.很棒。
倘若我们把学习率加大呢?

gradient_descent(4,5,20)

在这里插入图片描述
可以看到是越来越偏的。

2.momentum

为了更好的看出来sgd的问题所在,与momentum的强大之处:我们这次采用二元函数:
z=x**2 + 50*y**2。我们现在就可以假设loss function为上面的函数,x,y则为自变量,想用梯度下降法找到最优解。显然这个函数在(0,0)处有最优解,那么来看看梯度下降如何处理:
先来看看图象长什么样:

import numpy as np
import pylab as plt

f(x)就是上面的函数,

def f(x):x = np.array(x)return x[0]**2+50*x[1]**2
def g(x):x = np.array(x)tidu = np.array([2*x[0],100*x[1]])return tidu
x_plot = np.linspace(-200,200,1000)
y_plot = np.linspace(-100,100,1000)
X,Y = np.meshgrid(x_plot,y_plot)
Z = X**2+50*Y**2
plt.contour(X,Y,Z)
plt.plot(0,0,marker='*')

在这里插入图片描述
暂停下,上面的知识点:X,Y = np.meshgrid(x_plot,y_plot)
以及plt.contour(X,Y,Z)。
首先说下第二个:contour函数是画等高线图的。第一个meshgrid函数:
https://zhuanlan.zhihu.com/p/29663486
下面截图来自上面这个链接。
Meshgrid函数的一些应用场景
Meshgrid函数常用的场景有等高线绘制及机器学习中SVC超平面的绘制(二维场景下)。

Meshgrid函数的基本用法
在Numpy的官方文章里,meshgrid函数的英文描述也显得文绉绉的,理解起来有些难度。

可以这么理解,meshgrid函数用两个坐标轴上的点在平面上画网格。

用法:

[X,Y]=meshgrid(x,y)

[X,Y]=meshgrid(x)与[X,Y]=meshgrid(x,x)是等同的

[X,Y,Z]=meshgrid(x,y,z)生成三维数组,可用来计算三变量的函数和绘制三维立体图

def gd(x0,step,epoch):x = np.array(x0,dtype='float64')x_list=[]for i in range(epoch):x_list.append(x.copy())print('epoch:{},x = {},gradient={}'.format(i,x,g(x)))x-=step*g(x)if abs(sum(g(x)))<=1e-6:return xreturn x,x_list

1.x_list.append(x.copy())中的.copy是必须要加的。不加的话x_list都是同一个值。

为了不使得本文太长,关于这个的解释我放到了:
https://blog.csdn.net/ssswill/article/details/86695607

2. x = np.array(x0,dtype=‘float64’)中的floate64是必须加的。(取决于你选的初始点),当然还是建议加的。如不加:

在这里插入图片描述
因为原来初始点选的是整数点,为int32类型。之后x-=step*g(x)相当于你还要用int32来存储floate64的结果,显然放不下,报错就是这个意思。
关于这点:http://blog.51cto.com/youerning/1714455
在这里插入图片描述
在这里插入图片描述

3.关于abs(sum(g(x)))

因为g(x)导数是2个元素组成的向量,所以这里用了求和

4.关于x_list。它存储了每次梯度变化的位置坐标,用来画图的。

go on.

x,x_list = gd([100,75],0.019,50)
plt.figure(figsize=(15,7))
plt.contour(X,Y,Z)
plt.plot(0,0,marker='*')
for i in range(len(x_list)):plt.plot([x_list[i][0],x_list[i+1][0]],[x_list[i][1],x_list[i+1][1]])if i==48:break

我这里选择的初始点是(100,75),学习率为0.019,来看看效果:
在这里插入图片描述
可以看到50次之后呢,还是到不了最优点,而且x=14.多,差得远。原因很简单,x方向梯度太小了。如果增大学习率呢?这样不就行了嘛?
我这里把学习率从0.019增加到0.2.来看看:

x,x_list = gd([100,75],0.02,50)
plt.figure(figsize=(15,7))
plt.contour(X,Y,Z)
plt.plot(0,0,marker='*')
for i in range(len(x_list)):plt.plot([x_list[i][0],x_list[i+1][0]],[x_list[i][1],x_list[i+1][1]])if i==48:break

在这里插入图片描述
吃惊。变成了这个鬼样子,甚至y方向都不收敛了,而且x也只到了13.多,还是不行。而且看来学习率不能再增大了,0.019是刚好的。那咋办?我就想让它在50次内收敛,难道没办法了嘛?

momentum来了!这是重点,我自己的一些理解:我们呢再来仔细看这个问题,gd不能使用的原因就是x方向梯度太小了,每次在x方向更新速度十分缓慢。反而y方向梯度很大,不到几个回合就到0附近了,甚至还会超过去。我们能不能牺牲一下y的梯度来增强x方向的梯度呢?或者换句话说,你只要能找到一种方法把x方向的梯度增大了,那这事就成了。这样看来,事就好办了。有很多种方法都可以增大x的梯度,momentum就是其中一种。

其实momentum只在gd基础上加了一句话:

        pre_gd = mu*pre_gd+g(x)x-=step*pre_gd

我们每次坐标更新变成了这样。梯度由两部分组成:一部分是我们见过的gd的g(x),也就是该点的导数了。我们刚不是说它太小嘛。那就给他加一点东西咯。所以在这里就加了mupre_gd。mu是一个折扣系数,0.5,0.7,0.9这个样子,它是超参数,由你设置。这里的mupre_gd意思就是上一次梯度的mu倍。这样x的梯度不就增大了吗。同时y方向的梯度是被消弱了的,因为前一次y的梯度总是与这次相反。(其实这句话不对,但是在本例很多限制条件下是没问题的。)
这就达到了x梯度增大,y梯度减小的目的。
再从物理的角度来探讨:momentum就是冲量,动量的意思。先从动能说起,我们想让x方向速度变大,那么y方向速度应该减小。同时对于动量来说,我们这样做相当于不断增大x的动量,而Y方向动量是不断抵消的,大概这个意思吧。

说了那么多,来看看效果吧。

def momentum(x0,step,mu,epoch):x = np.array(x0,dtype='float64')x_list=[]pre_gd = np.array([0,0])for i in range(epoch):x_list.append(x.copy())print('epoch:{},x = {},gradient={}'.format(i,x,g(x)))pre_gd = mu*pre_gd+g(x)x-=step*pre_gdif abs(sum(g(x)))<=1e-6:return xreturn x,x_list
x,x_list = momentum([100,75],0.01,0.7,50)
plt.figure(figsize=(15,7))
plt.contour(X,Y,Z)
plt.plot(0,0,marker='*')
for i in range(len(x_list)):plt.plot([x_list[i][0],x_list[i+1][0]],[x_list[i][1],x_list[i+1][1]])if i==48:break

我这里只用了0.01的学习率。
在这里插入图片描述
很完美的。这时候为了更清楚看清momentum,我再用0.025的学习率看看如何,代码不贴出来了,和上面一样,只是改了个参数。
在这里插入图片描述
我箭头指的地方。是不是就是x的动量很大,y很小的例子。他因为这时候y方向不受力或受力很小,x方向受力较大,所以是这样子。

最后:你如果自己调这些代码时,你可以清楚地发现学习率与mu的重要性,稍微改变一点,图象就会大变。这还仅仅是一个简单的二元函数。在真实应用中,那么多参数,那么复杂的网络,调参可没那么简单。

这篇关于关于梯度下降与Momentum通俗易懂的解释的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/661868

相关文章

wolfSSL参数设置或配置项解释

1. wolfCrypt Only 解释:wolfCrypt是一个开源的、轻量级的、可移植的加密库,支持多种加密算法和协议。选择“wolfCrypt Only”意味着系统或应用将仅使用wolfCrypt库进行加密操作,而不依赖其他加密库。 2. DTLS Support 解释:DTLS(Datagram Transport Layer Security)是一种基于UDP的安全协议,提供类似于

✨机器学习笔记(二)—— 线性回归、代价函数、梯度下降

1️⃣线性回归(linear regression) f w , b ( x ) = w x + b f_{w,b}(x) = wx + b fw,b​(x)=wx+b 🎈A linear regression model predicting house prices: 如图是机器学习通过监督学习运用线性回归模型来预测房价的例子,当房屋大小为1250 f e e t 2 feet^

设计模式之工厂模式(通俗易懂--代码辅助理解【Java版】)

文章目录 1、工厂模式概述1)特点:2)主要角色:3)工作流程:4)优点5)缺点6)适用场景 2、简单工厂模式(静态工厂模式)1) 在简单工厂模式中,有三个主要角色:2) 简单工厂模式的优点包括:3) 简单工厂模式也有一些限制和考虑因素:4) 简单工厂模式适用场景:5) 简单工厂UML类图:6) 代码示例: 3、工厂方法模式1) 在工厂方法模式中,有4个主要角色:2) 工厂方法模式的工作流程

AI学习指南深度学习篇-带动量的随机梯度下降法的基本原理

AI学习指南深度学习篇——带动量的随机梯度下降法的基本原理 引言 在深度学习中,优化算法被广泛应用于训练神经网络模型。随机梯度下降法(SGD)是最常用的优化算法之一,但单独使用SGD在收敛速度和稳定性方面存在一些问题。为了应对这些挑战,动量法应运而生。本文将详细介绍动量法的原理,包括动量的概念、指数加权移动平均、参数更新等内容,最后通过实际示例展示动量如何帮助SGD在参数更新过程中平稳地前进。

嵌入式技术的核心技术有哪些?请详细列举并解释每项技术的主要功能和应用场景。

嵌入式技术的核心技术包括处理器技术、IC技术和设计/验证技术。 1. 处理器技术    通用处理器:这类处理器适用于不同类型的应用,其主要特征是存储程序和通用的数据路径,使其能够处理各种计算任务。例如,在智能家居中,通用处理器可以用于控制和管理家庭设备,如灯光、空调和安全系统。    单用途处理器:这些处理器执行特定程序,如JPEG编解码器,专门用于视频信息的压缩或解压。在数字相机中,单用途

请解释Java Web应用中的前后端分离是什么?它有哪些好处?什么是Java Web中的Servlet过滤器?它有什么作用?

请解释Java Web应用中的前后端分离是什么?它有哪些好处? Java Web应用中的前后端分离 在Java Web应用中,前后端分离是一种开发模式,它将传统Web开发中紧密耦合的前端(用户界面)和后端(服务器端逻辑)代码进行分离,使得它们能够独立开发、测试、部署和维护。在这种模式下,前端通常通过HTTP请求与后端进行数据交换,后端则负责业务逻辑处理、数据库交互以及向前端提供RESTful

OpenStack:Glance共享与上传、Nova操作选项解释、Cinder操作技巧

目录 Glance member task Nova lock shelve rescue Cinder manage local-attach transfer backup-export 总结 原作者:int32bit,参考内容 从2013年开始折腾OpenStack也有好几年的时间了。在使用过程中,我发现有很多很有用的操作,但是却很少被提及。这里我暂不直接

OpenStack实例操作选项解释:启动和停止instance实例

关于启动和停止OpenStack实例 如果你想要启动和停止OpenStack实例时,有四种方法可以考虑。 管理员可以暂停、挂起、搁置、停止OpenStack 的计算实例。但是这些方法之间有什么不同之处? 目录 关于启动和停止OpenStack实例1.暂停和取消暂停实例2.挂起和恢复实例3.搁置(废弃)实例和取消废弃实例4.停止(删除)实例 1.暂停和取消暂停实例

Zuul详细解释

Zuul 是 Netflix 开源的 API 网关,广泛用于微服务架构中。它作为系统的前置网关,主要功能包括路由、负载均衡、限流、安全性管理等。Zuul 最常见的应用场景是作为反向代理,它接收所有来自客户端的请求,并将请求转发给后端的微服务,从而屏蔽了微服务的复杂性。Spring Cloud 集成了 Zuul,使其成为 Spring Cloud 微服务生态系统中的一个重要组件。 为什么使用 Zu

AI学习指南深度学习篇-带动量的随机梯度下降法简介

AI学习指南深度学习篇 - 带动量的随机梯度下降法简介 引言 在深度学习的广阔领域中,优化算法扮演着至关重要的角色。它们不仅决定了模型训练的效率,还直接影响到模型的最终表现之一。随着神经网络模型的不断深化和复杂化,传统的优化算法在许多领域逐渐暴露出其不足之处。带动量的随机梯度下降法(Momentum SGD)应运而生,并被广泛应用于各类深度学习模型中。 在本篇文章中,我们将深入探讨带动量的随