【剑指offer】反向传播

这篇具有很好参考价值的文章主要介绍了【剑指offer】反向传播。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

BN层详解
梯度消失和梯度爆炸
交叉熵损失函数
1*1卷积的作用


原文地址:反向传播


什么是反向传播

深度学习中的反向传播(Backpropagation)是一种基于梯度下降法的优化方法,用于计算神经网络中每个参数的梯度值,以便利用梯度下降法或其他优化方法来更新参数,从而最小化损失函数。

反向传播的基本思想是通过链式法则计算整个神经网络中每个参数对损失函数的贡献,以便利用梯度下降法来更新参数。具体来说,反向传播算法从输出层开始,将输出误差反向传播到隐藏层和输入层,计算每个神经元的误差和梯度,并使用梯度下降法来更新参数。反向传播算法的关键在于计算每个神经元的误差和梯度,这可以通过链式法则来实现。

在深度学习中,反向传播是一种非常重要的优化方法,可以用于训练各种类型的神经网络,包括卷积神经网络、循环神经网络和自编码器等。反向传播算法的优化和改进也一直是深度学习研究的热点之一。

反向传播的过程

反向传播是深度学习中最基本的优化方法之一,用于计算神经网络中每个参数的梯度值,以便利用梯度下降法或其他优化方法来更新参数,从而最小化损失函数。反向传播的过程可以分为以下几个步骤:

假设我们有一个多层前馈神经网络,其中包含输入层、若干个隐藏层和输出层,每个神经元都有权重和偏差。我们的目标是最小化损失函数。

  1. 前向传播:将输入数据输入到网络中,通过神经网络的前向传播计算出每个神经元的输出结果,直到输出层输出最终的结果。
  2. 计算损失函数:将神经网络输出的结果与真实标签进行比较,计算出损失函数的值。
  3. 反向传播误差:从输出层开始,计算每个神经元的误差,然后向前计算每个神经元的误差,直到计算出输入层每个神经元的误差。具体来说,我们首先计算输出层的误差,然后反向传播到前一层隐藏层,计算隐藏层的误差,并将误差反向传播到更早的层,直到计算出输入层的误差。这个过程可以使用链式法则来计算。
  4. 计算梯度:根据误差计算每个神经元的梯度,即损失函数对每个神经元权重和偏差的偏导数。
  5. 更新参数:使用梯度下降法或其他优化方法来更新每个神经元的权重和偏差,使得损失函数的值最小化。

重复上述步骤,直到达到收敛条件或达到预设的训练次数。通过反向传播算法,神经网络可以根据给定的输入和输出数据进行训练,并逐步优化网络参数,从而得到更准确的预测结果。

部分过程详解

(1)前向传播

前向传播是计算神经网络输出的过程。在前向传播中,输入信号通过神经网络的所有层,最终得到输出信号。这个过程可以看作是一个函数的计算过程,函数的输入是神经网络的输入数据,输出是神经网络的输出数据。在计算神经网络的输出时,需要使用神经元的权重和偏置值进行计算。
具体来说,前向传播的过程如下:

  1. 将输入数据传递给输入层的神经元。
  2. 计算输入层神经元的输出,即将输入数据乘以神经元的权重,再加上神经元的偏置值,最后使用激活函数进行非线性变换。这样可以得到输入层的输出信号。
  3. 将输入层的输出信号传递给下一层的神经元。
  4. 重复步骤2和3,直到所有层的神经元都计算完毕,得到神经网络的输出信号。
  5. 将输出信号与真实的标签进行比较,计算损失函数的值。

将损失函数的值作为反向传播的起点,使用链式法则计算每个神经元的梯度,以便进一步更新神经元的权重和偏置值。
在前向传播中,每个神经元都扮演着一个函数的角色,将输入信号转换为输出信号。这些函数的参数是神经元的权重和偏置值。因此,在反向传播中,需要计算每个神经元函数的梯度,以便更新神经元的参数,以最小化损失函数。

(2)计算梯度和更新参数

反向传播算法中的计算梯度和更新参数部分是整个算法的核心。在前向传播过程中,神经元的输出由输入和参数共同决定。在反向传播过程中,需要计算损失函数对每个参数的偏导数,以确定梯度方向。然后,使用梯度下降法或其他优化方法来更新参数,以最小化损失函数。

