深度学习(斋藤康毅)学习笔记(六)反向传播3

上一篇文章介绍了反向传播的自动化,但也存在一些问题,本章用于说明这些问题,并修改原有框架,使其支持复杂计算图的运行:

问题一:重复使用一个变量,梯度不会累计

也就是说,反向传播时gx=[1,1],f.inputs=[x,x],在循环中第二次赋值把第一次赋的值给覆盖了。

如何解决

问题二:重复计算导数,梯度不会自动清零

第一次计算,x的导数是2,第二次计算x的导数是3。但是两次的导数值累加了。

设置x.cleargrad() 手动清空梯度

问题三:不支持复杂计算图

循环funs中的函数
0(初始化)[D]
1[B,C]
2[B,A]
3[B]
4[A]
5[ ]

如何解决

代码验证

完整代码

import numpy as np

class Variable:
    def __init__(self, data):
        if data is not None:
            if not isinstance(data, np.ndarray):
                raise TypeError('{} is not supported'.format(type(data)))
        self.data = data
        self.grad = None
        self.creator = None
        self.generation = 0

    def set_creator(self, func):
        self.creator = func
        self.generation = func.generation + 1

    def cleargrad(self):
        self.grad = None

    def backward(self):
        if self.grad is None:
            self.grad = np.ones_like(self.data)
        funcs = []
        seen_set = set()

        def addfunc(f):
            if f not in seen_set:
                funcs.append(f)
                seen_set.add(f)
                funcs.sort(key=lambda x: x.generation)#funcs按照从小到大的辈分排序

        addfunc(self.creator)

        while funcs:
            f = funcs.pop()
            gys = [output.grad for output in f.outputs]  # 获取所有输出的梯度
            gxs = f.backward(*gys)                       # 调用 backward 方法
            if not isinstance(gxs, tuple):               # 确保 gxs 是元组
                gxs = (gxs,)
            for x, gx in zip(f.inputs, gxs):            # 为每个输入分配梯度
                if x.grad is None:
                    x.grad = gx
                else:
                    x.grad = x.grad + gx
                if x.creator is not None:
                    addfunc(x.creator)

class Function:
    def __call__(self, *inputs):
        xs = [x.data for x in inputs]               # 提取输入数据
        ys = self.forward(*xs)                      # 前向传播(解包)
        if not isinstance(ys, tuple):               # 确保 ys 是元组
            ys = (ys,)
        outputs = [Variable(as_array(y)) for y in ys]  # 创建输出变量

        self.generation = max([x.generation for x in inputs])
        for output in outputs:
            output.set_creator(self)
        self.inputs = inputs                        # 保存输入
        self.outputs = outputs                      # 保存输出
        return outputs if len(outputs) > 1 else outputs[0]  # 根据输出数量返回

    def forward(self, *xs):
        raise NotImplementedError()

    def backward(self, *gys):
        raise NotImplementedError()

# 实现具体的函数类
class Square(Function):
    def forward(self, x):
        return x ** 2

    def backward(self, gy):
        x = self.inputs[0].data                     # 从 inputs 中获取数据
        gx = 2 * x * gy
        return gx

class Add(Function):
    def forward(self, x0, x1):
        y = x0 + x1
        return y

    def backward(self, gy):
        return gy, gy                               # 对两个输入返回相同的梯度

# 定义便捷函数
def square(x):
    return Square()(x)

def add(x0, x1):
    return Add()(x0, x1)

# 定义 as_array 函数
def as_array(x):
    if np.isscalar(x):
        return np.array(x)
    return x

x = Variable(np.array(2.0))
a = square(x)
y = add(square(a) , square(a))
y.backward()
print(y.data)
print(x.grad)
'''
# 测试代码
x = Variable(np.array(2.0))
y = Variable(np.array(3.0))
z = add(square(x), square(y))
z.backward()
print(z.data)    # 输出结果: 13.0 (2^2 + 3^2 = 4 + 9 = 13)
print(x.grad)    # 输出梯度: 4.0 (dz/dx = 2 * 2 = 4)
print(y.grad)    # 输出梯度: 6.0 (dz/dy = 2 * 3 = 6)
'''

