深度学习中的卷积和反卷积(四)——卷积和反卷积的梯度
本系列已完结,全部文章地址为:
深度学习中的卷积和反卷积(一)——卷积的介绍
深度学习中的卷积和反卷积(二)——反卷积的介绍
深度学习中的卷积和反卷积(三)——卷积和反卷积的计算
深度学习中的卷积和反卷积(四)——卷积和反卷积的梯度
1 卷积的梯度计算
1.1 Tensorflow中矩阵梯度运算的说明
请注意,计算y对x的梯度时,如果y、x都是矩阵,梯度理应是每一个y对每一个x求偏导的结果。但在Tensorflow中,gradient是返回了总和的梯度。如果想求出每个分量的梯度,应该使用Jacobian矩阵。这一点困扰了笔者很久,直到翻到文档才恍然大悟。文档地址:梯度和自动微分简介 | TensorFlow Core
import tensorflow as tfx = tf.Variable(2.0)
# 求gradient,结果为7
with tf.GradientTape() as tape:y = x * [3., 4.]
print(tape.gradient(y, x).numpy())
# 求gradient,结果为[3. 4.]
with tf.GradientTape() as tape:y = x * [3., 4.]
print(tape.jacobian(y, x).numpy())
1.2 卷积对input的梯度
沿用上一篇的例子如下图:
数值例子为:
输入是3*3的维度,因此梯度维度也是3*3,表示对每一个a中的元素求梯度的结果
观察卷积输出的结果,例如,参与了
的计算,系数是
,因此梯度为
。同理,所有的y对所有的输入都可以计算梯度。以
为例:
在Tensorflow中验证如下
@tf.function
def compute_gradient(x, filters):with tf.GradientTape() as tape:tape.watch(x) # 监视xy = tf.nn.conv2d(x, filters, [1, 1, 1, 1], "VALID")return tape.jacobian(y, x) # 计算y相对于x的梯度print(compute_gradient(x, filters).numpy().reshape([4, 3, 3]))
输出如下,的输出结果与上文中表格一致,其余y分量不再赘述。
[[[1. 2. 0.][3. 4. 0.][0. 0. 0.]][[0. 1. 2.][0. 3. 4.][0. 0. 0.]][[0. 0. 0.][1. 2. 0.][3. 4. 0.]][[0. 0. 0.][0. 1. 2.][0. 3. 4.]]]
1.3 卷积对kernel的梯度
对卷积核计算的梯度,就是每一个y对每一个k求梯度,例如每一个y对于的梯度,就是下图红框中的部分,分别是1、2、4、5。
还是以为例,在Tensorflow中验证如下
@tf.function
def compute_kernel_gradient(x, filters):with tf.GradientTape() as tape:tape.watch(filters) # 监视xy = tf.nn.conv2d(x, filters, [1, 1, 1, 1], "VALID")return tape.jacobian(y, filters)print(compute_kernel_gradient(x, filters).numpy().reshape([4, 2, 2]))
输出如下,符合预期。
[[[1. 2.][4. 5.]][[2. 3.][5. 6.]][[4. 5.][7. 8.]][[5. 6.][8. 9.]]]
2 反卷积的梯度计算
由于反卷积的计算相当于对矩阵先做填充再做卷积,因此反卷积的梯度等价于对填充后的输入矩阵做卷积的梯度。
2.1 反卷积对input的梯度
以前文的数据为例,首先对输入矩阵填充0,然后翻转卷积核,得到4*4的输出。
我们计算每一个输出对每一个输入的梯度,输出是4*4,输入是3*3,因此算梯度的Jacobian矩阵维度是4*4*3*3。
我们以对
的梯度为例,先看
是怎么算出来的
因此对
的梯度为
Tensorflow中验证如下:
import numpy as np
import tensorflow as tfdef conv2d_transpose(x, filters):return tf.nn.conv2d_transpose(x, filters, [1, 4, 4, 1], strides=1, padding="VALID")@tf.function
def compute_conv2d_transpose_i_gradient(x, filters):with tf.GradientTape() as tape:tape.watch(x)y = conv2d_transpose(x, filters)return tape.jacobian(y, x)x = tf.constant(np.arange(1, 10).reshape([1, 3, 3, 1]), dtype=tf.float32)
filters = tf.constant(np.arange(1, 5).reshape(2, 2, 1, 1), dtype=tf.float32)
print(compute_conv2d_transpose_i_gradient(x, filters).numpy().reshape([4, 4, 3, 3])[2][1][1][1]) # 注意下标是从0开始的,[2][1]代表y32,[1][1]代表a22
输出为3,与手算结果一致。
3.0
2.2 反卷积对kernel的梯度
与反卷积对input梯度类似,也等价于对填充后的输入矩阵做卷积时计算梯度。同样用数值例子验证。
计算 对
的梯度,结合上节的表达式,得到梯度为
Tensorflow中验证如下:
import numpy as np
import tensorflow as tfdef conv2d_transpose(x, filters):return tf.nn.conv2d_transpose(x, filters, [1, 4, 4, 1], strides=1, padding="VALID")@tf.function
def compute_conv2d_transpose_k_gradient(x, filters):with tf.GradientTape() as tape:tape.watch(filters)y = conv2d_transpose(x, filters)return tape.jacobian(y, filters)x = tf.constant(np.arange(1, 10).reshape([1, 3, 3, 1]), dtype=tf.float32)
filters = tf.constant(np.arange(1, 5).reshape(2, 2, 1, 1), dtype=tf.float32)
print(compute_conv2d_transpose_k_gradient(x, filters).numpy().reshape([4, 4, 2, 2])[2][1][1][0])
输出为5,与手算结果一致。
5.0
3 反卷积等价于误差反向传播
https://zhuanlan.zhihu.com/p/338780702
下图是Tensorflow中反卷积函数的源码,可以看出反卷积等价于将input作为卷积下层误差反向传播,本节进行推导。
@tf_export("nn.conv2d_transpose", v1=[])
@dispatch.add_dispatch_support
def conv2d_transpose_v2(input, # pylint: disable=redefined-builtinfilters, # pylint: disable=redefined-builtinoutput_shape,strides,padding="SAME",data_format="NHWC",dilations=None,name=None):......return gen_nn_ops.conv2d_backprop_input(input_sizes=output_shape,filter=filters,out_backprop=input,strides=strides,padding=padding,explicit_paddings=explicit_paddings,data_format=data_format,dilations=dilations,name=name)
3.1 全连接网络的误差反向传播
卷积可视作特殊的全连接网络。全连接网络中每一个输出与每一个输入都使用权重边相连,输出是各输入的加权求和。对于卷积而言,输出只与某些输入有关,但可以理解为所有输出与所有输入相连,只是其中有些权重边固定为0而已。因此,本节先回顾全连接网络的误差反向传播过程,随后推广到卷积的误差反向传播。
如下图所示,我们构造了一个全连接神经网络,忽略偏置。
符号表示如下:
符号 | 含义 |
L层第i个输入。A指activation,表示L-1层激活后传递给L层的输入 | |
L层第i个输入连接到第j个输出的权重 | |
L层第i个输出 | |
L层偏置 | |
损失函数 | |
最终的误差对于L层第i个输出的梯度,表示反向传播过来的误差 |
对于L层来说,误差反向传播需要做两件事情:(1)计算误差对本层权重的梯度,从而更新权重;(2)将误差反向传播到上一层,从而更新上层的权重。
3.1.1 误差对本层权重的梯度
根据链式法则,有:
根据的定义,前一项即为
。后一项比较简单,因为Z是由W加权求和而来,因此该项等于
。在卷积中,卷积核其实就是特殊的权重,因此该项即对应前文讨论的卷积对kernel的梯度。
表示误差传播到
这个节点的误差,表示节点对于最后误差负的责任,注意这里的
是激活之前的输出。
可以继续分解为最终误差对激活后的结果A的梯度乘A对于Z的梯度,如果是最后一层,则代表损失函数的梯度。后者代表激活函数的梯度。
求出梯度后,根据神经网络的学习规则,权重根据学习率、梯度动态更新。
3.1.2 误差反向传播到上一层
本层需要求出,从而使得下一层根据此结果更新权重。以L-1层第j个输出为例
注意乘号后一项就是激活函数的导数,下面分析乘号前一项。注意L层的Aj会参与到多个输出Z,因此需要将所有输出Zi都考虑在内。
此式后一项即为卷积中对input的梯度。可进一步化简,结果为,因此损失函数对L层输入的梯度可表示为
与权重相乘后求和。
3.2 卷积的误差反向传播
误差反向传播,对应前文中“误差反向传播到上一层”这一小节。在卷积中,卷积核其实就是特殊的稀疏权重,其中有很多权重为0。
还是以前文卷积计算为例,我们列出损失函数对所有输入的梯度。代入上式,得到:
注意这里符号表示有所调整,因为全连接网络是把输入和输出展开的,卷积这里输入和输出是二维的,因此下标用二维坐标表示。同时此处只讨论第L层网络情况,不再保留上标。
可以看到由于a22参与了所有的输出,所以表达式有4项,其他输入只参与了1或2项输出,相当于对剩余输出的权重为0,因此表达式只有1、2项。
这种计算结果等价于对下式求卷积:
可以发现,这正好是反卷积的计算过程。
3.3 Tensorflow的验证
在Tensorflow中验证如下:
def conv2d_transpose(x, filters):return tf.nn.conv2d_transpose(x, filters, [1, 4, 4, 1], strides=1, padding="VALID")x = tf.constant(np.arange(1, 10).reshape([1, 3, 3, 1]), dtype=tf.float32)
filters = tf.constant(np.arange(1, 5).reshape(2, 2, 1, 1), dtype=tf.float32)
print("反卷积结果:")
print(conv2d_transpose(x, filters).numpy().reshape([4, 4]))
# 卷积反向传播
x = tf.constant(np.array([[0, 0, 0, 0, 0],[0, 1, 2, 3, 0],[0, 4, 5, 6, 0],[0, 7, 8, 9, 0],[0, 0, 0, 0, 0]]).reshape([1, 5, 5, 1]), dtype=tf.float32)
filters = tf.constant(np.array([[4, 3],[2, 1]]).reshape(2, 2, 1, 1), dtype=tf.float32)
print("卷积反向传播结果:")
print(tf.nn.conv2d(x, filters, [1, 1, 1, 1], "VALID").numpy().reshape(4, 4))
输出如下图所示,二者一致。
反卷积结果:
[[ 1. 4. 7. 6.][ 7. 23. 33. 24.][19. 53. 63. 42.][21. 52. 59. 36.]]
卷积反向传播结果:
[[ 1. 4. 7. 6.][ 7. 23. 33. 24.][19. 53. 63. 42.][21. 52. 59. 36.]]
参考资料
《卷积神经网络(CNN)反向传播算法详细解析》
《反向传播算法中的权重更新是如何进行的?》
相关文章:

深度学习中的卷积和反卷积(四)——卷积和反卷积的梯度
本系列已完结,全部文章地址为: 深度学习中的卷积和反卷积(一)——卷积的介绍 深度学习中的卷积和反卷积(二)——反卷积的介绍 深度学习中的卷积和反卷积(三)——卷积和反卷积的计算 …...

ASP.NET Core - IStartupFilter 与 IHostingStartup
ASP.NET Core - IStartupFilter 与 IHostingStartup 1. IStartupFilter2 IHostingStartup2.5.1 创建外部程序集2.5.2 激活外部程序集 1. IStartupFilter 上面讲到的方式虽然能够根据不同环境将Startup中的启动逻辑进行分离,但是有些时候我们还会可以根据应用中的功能…...

【零基础租赁实惠GPU推荐及大语言模型部署教程01】
租赁GPU推荐及大语言模型部署简易教程 1 官网地址2 注册账号及登录3 租用GPU3.1 充值(不限制充值最低金额,1元亦可)3.2 容器实例(实际就是你租用的GPU电脑)3.3 选择镜像(选择基础环境:框架版本和…...

接口传参 data格式和json格式区别是什么
接口传参 data格式和json格式区别是什么 以下是接口传参 data 格式和 JSON 格式的区别: 定义和范围 Data 格式: 是一个较为宽泛的概念,它可以指代接口传递参数时所使用的任何数据的组织形式。包括但不限于 JSON、XML、Form 数据、纯文本、二进…...

踏上 C++ 编程之旅:开篇之作
踏上 C 编程之旅:开篇之作 在计算机编程的广袤天地中,C 宛如一座巍峨的高峰,吸引着无数开发者攀登探索。今天,就让我们一同开启这段充满挑战与惊喜的 C 编程之旅,在代码的世界里开辟属于自己的道路。 一、为什么选择…...

docker在不删除容器的情况下修改端口映射
注意:必须先停止docker服务!!!! 1) 停止容器 2) 停止docker服务(systemctl stop docker) 3) 修改这个容器的hostconfig.json和config.v2.json文件中的端口 先查看容器id docker inspect jenkins 进入该目录 hostcon…...

