【深度学习】3-3 神经网络的学习- 导数梯度

news2024/11/26 23:24:32

导数

导数就是表示某个瞬间的变化量,式子如下:
在这里插入图片描述

式子的左边,表示f(x)关于x的导数,即f(x)相对于x的变化程度。式子表示的导数的含义是,x的“微小变化”将导致函数f(x)的值在多大程度上发生变化其中,表示微小变化h无限趋近0
下面使用程序来实现上面的例子

def numerical_diff(f,x):
	h = 10e - 50
	return (f(x+h) - f(x))/h

这个函数有两个参数,即“函数f”和“传给函数f的参数x”
上面的函数乍一看没什么问题,但是实际上这段代码有两个需要改进的地方

  1. h使用了10e-50这个微小值。但是,这样反而产生了舍入误差(rounding error)。所谓舍人误差,是指因省略小数的精细部分的数值(比如小数点后第8位以后的数值)而造成最终的计算结果上的误差。如果用float32类型(32位的浮点数)来表示10e-50,就会变成0.0,无法正确表示出来。因此需要将微小值h改为。使用0.0001就可以得到正确的结果。
  2. 第二个要改进的地方与函数f的差分有关。上述实现中计算了函数f在x+h和x之间的差分,但这个计算有误差,因为“真的导数”对应函数在x处的斜率(称为切线),但上述实现中计算的导数对应的是(x+h)和x之间的斜率。这个差异出现是因为h不可能无限接近0。为了减少这个误差,可以以x为中心,计算它左右两边的差分,所以也称为中心差分。(x + h)和x之间的差分称前向差分

在这里插入图片描述

看下面是改进的代码:

def numerical_diff(f,x):
	h = 1e-4  #0.001
	return (f(x+h) - f(x-h))/ 2*h

利用微小的差分求导数的过程称为数值微分(numerical differentiation)
基于数学式的推导求导数的过程,称为“解析性求解”或者“解析性求导
解析性求导得到的导数是不含误差的“真的导数”。

偏导数
有多个变量的函数的导数称为偏导数
例如这个例子:
在这里插入图片描述

这个式子可以用Python来实现,如下所示

def function_2(x):
	return x[0]**2 + x[1]**2
	# 或者 return np.sum(x**2)

这里,假定想参数输入了一个NumPy数组,函数的内部实现比较简单,先计算 NumPy 数组中各个元素的平方,再求它们的和。下面是这个函数的图像:
在这里插入图片描述

求这个式子的导数,这里需要注意的是,这个式子有两个变量,所以有必要区分对哪个变量求导数。

求x0=3,x1=4时,关于x0的偏导数

>>>def function tmp1(x0):
... return x0*x0+4.0**2.0
...
>>> numerical_diff(function_tmp1, 3.0)

结果:600000000000378

求x0=3,x1=4时,关于x1的偏导数

>>>def function tmp1(x0):
... return 3.0**2.0+x1*x1
...
>>> numerical_diff(function_tmp2, 4.0)

结果:7.999999999999119

这里的结果和解析解的导数基本一致。
像这样,偏导数和单变量的导数一样,都是求某个地方的斜率
偏导数需要将多个变量中的某一个变量定为目标变量,并将其他变量固定为某个值。

梯度

由全部变量的偏导数汇总而成的向量称为梯度(gradient)。
梯度可以像下面这样来实现

def numerical_gradient(f,x):
	h = 1e - 4
	grad = np.zeros_like(x)

	for idx in range(x.size):
		tmp_val = x[idx]
		# f(x+h)的计算
		x[idx] = tmp_val + h
		fxh1 = f(x)

		# f(x-h)的计算
		x[idx] = tmp_val - h
		fxh2 = f(x)

		grad[idx] = (fxh1 - fxh2) /(2*h)
		x[idx] = tmp_val # 还原值
	return grad

在该函数中,参数f为函数,x为NumPy数组
然后用这个方法来求点(3,4)、(0,2)、(3,0)处的梯度
可以得到:
点(3,4)处的梯度是(6,8),点(0.2)处的梯度是(0,4),点(3,0)处的梯度是(6,0)。
如果把函数的所有梯度(元素值为负梯度)都显示出来会发现梯度指向函数的“最低处”(最小值)。然而并不是任何时候梯度都会指向最低处,实际上,梯度会指向各点处的函数值降低的方向。更严格地讲,梯度指示的方是各点处的函数值减小最多的方向

梯度法
神经网络也必须在学习时找到最优参数(权重和偏置)。这里所说的最优参数是指损失函数取最小值时的参数,这里通过巧妙地使用梯度来寻找函数最小值(或者尽可能小的值)的方法就是梯度法。

这里需要注意的是,梯度表示的是各点处的函数值减小最多的方向。因此,无法保证梯度所指的方向就是函数的最小值或者真正应该前进的方向。实际上,在复杂的函数中,梯度指示的方向基本上都不是函数值最小处

函数的极小值、最小值以及被称为鞍点(saddle point)的地方,梯度为0。鞍点是从某个方向上看是极大值,从另一个方向上看则是极小值的点。虽然梯度法是要寻找梯度为0的地方,但是那个地方不一定就是最小值(也有可能是极小值或者鞍点)。(梯度为0的地方,不一定就是最小值)