运行结果:

下一章将会深入实践深度学习中的内存管理部分,掌握代码技术

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3.6c语言

#define _CRT_SECURE_NO_WARNINGS #include <math.h> #include <stdio.h> int main() {int sum 0,i,j;for (j 1; j < 1000; j){sum 0;for (i 1; i < j; i){if (j % i 0){sum i;} }if (sum j){printf("%d是完数\n", j);}}return 0; }#de…

element-plus中table组件的使用

1、table组件的基本使用 注意&#xff1a; ①对象集合&#xff0c;要从后端查询。 ②prop是集合中的对象的属性名&#xff1b;label是表格表头的名称。 2、将性别一列的71转为男&#xff0c;72转为女 问题描述&#xff1a; 解决步骤&#xff1a; ①将el-table-column变成双标签…

.NET CAD 二次开发中的 Transform 与数学矩阵详解

.NET CAD 二次开发中的 Transform 与数学矩阵详解 一、Transform 的定义与作用 在 .NET CAD 二次开发中,Transform 是通过数学矩阵对图形实体进行几何变换的核心机制,包括平移、旋转、缩放、镜像和切变等操作。这些操作通过矩阵乘法实现,能够高效地修改图形的位置、方向和…

【js逆向】iwencai国内某金融网站实战

地址&#xff1a;aHR0cHM6Ly93d3cuaXdlbmNhaS5jb20vdW5pZmllZHdhcC9ob21lL2luZGV4 在搜索框中随便输入关键词 查看请求标头&#xff0c;请求头中有一个特殊的 Hexin-V,它是加密过的&#xff1b;响应数据包中全是明文。搞清楚Hexin-V的值是怎么生成的&#xff0c;这个值和cooki…

STM32之ADC

逐次逼近式ADC&#xff1a; 左边是8路输入通道&#xff0c;左下是地址锁存和译码&#xff0c;可将通道的地址锁存进ADDA&#xff0c;ADDB&#xff0c;ADDC类似38译码器的结构&#xff0c;ALE为锁存控制键&#xff0c;通道选择开关可控制选择单路或者多路通道&#xff0c;DAC为…

【Linux内核系列】:深入解析输出以及输入重定向

&#x1f525; 本文专栏&#xff1a;Linux &#x1f338;作者主页&#xff1a;努力努力再努力wz ★★★ 本文前置知识&#xff1a; 文件系统以及文件系统调用接口 用c语言简单实现一个shell外壳程序 内容回顾 那么在此前的学习中&#xff0c;我们对于Linux的文件系统已经有了…

基于YOLO11深度学习的电瓶车进电梯检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

无人机扩频技术对比!

一、技术原理与核心差异 FHSS&#xff08;跳频扩频&#xff09; 核心原理&#xff1a;通过伪随机序列控制载波频率在多个频点上快速跳变&#xff0c;收发双方需同步跳频序列。信号在某一时刻仅占用窄带频谱&#xff0c;但整体覆盖宽频带。 技术特点&#xff1a; 抗干扰…

项目实战--网页五子棋(对战功能)(9)

上期我们完成了websocket建立连接后的数据初始化&#xff0c;今天我们完成落子交互的具体代码&#xff1a; 这里我们先复习一下&#xff0c;之前约定好的落子请求与响应包含的字段&#xff1a; 1. 发送落子请求 我们在script.js文件中找到落子的相关方法&#xff0c;增加发送请…

elementplus的cascader级联选择器在懒加载且多选时的一些问题分析

1. 背景 在之前做的一个项目中使用到了element的级联选择器&#xff0c;并且是需要懒加载、多选、父子不关联等等&#xff0c;在选的时候当然没问题&#xff0c;但是回显的时候就会回显不出来&#xff0c;相信大部分伙伴都遇到过这个问题。我在以前出过一篇文章写过关于级联选…