Mysql tinyint与Java的数据类型的对应关系
参考资料 理解误区——mysql中tinyint与Java的数据类型的对应关系;tinyint(1) 与tinyint(4)的区别 1.1 tinyint字段取值 数据库字段类型为 tinyint,值为0或1,直接通过SQL语句查询的话,0会取出false;1会取出true目前就想取出的结果为 0 或 1 selectpg_id ,pg_name…...

mac intel芯片下载安卓模拟器
一、调研 目前主流两个模拟器: 雷神模拟器 不支持macosmumu模拟器pro版 不支持macos intel芯片 搜索到mumu的Q&A中有 “Intel芯片Mac如何安装MuMu?” q&a🔗:https://mumu.163.com/mac/faq/install-on-intel-mac.html 提…...

掌握 Ubuntu 终端 mv 与 rename 命令的高效重命名使用方法
在日常的计算任务中,文件重命名是一个经常性的需求。对于熟悉图形用户界面(GUI)的人来说,通过右键点击并选择“重命名”选项,这个过程简单直接。然而,当涉及到大量文件或需要自动化流程时,命令行…...

【Python】数据容器:列表,元组,字符串,集合字典及通用操作
文章目录 一.序列1.1list列表定义常用操作列表的遍历 1.2tuple元组定义常见操作元组的遍历 1.3str字符串定义常见操作字符串的遍历 1.4序列常用操作——切片 二.set集合定义常见操作集合的遍历 三.dict字典定义常用操作字典的嵌套 *数据容器对比总结四.数据容器的通用操作4.1通…...