反向传播算法的计算梯度和更新参数部分可以分为以下步骤:

  1. 计算输出层神经元的梯度。输出层神经元的梯度可以通过损失函数的导数和激活函数的导数来计算。具体来说,输出层神经元的梯度等于损失函数对神经元输出的偏导数乘以激活函数对神经元加权和的偏导数。
  2. 计算隐藏层神经元的梯度。隐藏层神经元的梯度可以通过链式法则来计算。具体来说,隐藏层神经元的梯度等于该神经元输出对下一层神经元加权和的偏导数乘以下一层神经元梯度对该神经元输出的偏导数。
  3. 计算参数的梯度。对于每个参数,需要计算损失函数对该参数的偏导数。具体来说,对于权重矩阵中的每个元素,需要计算损失函数对该元素的偏导数。对于偏置向量中的每个元素,需要计算损失函数对该元素的偏导数。
  4. 更新参数。使用梯度下降法或其他优化方法来更新参数。具体来说,对于权重矩阵中的每个元素,需要将该元素减去学习率乘以该元素的梯度。对于偏置向量中的每个元素,需要将该元素减去学习率乘以该元素的梯度。
    (具体地,可以使用随机梯度下降法(SGD)等优化算法来更新参数,公式如下: w = w - learning_rate * dw b = b - learning_rate * db 其中,w和b分别表示神经元的权重和偏置,dw和db分别表示相应的梯度,learning_rate表示学习率,用于控制参数更新的步长。)
  5. 重复步骤1到4,直到达到停止条件。

在实现反向传播算法时,需要注意梯度消失和梯度爆炸的问题。梯度消失和梯度爆炸可能会导致算法无法更新参数,从而影响模型的训练效果。为了解决这个问题,可以使用一些技巧,例如梯度裁剪、权重初始化和正则化等方法。其中,梯度裁剪可以防止梯度爆炸,即限制梯度的最大值,以避免梯度过大。权重初始化可以使神经元的输出均匀分布,从而避免梯度消失。正则化可以通过限制参数的大小来避免过拟合,从而提高模型的泛化能力。也可以参考系列文章:梯度消失和梯度爆炸

总之,在反向传播算法中,计算梯度和更新参数是非常重要的步骤。通过计算参数的梯度,并使用梯度下降法或其他优化方法来更新参数,可以最小化损失函数,从而提高模型的准确性。而为了处理梯度消失和梯度爆炸的问题,需要使用一些技巧来优化算法。

代码理解

以下是一个简单的Python代码示例,用于说明反向传播过程的实现:

假设我们有一个三层神经网络,包含一个输入层、一个隐藏层和一个输出层,其中输入层有两个神经元,隐藏层有三个神经元,输出层有一个神经元。我们使用sigmoid作为激活函数,并使用均方误差作为损失函数。文章来源地址https://www.toymoban.com/news/detail-416405.html

import numpy as np


# 激活函数sigmoid
def sigmoid(x):
	return 1 / (1 + np.exp(-x))


# 损失函数均方误差
def mse_loss(y_true, y_pred):
	return np.mean(np.square(y_true - y_pred))


# 前向传播
def forward_propagation(X, W1, b1, W2, b2):
	hidden_layer_output = sigmoid(np.dot(X, W1) + b1)
	y_pred = sigmoid(np.dot(hidden_layer_output, W2) + b2)
	return hidden_layer_output, y_pred


# 反向传播
def backward_propagation(X, y_true, hidden_layer_output, y_pred, W1, b1, W2, b2):
	# 计算输出层误差
	output_error = y_pred - y_true
	output_delta = output_error * y_pred * (1 - y_pred)

	# 计算隐藏层误差
	hidden_error = np.dot(output_delta, W2.T)
	hidden_delta = hidden_error * hidden_layer_output * (1 - hidden_layer_output)

	# 计算梯度
	dW2 = np.dot(hidden_layer_output.T, output_delta)
	db2 = np.sum(output_delta, axis=0, keepdims=True)
	dW1 = np.dot(X.T, hidden_delta)
	db1 = np.sum(hidden_delta, axis=0, keepdims=True)

	return dW1, db1, dW2, db2


# 训练模型
def train(X, y_true, hidden_units, epochs, learning_rate):
	# 初始化参数
	input_units = X.shape[1]
	output_units = y_true.shape[1]
	W1 = np.random.randn(input_units, hidden_units)
	b1 = np.zeros((1, hidden_units))
	W2 = np.random.randn(hidden_units, output_units)
	b2 = np.zeros((1, output_units))

	# 迭代训练
	for i in range(epochs):
		# 前向传播
		hidden_layer_output, y_pred = forward_propagation(X, W1, b1, W2, b2)

		# 计算损失函数
		loss = mse_loss(y_true, y_pred)

		# 反向传播
		dW1, db1, dW2, db2 = backward_propagation(X, y_true, hidden_layer_output, y_pred, W1, b1, W2, b2)

		# 更新参数
		W1 -= learning_rate * dW1
		b1 -= learning_rate * db1
		W2 -= learning_rate * dW2
		b2 -= learning_rate * db2

		# 打印损失函数
		if i % 1000 == 0:
			print("Epoch %d: loss = %f" % (i, loss))

	# 返回训练好的模型参数
	return W1, b1, W2, b2