此外,当函数很复杂且呈扁平状时,学习可能会进入一个(几乎)平坦的地区,陷入被称为“学习高原”的无法前进的停滞期。

虽然梯度的方向并不一定指向最小值,但沿着它的方向能够最大限度地减小函数的值。因此,在寻找函数的最小值(或者尽可能小的值)的位置的任务中,要以梯度的信息为线索,决定前进的方向
(要以梯度为学习的前进方向)
通过不断地沿梯度方向前进,逐渐减小函数值的过程就是梯度法

下面用数学式来表示梯度法,如下所示:
在这里插入图片描述
其中n表示更新量,在神经网络的学习中,称为学习率。学习率决定在一次学习中,应该学习多少,以及在多大程度上更新参数
学习率需要事先确定为某个值,比如0.01或0.001。一般而言,这个过大或过小,都无法抵达一个“好的位置”。在神经网络的学习中,一般会边改变学习率的值,一边确认学习是否正确进行了。
学习率过大的话,会发散成一个很大的值;反过来,学习率过小的话,基本上没怎么更新就结束了。
像学习率这样的参数称为超参数,超参数需要尝试多个值,以便找到一种可以使学习顺进行的设定。

下面用Python来实现梯度下降法。

def gradient_descent(f,init_x,lr=0.01,step_num=100):
	x=init_x
	for i in range(step_num):
		grad = numerical_gradient(f,x)
		x -= lr*grad
	return x

init_x是初始值,lr是学习率learnirate,step_num是梯度法的重复次数
使用这个函数可以求函数的极小值,顺利的话,还可以求函数的最小值。

神经网络的梯度
神经网络的梯度是指损失函数关于权重参数的梯度。
比如,有一个只有一个形状为2 x 3的权重 W的神经网络,损失函数用L表示。此时,梯度可以用请添加图片描述表示

用数学式表示的话,如下所
在这里插入图片描述

请添加图片描述的元素由各个元素关于W的偏导数构成。比如,第1行第1列的元素请添加图片描述表示当W11稍微变化时,损失函数L会发生多大变化。这里要注意的是形状要和W相同

下面,我们以一个简单的神经网络为例,来实现求梯度的代码。

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录中的文件而进行的设定
import numpy as np
from common.functions import softmax, cross_entropy_error
from common.gradient import numerical_gradient


class simpleNet:
    def __init__(self):
    	# 实例变量, 形状为2x3的权重参数
        self.W = np.random.randn(2,3) # 用高斯分布进行初始化

	# 用于预测
    def predict(self, x):
        return np.dot(x, self.W)

	# 求损失函数值,这里参数x接收输人数据,t接收正确解标签
    def loss(self, x, t):
        z = self.predict(x)
        y = softmax(z)
        loss = cross_entropy_error(y, t)

        return loss

x = np.array([0.6, 0.9])
t = np.array([0, 0, 1])

net = simpleNet()

# Python中如果定义的是简单的函数,可以使用lambda表示法
# 对应的方法其实是
# def f(W):
#	return net.loss(x,t)
# 这里面参数W是一个伪参数,因为numerical_gradient会在内部执行f(x),为了与之兼容定义f(W)

f = lambda w: net.loss(x, t)

# 使用numerical_gradient求梯度
# net.W 权重参数
dW = numerical_gradient(f, net.W)

print(dW)

求出神经网络的梯度后,接下来只需根据梯度法,更新权重参数即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/665385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI绘画是什么?怎样提高AI绘画技巧

大家好,我是权知星球,今天跟大家探讨一下AI绘画是什么?怎样才能提高AI绘画技巧的问题。 随着人工智能技术的迅速发展,AI绘画已成为一项具有前瞻性的技术。在过去几年中,涌现出了许多功能强大的人工智能绘画工具&#x…

荣耀加冕!数据猿斩获三项大奖,彰显技术媒体硬实力!

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 6月15日及6月16日,由数央网、数央公益联合国内众多媒体共同举办的2023国际绿色零碳节暨ESG领袖峰会、2023国际智造节暨硬科技峰会在北京举行。 该峰会旨在倡导全社会关注气候变化问题,积极采取行动&a…

TBarCode SDK:条码生成:11.15.1 Crack

TBarCode SDK:条码生成软件 TBarCode SDK 提供给 Microsoft Office 用户 和软件开发人员 条码打印。用这种 条码生成软件 您可以优良的品质的创建和打印所有用于工业和商业的 条码符号 。 最好的条码生成软件 TBarCode SDK 表示一个公知的集条形码创建组件集. 优秀…

Python爬虫需要那些步骤 ?

Python爬虫是一种自动化程序,可以通过网络爬取网页上的数据。Python爬虫可以用于各种用途,例如数据挖掘、搜索引擎优化、市场研究等。Python爬虫通常使用第三方库,例如BeautifulSoup、Scrapy、Requests等,这些库可以帮助开发者轻松…

Python面向对象编程2-面向过程的银行账号模拟程序 项目2.1 创建账号与存款