基于Oracle与PyQt6的电子病历多模态大模型图形化查询系统编程构建
一、引言 1.1 研究背景阐述 在当今数字化时代,医疗行业正经历着深刻的变革,数字化转型的需求日益迫切。电子病历(EMR)作为医疗信息化的核心,其管理的高效性和数据利用的深度对于提升医疗服务质量、优化临床决策以及推动医学研究具有至关重要的意义。传统的电子病历管理系…...

2025智能网联汽车数据分类分级白皮书
智能网联汽车作为现代交通技术的重要成果,其核心特征之一是产生了大量的、多样化的数据,这些数据不仅对提升车辆性能和用户体验至关重要,对维护交通安全、推动智能交通系统的发展具有深远影响。在数字经济时代,数据的价值日益凸显…...

使用Dify创建个问卷调查的工作流
为啥要使用Dify创建工作流呢?一个基于流程的智能体的实现,特别是基于业务的实现,使用Dify去实现时,通常都是一个对话工作流,当设计到相对复杂一些的流程时,如果将所有逻辑都放在对话工作流中去实现…...

紫光无人机AI飞控平台介绍
随着无人机技术的迅猛发展,无人机飞控平台的智能化需求不断提升。紫光无人机AI飞控平台作为一款创新型产品,为用户提供了从飞行控制到任务管理的一站式解决方案,尤其在AI实时识别和事件分析方面具有显著优势。本文将介绍平台的核心功能、技术…...