基于PySide6的CATIA零件自动化着色工具开发实践

引言 在汽车及航空制造领域&#xff0c;CATIA作为核心的CAD设计软件&#xff0c;其二次开发能力对提升设计效率具有重要意义。本文介绍一种基于Python的CATIA零件着色工具开发方案&#xff0c;通过PySide6实现GUI交互&#xff0c;结合COM接口操作实现零件着色自动化。该方案成…

Uniapp项目运行到微信小程序、H5、APP等多个平台教程

摘要&#xff1a;Uniapp作为一款基于Vue.js的跨平台开发框架&#xff0c;支持“一次开发&#xff0c;多端部署”。本文将手把手教你如何将Uniapp项目运行到微信小程序、H5、APP等多个平台&#xff0c;并解析常见问题。 一、环境准备 在开始前&#xff0c;请确保已安装以下工具…

ROS分布式部署通信

目录 一、概念 二、设置 ROS 分布式网络 1. 环境要求 2. 主机&#xff08;Master&#xff09;设置 3. 从机&#xff08;节点设备&#xff09;设置 4. 测试是否正常通信 三、进阶启动多从机节点&#xff08;launch&#xff09;。 一、概念 ROS 分布式通信用于在多台计算机…

qt open3dAlpha重建

qt open3dAlpha重建 效果展示二、流程三、代码效果展示 二、流程 创建动作,链接到槽函数,并把动作放置菜单栏 参照前文 三、代码 1、槽函数实现 void on_actionAlpha_triggered();//alpha重建 void MainWindow::

我的三维引擎独立开发之路:坚持与迷茫

今天终于解决了&#xff0c;之前开发的基于threeceisum开发的融合引擎Merge3D,引用threejs版本过低的问题&#xff0c;也算又前进了一步&#xff01; 有人说&#xff0c;直接用最新版本不就行了&#xff0c;哎关键之前版本怎么办哪&#xff0c;很多不兼容性&#xff0c;需要一个…

【ArcGIS】地理坐标系

文章目录 一、坐标系理论体系深度解析1.1 地球形态的数学表达演进史1.1.1 地球曲率的认知变化1.1.2 参考椭球体参数对比表 1.2 地理坐标系的三维密码1.2.1 经纬度的本质1.2.2 大地基准面&#xff08;Datum&#xff09;的奥秘 1.3 投影坐标系&#xff1a;平面世界的诞生1.3.1 投…

数据分析人员需要掌握sql到什么程度?

学习SQL三个层次 熟悉基本的增删改查语句及函数&#xff0c;包括select、where、group by、having、order by、delete、insert、join、update等&#xff0c;可以做日常的取数或简单的分析&#xff08;该水平已经超过90%非IT同事&#xff09;;掌握并熟练使用高阶语法&#xff0…

简洁实用的3个免费wordpress主题

高端大气动态炫酷的免费企业官网wordpress主题 非常简洁的免费wordpress主题&#xff0c;安装简单、设置简单&#xff0c;几分钟就可以搭建好一个wordpress网站。 经典风格的免费wordpress主题 免费下载 https://www.fuyefa.com/wordpress

golang从入门到做牛马:第一篇-我与golang的缘分,go语言简介

还记得2018年的夏天,刚毕业的我不知道该做些什么,于是自学了一周的go语言,想要找一份go语言工作的代码,当时的go还没有go mod来管理依赖包,在北京找了一个月的工作,找到了一个小公司做了后端开发,当然使用go语言开发,带着兴奋劲,年轻身体也好,边努力学习,边工作。 时…

【Python编程】高性能Python Web服务部署架构解析

一、FastAPI 与 Uvicorn/Gunicorn 的协同 1. 开发环境&#xff1a;Uvicorn 直接驱动 作用&#xff1a;Uvicorn 作为 ASGI 服务器&#xff0c;原生支持 FastAPI 的异步特性&#xff0c;提供热重载&#xff08;--reload&#xff09;和高效异步请求处理。 启动命令&#xff1a; u…