项目总目标:用面向过程思想设计一个简单的银行账号模拟程序。本次将迭代多个程序版本,每个版本都将添加更多功能。虽然这些程序没有达到发布的质量标准,但整个项目的目的是关注于代码如何与一个或多个银行账户的数据进行交互。 分析项目的必要…

<Linux> 基础IO

文章目录 文件操作基本概念当前路径文件打开方式"a""w""r" 文件描述符文件描述符fd是啥1. 为什么fd是从3开始,0,1,2呢?2. fd为什么是0,1,2,3,4&#…

Mockito单元测试基本使用

文章目录 1.为什么需要Mock2.Mockito 中常用方法2.1 Mock 方法2.2 对 Mock 出来的对象进行行为验证和Junit结果断言2.3 测试桩stub2.4 参数匹配器2.5 mock()与spy()2.6 InjectMocks 本文参考: 【码农教程】手把手教你Mockito的使用 - 掘金 (juejin.cn) java - doRet…

利用SD的插件从文本或者图片创建3D模型

利用SD的插件从文本或者图片创建3D模型 一个用于自动从文本或图像生成3D模型的稳定扩散WebUI的自定义扩展。 利用 OpenAl Shap-E 从文本或图像生成 3D 模型, GitHub项日地址: https://github.com/jtydhr88/sd-webui-txt-img-to-3d-model 安装步骤: 在扩展中心选…

Linux之LVM模式下LV和VG扩容

一、LVM简介 LVM (Logical Volume Manager) 是一个逻辑卷管理器,它允许用户将多个硬盘分区或者整个硬盘组成一个或多个逻辑卷。LVM 可以在运行时动态地改变逻辑卷的大小,而不需要关机或重新启动系统。它也可以将多个硬盘的存储空间组合在一起&#xff0c…

OpenGL视口学习

VC6新建一个openGL类型项目; 出现一些选项,默认后生成一个项目; VC6自带GL支持; 需要添加附加包含路径; 而后构建工程;运行如下; 是一个旋转的立方体; 生成的代码不是MFC的&#xff…

Python入门教程+项目实战-13.4节-程序实战-二分查找算法

目录 13.4.1 何为二分查找? 13.4.2 算法实现 13.4.3 系统学习python 13.4.1 何为二分查找? 我们已经学完了Python中的字典和集合,利用字典和集合就可以实现快速查找,非常方便。字典与集合使用了哈希表的索引结构来加快查找&am…

C++ 设计模式----“对象创建“模式

“对象创建”模式  通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。  典型模式 • Factory Method •…

【Java】Java核心要点总结 68

文章目录 1. 为什么重写 equals() 时候必须重写 hashCode()2. 字符串常量池3. 字符串中的 intern() 方法4. try-catch-finally5. finally 中的代码不一定会执行 1. 为什么重写 equals() 时候必须重写 hashCode() 因为两个相等的对象的 hashCode 值必须是相等。也就是说如果 equ…

三、动画 -变形transform

目录: 1.变形transform定义 2.具体描述 3.用途 4.练习 一、变形transform定义 变形就是指通过CSS来改变元素的形状或位置 变形不会影响到页面的布局transform 用来设置元素的变形效果设置具体的值用translate()函数 二、具体描述 - 平移:translateX() 沿…

2023 3de实时仿真环境下资源不可见或没有了(只有floor)

F3退出实时仿真环境,双击结构树父节点 之后再进入实时仿真,3d仿真,再打开资源就可以看到了。

【雕爷学编程】Arduino动手做(117)---P10V706LED屏模组

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&am…

【Atlas 200DK A2体验】Atlas 200DK A2初体验记录

开箱照 烧录镜像 Windows版制卡工具下载地址: https://ascend-repo.obs.cn-east-2.myhuaweicloud.com/Atlas%20200I%20DK%20A2/DevKit/tools/latest/Ascend-devkit-imager_latest_win-x86_64.exe 准备一张MicroSD卡,个人建议容量至少在64GB以上 一键制…

6 月份有哪些 GitHub 项目火了?

本期推荐开源项目目录: 1. 谁在招人? 2. ChatGPT-Midjourney 3. 让 AI 给你写代码 4. 免费的 OpenAI GPT-4 的 API 5. 金融领域的大模型 6. 文本生成音乐模型 01 谁在招人? 阮一峰在 GitHub 上维护了一个《科技爱好者周刊》,每周五…

开源的可视化爬虫易采集EasySpider:如何无代码可视化的爬取需要登录才能爬的网站

一个可视化爬虫软件,可以使用图形化界面,无代码可视化的设计和执行爬虫任务。只需要在网页上选择自己想要爬的内容并根据提示框操作即可完成爬虫设计和执行。同时软件还可以单独以命令行的方式进行执行,从而可以很方便的嵌入到其他系统中。 …

AI导师、AI提示工程师 # Earth实现任意角色设定

‍‍ 如何通过学习优秀的开源项目, 设定一个任意角色 opus 嗨,Shadow,我想学习如何给ChatGPT设定一个角色,可以教我吗? 当然可以,我们可以通过学习优秀的开源项目来了解实现细节。 shadow 其中,…