UI自动化测试:异常截图和page_source
自动化测试过程中,是否遇到过脚本执行中途出错却不知道原因的情况?测试人员面临的不仅是问题的复现,还有对错误的快速定位和分析。而异常截图与页面源码(Page Source)的结合,正是解决这一难题的利器。 在实…...

47,【5】BUUCTF web lovesql
进入靶场 可知是单引号闭合,属于字符串型注入 则后续方法与字符串型无异 使用order by 判断出字节数为3 使用union select寻找注入点时切记第一个select为空 库名geek 表名group_concat(table_name) from information_schema.tables where table_schemageek# geek…...

网络安全——常用语及linux系统
一、网络安全概念及法规 网络安全:网络空间安全 cyber security 信息系统:由计算机硬件、网络和通信设备、计算机软件、信息资源、信息用户和规章制度组成的已处理信息流为目的的人机一体化系统 信息系统安全三要素(CIA) 保密…...

json().get() 和 json[““] 的区别
以下是 json().get() 和 json[“”] 的区别: 使用方法和语法 json[“”]: 这是使用字典的索引操作符 [] 来访问 JSON 数据。假设 json 是一个字典,你可以通过 json[“key”] 的方式来获取对应 key 的值。 示例: python import js…...

深入解析CSS属性值计算:从声明到渲染的完整流程
目录 引言1. 确定声明值2. 层叠冲突3. 使用继承4. 使用默认值总结 引言 在网页开发中,理解CSS属性值的计算过程对于开发者来说至关重要。它不仅影响页面样式的最终呈现,还涉及到浏览器如何解析和应用样式规则。本文将深入探讨从无属性值到每个属性都有…...

