深度学习笔记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)
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号