pytorch基本运算-Python控制流梯度运算

【1】引言

前序学习进程中,已经对pytorch基本运算-梯度运算:requires_grad_(True)和backward()进行了学习,了解了pytorch求导的基本运算方法。

今天继续学习,当计算进入循环时,就进入了Python控制流,如何对Python控制流进行梯度运算就是学习目标。

【2】Python控制流循环运算对应梯度

这里我们使用一个代码实例来体会梯度运算。

首先引入模块:

python 复制代码
# 引入模块
import torch

这里的目的是引入Pytorch模块,为之后的运算构建一个Pytorch环境。

然后定义一个常数:

python 复制代码
# 定义变量a为标准正态分布的随机数,并且允许对a求导
a=torch.randn(size=(),requires_grad=True)

这个常数会代入后面的运算,这个运算先定义了一个函数:

python 复制代码
# 定义基本函数
def f(a):
    b=a*2
    print('a0=',a)
    print('b0=', b)
    k=1
    # 如果b的绝对值小于1000,b的值扩大2倍
    # 这个扩大2倍的计算循环执行,直到b的绝对值超过1000
    while b.norm()<20:
        b=b*2
        k=k+1
        print('b[',k,']=',b)
        print('k=',k)
    # 如果b本身的值非负,c的取值就是b
    # 否则c的取值是100*b
    # 返回c值
    if b.sum()>0:
        c=b
    else:
        c=100*b
    print('c=',c)
    return c

这个自定义函数首先定义了一个b=a2,然后判断b的绝对值是否小于1000,如果满足,就不断扩大两倍,直到b的绝对值大于1000。
之后根据b的实际取值,对c进行赋值,如果b是正数,c=b,否则c=100
b。

之后就很简单,直接提取循环计算的计算结果就可以:

python 复制代码
d=f(a)
# 对自定义函数的返回值求导
d.backward()
# 输出a的导数
print('a.grad=',a.grad)
# 输出d
print('d=',d)
# 输出d/a的结果
print('d/a=',d/a)
# 输出a.grad和d/a是否相等
print('a.grad==d/a=',a.grad==d/a)

这里面对循环求导数实际上定义完a.grad就够了,单位了展示细节,分别输出了a,d/a。

代码运行后,输出的实际效果为:

a= tensor(0.9862, requires_grad=True)

a0= tensor(0.9862, requires_grad=True)

b0= tensor(1.9725, grad_fn=)

b[ 2 ]= tensor(3.9450, grad_fn=)

k= 2

b[ 3 ]= tensor(7.8899, grad_fn=)

k= 3

b[ 4 ]= tensor(15.7799, grad_fn=)

k= 4

b[ 5 ]= tensor(31.5597, grad_fn=)

k= 5

c= tensor(31.5597, grad_fn=)

a.grad= tensor(32.)

d= tensor(31.5597, grad_fn=)

d/a= tensor(32., grad_fn=)

a.grad==d/a= tensor(True)

这里的最开始获得随机数a=0.9862,然后它扩大2倍赋值给b,b<1000,所以会继续不断按照2倍的速率扩大,直到b>1000,刚好计算了5次,也就是k的取值。

由于b>0,所以c的取值就是b,因为b相对a扩大了5次,所以循环计算对a的导数就是2^5=32。这个值就是d/a的结果。

如果再计算一次,a的取值为负:

a= tensor(-2.3740, requires_grad=True)

a0= tensor(-2.3740, requires_grad=True)

b0= tensor(-4.7480, grad_fn=)

b[ 2 ]= tensor(-9.4960, grad_fn=)

k= 2

b[ 3 ]= tensor(-18.9921, grad_fn=)

k= 3

b[ 4 ]= tensor(-37.9842, grad_fn=)

k= 4

c= tensor(-3798.4180, grad_fn=)

a.grad= tensor(1600.)

d= tensor(-3798.4180, grad_fn=)

d/a= tensor(1600., grad_fn=)

a.grad==d/a= tensor(True)

此时b会在往负数不断变小的方向上,按照2倍的速率扩大绝对值,一共计算了4次。

由于b<0,所以c的取值就是b*100,因为b相对a扩大45次,所以循环计算对a的导数就是(2^4)*100=1600。这个值就是d/a的结果。

此时的完整代码为:

python 复制代码
# 引入模块
import torch

# 定义基本函数
def f(a):
    b=a*2
    print('a0=',a)
    print('b0=', b)
    k=1
    # 如果b的绝对值小于1000,b的值扩大2倍
    # 这个扩大2倍的计算循环执行,直到b的绝对值超过1000
    while b.norm()<20:
        b=b*2
        k=k+1
        print('b[',k,']=',b)
        print('k=',k)
    # 如果b本身的值非负,c的取值就是b
    # 否则c的取值是100*b
    # 返回c值
    if b.sum()>0:
        c=b
    else:
        c=100*b
    print('c=',c)
    return c
# 定义变量a为标准正态分布的随机数,并且允许对a求导
a=torch.randn(size=(),requires_grad=True)
# 输出a
print('a=',a)
# 将a代入自定义函数
d=f(a)
# 对自定义函数的返回值求导
d.backward()
# 输出a的导数
print('a.grad=',a.grad)
# 输出d
print('d=',d)
# 输出d/a的结果
print('d/a=',d/a)
# 输出a.grad和d/a是否相等
print('a.grad==d/a=',a.grad==d/a)

【3】总结

学习了以循环为基础的Python控制流梯度运算的基本方法。

相关推荐
北邮刘老师3 小时前
关于智能体互联协议标准的130天
人工智能·大模型·智能体·智能体互联网
人工干智能4 小时前
科普:Python 中,字典的“动态创建键”特性
开发语言·python
一条星星鱼4 小时前
深度学习是如何收敛的?梯度下降算法原理详解
人工智能·深度学习·算法
Elastic 中国社区官方博客4 小时前
AutoOps:简单的 Elasticsearch 集群监控与管理现已支持本地部署
大数据·人工智能·elasticsearch·搜索引擎·云计算·全文检索
金井PRATHAMA6 小时前
语义网络对人工智能自然语言处理中深层语义分析的影响与启示
人工智能·自然语言处理·知识图谱
程序猿阿伟7 小时前
《重构工业运维链路:三大AI工具让设备故障“秒定位、少误判”》
运维·人工智能·重构
开心-开心急了7 小时前
主窗口(QMainWindow)如何放入文本编辑器(QPlainTextEdit)等继承自QWidget的对象--(重构版)
python·ui·pyqt
yueyuebaobaoxinx7 小时前
聚焦技术落地,展现 AI 重构产业的实践路径。
人工智能·重构
算家云7 小时前
Sora 2 的社交野心:AI 如何重构内容社交产品逻辑?
人工智能·openai·算家云·租算力,到算家云·sora 2·ai社交
飞哥数智坊7 小时前
Qwen3 Omni 的“全模态”,到底和多模态有啥不一样?
人工智能