X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y_true = np.array([[0], [1], [1], [0]])
W1, b1, W2, b2 = train(X, y_true, hidden_units=3, epochs=10000, learning_rate=0.1)
_, y_pred = forward_propagation(X, W1, b1, W2, b2)
print("Predictions: \n", y_pred)

到了这里,关于【剑指offer】反向传播的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【LeetCode-中等】剑指 Offer 31. 栈的压入、弹出序列(详解)

    输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。 示例

    2024年02月13日
    浏览(43)
  • 【LeetCode-中等】剑指 Offer 67. 把字符串转换成整数(详解)

    写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续

    2024年02月15日
    浏览(52)
  • 微服务系列文章之 Nginx反向代理

    Nginx反向代理模块的指令是由 ngx_http_proxy_module 模块进行解析,该模块在安装Nginx的时候已经自己加装到Nginx中了,接下来我们把反向代理中的常用指令一一介绍下: 该指令用来设置被代理服务器地址,可以是主机名称、IP地址加端口号形式。 语法 proxy_pass URL; 默认值 — 位置

    2024年02月16日
    浏览(36)
  • 手搓GPT系列之 - 通过理解LSTM的反向传播过程,理解LSTM解决梯度消失的原理 - 逐条解释LSTM创始论文全部推导公式,配超多图帮助理解(下篇)

    本文承接上篇上篇在此和中篇中篇在此,继续就Sepp Hochreiter 1997年的开山大作 Long Short-term Memory 中APPENDIX A.1和A.2所载的数学推导过程进行详细解读。希望可以帮助大家理解了这个推导过程,进而能顺利理解为什么那几个门的设置可以解决RNN里的梯度消失和梯度爆炸的问题。中

    2024年02月16日
    浏览(60)
  • 手搓GPT系列之 - 通过理解LSTM的反向传播过程,理解LSTM解决梯度消失的原理 - 逐条解释LSTM创始论文全部推导公式,配超多图帮助理解(中篇)

    近期因俗事缠身,《通过理解LSTM的反向传播过程,理解LSTM解决梯度消失的原理 - 逐条解释LSTM创始论文全部推导公式,配超多图帮助理解》的中下篇鸽了实在太久有些不好意思了。为了避免烂尾,还是抽时间补上(上篇在此)。本文承接上篇,继续就Sepp Hochreiter 1997年的开山

    2024年02月11日
    浏览(52)
  • vscode 系列文章目录 - ctrl+鼠标左键无效

    vscode 中有时会遇到 “Alt + 鼠标点击” 有效,但 “Ctrl + 鼠标点击” 无效,这时可以通过 Ctrl + , 进行系统配置。 进入VScode的首选项,选择设置(快捷键 Ctrl + , ),输入Go to definition,找到如下两个设置。 Editor: Multi Cursor Modifier 设置成 alt “editor.gotoLocation.multipleDefinitions” 设置

    2024年04月23日
    浏览(54)
  • 【vim 学习系列文章 5 - cscope 过滤掉某些目录】

    上篇文章:【vim 学习系列文章 4 - vim与系统剪切板之间的交互】 下篇文章:【vim 学习系列文章 6 – vim 如何从上次退出的位置打开文件】 第一步 创建自己的 cscope 脚本 ~/.local/bin/cscope.sh ,如下: 我的这个脚本首先去区分当前执行 cscope 命令的目录是 rt-thread 目录还是 linux 目

    2024年02月12日
    浏览(84)
  • Git系列文章目录 - Git 子模块git submodule使用

    项目中有时会遇到会涉及子模块的使用,比如 flatpak 项目包含多个子模块。 进入需要添加子模块的目录,一般是项目根目录。 删除子模块目录及源码: 删除项目目录下.gitmodules文件中子模块相关条目: 删除配置项中子模块相关条目: 删除模块下的子模块目录: 清除子模块

    2024年01月20日
    浏览(66)
  • pytorch 前向传播与反向传播代码+ fp16

    optim.zero_grad() : 将模型的梯度参数设置为0,即清空之前计算的梯度值,在训练模型过程中,每次模型反向传播完成后,梯度都会累加到之前的梯度值上,如果不清空,这些过时的梯度将会影响下一次迭代的结果。因此,使用 optim.zero_grad() 来清空梯度避免这种情况的发生。保证

    2024年02月05日
    浏览(45)
  • 力扣 [344、541、剑指offer 05.、151、剑指offer58-ll]

    双指针:自己的 双指针,左指针指向开头,右指针指向末尾。 交换两个左右指针。 左右指针向中间移动。 时间复杂度:O(n); 空间复杂度:O(1); 实现代码: 分类讨论:自己的 分类讨论: 如果剩余字符少于k个,则将剩余字符全部反转。 如果剩余字符大于或等于k个,则反

    2024年02月15日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包