npm发布工具包+使用
1.初始化package包 npm init -y {"name": "common-cjs-tools","version": "1.0.0","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" &&…...

28:CAN总线入门一:CAN的基本介绍
CAN总线入门 1、CAN总线简介和硬件电路1.1、CAN简要介绍1.2、硬件电路1.3、CAN总线的电平标准 2、帧格式2.1、数据帧(掌握)2.2、遥控帧(掌握)2.3、错误帧(了解)2.4、过载帧(了解)2.5…...

RK3568平台(音频篇)lineout无声调试
一.声音硬件框架 硬件HP_MUTE已强制拉低。 二.设备树配置 es8388_sound: es8388-sound {status = "okay";compatible = "rockchip,multicodecs-card";rockchip,card-name = "rockchip-es8388";hp-det-gpio = <&gpio1 RK_PD2 GPIO_ACT…...

ros2-7.5 做一个自动巡检机器人
7.5.1 需求及设计 又到了小鱼老师带着做最佳实践项目了。需求:做一个在各个房间不断巡逻并记录图像的机器人。 到达目标点后首先通过语音播放到达目标点信息, 再通过摄像头拍摄一张图片保存到本地。 7.5.2 编写巡检控制节点 在chapt7_ws/src下新建功…...

服务器下发任务镭速利用变量实现高效的大文件传输效率
在分布式系统和自动化部署场景中,任务下发往往伴随着大量的文件传输需求。为了提高文件传输的效率,本文将介绍如何巧妙地利用变量来优化任务下发过程中的文件传输。我们将介绍几种方法,通过合理利用变量来减少传输负担、提升传输速度…...

本地用docker装mysql
目录 拉取镜像查看镜像 启动容器查看运行中的容器连接到 MySQL 容器其他一些操作 装WorkBench链接mysql——————————————允许远程登录MySql 拉取镜像 docker pull mysql查看镜像 docker image lsREPOSITORY TAG IMAGE ID CREATED SIZE mysq…...

前端canvas对象转成file对象
import html2canvas from html2canvasexport default {methods: {//canvas对象转成file对象canvasToFile() {html2canvas(this.$parent.$refs[mapPanel].$el,{width: this.$parent.$refs[mapPanel].$el.clientWidth - 600// height:}).then(canvas > {const base64Data can…...

mermaid大全(语法、流程图、时序图、甘特图、饼图、用户旅行图、类图)
⚠️ 有些网站的mermaid可能不完整,因此下面教程中可能有些语法是无效的。 😊亲测Typora软件均可以显示。 1. 介绍 Mermaid是一个基于JavaScript的图表绘制工具,它使用类似Markdown的语法来创建和修改各种类型的图表。以下是关于Mermaid的详…...

运行fastGPT 第四步 配置ONE API 添加模型
上次已经装好了所有的依赖和程序。 下面在网页中配置One API ,这个是大模型的接口。配置好了之后,就可以配置fastGPT了。 打开 OneAPI 页面 添加模型 这里要添加具体的付费模型的API接口填进来。 可以通过ip:3001访问OneAPI后台,**默认账号…...

Spring Initializr创建springboot项目 “java: 错误: 无效的源发行版:19”
我用的1.8的jdk,排查发现这是jdk和springboot版本冲突导致的。 1、File->Project Structure->Project Settings->Project,把language level改成相应的版本 2、File->Project Structure->Module,source和dependancies改成相应的版本 3、F…...

Java IDEA中Gutter Icons图标的含义
前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下"通俗易懂,风趣幽默",感觉非常有意思,忍不住分享一下给大家。 👉点击跳转到教程 前言: 很多人刚开始用IDEA来学习编程,会发现下面这些图标。 但是…...