深度学习笔记003AutoDerivative矩阵计算/自动求导

今天跟着沐神学了矩阵计算,包括标量、向量与矩阵三者之间的运算关系(笔记看云记即可),虽然机器学习很少不到矩阵之间的运算,但也花了比较大的篇幅去讲解,了解了向量里的链式法则,学习了正反两种求导方式,着重讲解了反向求导(反向传递)的过程,相对来说比较清晰(不是说沐神讲的不好,只是我菜,需要时间消化)。

随后,用代码实现了一下机器学习可能需要的求导内容,如下:

 1 from mxnet import sym
 2 from mxnet import autograd,nd
 3 
 4 # # 将代码分解成操作子,显示构造 (有向无环图)
 5 # a=sym.var()
 6 # b=sym.var()
 7 # c=2*a+b
 8 
 9 # # 隐式构造
10 # with autograd.record():
11 #     a=nd.ones((2,1))
12 #     b=nd.ones((2,1))
13 #     c=2*a+b
14 
15 # 自动求导的两个模式:1.正向累积,就是从x一级一级算到y; 2.反向求导(反向传递):从y开始一级 一级算到x(高数思路,bp网络,Back-Propagation)
16 # 正向执行图时存储中间结果,从相反方向执行图,去除不需要的枝
17 # 正反向计算复杂度o(n),反向内存复杂度是o(N),因为反向计算需要存储正向计算的所有中间结果
18 # 优缺点:
19 #  反向:内存、时间复杂度都是O(n),但是计算了就都存储了;
20 #  正向:内存复杂度是O(1),但是计算一个变量的梯度的复杂度是O(n)。
21 
22 # 自动求导代码实现
23 # 对y=2(列向量x的转置)乘以(列向量x)
24 import torch
25 x= torch.arange(4.0) #可以带上一个参数requires_grad=True,等价于下面的导数存储
26 print(x)
27 x.requires_grad_(True)# y关于x的导数存在这里
28 print(x.grad)
29 # y的计算
30 y=2*torch.dot(x,x)
31 print(y)
32 print(x.grad)
33 y.backward() #反向传播求导
34 print(x.grad)
35 # 求证结果:2(x·x),等价于2||x||²的导数,也就是4x
36 print(x.grad==4*x)
37 print("计算另一个函数——————————————————————————————————————")
38 print(x.grad)
39 x.grad.zero_()
40 print(x.grad)
41 y=x.sum()
42 y.backward()
43 print(x.grad)
44 
45 #深度学习中,很少计算矩阵的导数,而是批量计算每个样本单独计算的偏导数之和
46 x.grad.zero_()
47 y=x*x
48 y.sum().backward()
49 print(x.grad)
50 
51 # 将计算移动到记录的计算图之外
52 x.grad.zero_()
53 y=x*x
54 u=y.detach() #将y变量化,让系统认为y是一个变量而不是一个式子,把它存入u
55 z=u*x
56 z.sum().backward()
57 print(x.grad==u)
58 
59 x.grad.zero_()
60 y.sum().backward()
61 print(x.grad==2*x)
62 
63 # 利用python的控制流建立的函数,也可以获得变量的梯度:
64 def f(a):
65     b=a*2
66     while b.norm() <1000:
67         b=b*2
68     if b.sum()>0:
69         c=b
70     else:
71         c=100*b
72     return c
73 a=torch.randn(size=(),requires_grad=True)
74 d=f(a)
75 d.backward()
76 print(a.grad)
77 print(a.grad==d/a)

 

posted @ 2022-01-01 18:49  爱和九九  阅读(197)  评论(0)    收藏  举报