NDArray自动求导

NDArray可以很方便的求解导数,比如下面的例子:(代码主要参考自https://zh.gluon.ai/chapter_crashcourse/autograd.html

 用代码实现如下:

 1 import mxnet.ndarray as nd
 2 import mxnet.autograd as ag
 3 x = nd.array([[1,2],[3,4]])
 4 print(x)
 5 x.attach_grad() #附加导数存放的空间
 6 with ag.record():
 7     y = 2*x**2
 8 y.backward() #求导
 9 z = x.grad #将导数结果(也是一个矩阵)赋值给z
10 print(z) #打印结果
[[ 1.  2.]
 [ 3.  4.]]
<NDArray 2x2 @cpu(0)>

[[  4.   8.]
 [ 12.  16.]]
<NDArray 2x2 @cpu(0)>

对控制流求导

NDArray还能对诸如if的控制分支进行求导,比如下面这段代码:

1 def f(a):
2     if nd.sum(a).asscalar()<15: #如果矩阵a的元数和<15
3         b = a*2 #则所有元素*2
4     else:
5         b = a 
6     return b

数学公式等价于:

这样就转换成本文最开头示例一样,变成单一函数求导,显然导数值就是x前的常数项,验证一下:

import mxnet.ndarray as nd
import mxnet.autograd as ag

def f(a):
    if nd.sum(a).asscalar()<15: #如果矩阵a的元数和<15
        b = a*2 #则所有元素平方
    else:
        b = a 
    return b

#注:1+2+3+4<15,所以进入b=a*2的分支
x = nd.array([[1,2],[3,4]])
print("x1=")
print(x)
x.attach_grad()
with ag.record():
    y = f(x)
print("y1=")
print(y)
y.backward() #dy/dx = y/x 即:2
print("x1.grad=")
print(x.grad)


x = x*2
print("x2=")
print(x)
x.attach_grad()
with ag.record():
    y = f(x)
print("y2=")
print(y)
y.backward()
print("x2.grad=")
print(x.grad)
x1=
[[ 1.  2.]
 [ 3.  4.]]
<NDArray 2x2 @cpu(0)>
y1=
[[ 2.  4.]
 [ 6.  8.]]
<NDArray 2x2 @cpu(0)>
x1.grad=
[[ 2.  2.]
 [ 2.  2.]]
<NDArray 2x2 @cpu(0)>
x2=
[[ 2.  4.]
 [ 6.  8.]]
<NDArray 2x2 @cpu(0)>
y2=
[[ 2.  4.]
 [ 6.  8.]]
<NDArray 2x2 @cpu(0)>
x2.grad=
[[ 1.  1.]
 [ 1.  1.]]
<NDArray 2x2 @cpu(0)>

头梯度

原文上讲得很含糊,其实所谓头梯度,就是一个求导结果前的乘法系数,见下面代码:

 1 import mxnet.ndarray as nd
 2 import mxnet.autograd as ag
 3 
 4 x = nd.array([[1,2],[3,4]])
 5 print("x=")
 6 print(x)
 7 
 8 x.attach_grad()
 9 with ag.record():
10     y = 2*x*x
11 
12 head = nd.array([[10, 1.], [.1, .01]]) #所谓的"头梯度"
13 print("head=")
14 print(head)
15 y.backward(head_gradient) #用头梯度求导
16 
17 print("x.grad=")
18 print(x.grad) #打印结果
x=
[[ 1.  2.]
 [ 3.  4.]]
<NDArray 2x2 @cpu(0)>
head=
[[ 10.     1.  ]
 [  0.1    0.01]]
<NDArray 2x2 @cpu(0)>
x.grad=
[[ 40.           8.        ]
 [  1.20000005   0.16      ]]
<NDArray 2x2 @cpu(0)>

对比本文最开头的求导结果,上面的代码仅仅多了一个head矩阵,最终的结果,其实就是在常规求导结果的基础上,再乘上head矩阵(指:数乘而非叉乘)

链式法则

先复习下数学

注:最后一行中所有变量x,y,z都是向量(即:矩形),为了不让公式看上去很凌乱,就统一省掉了变量上的箭头。NDArray对复合函数求导时,已经自动应用了链式法则,见下面的示例代码:

 1 import mxnet.ndarray as nd
 2 import mxnet.autograd as ag
 3 
 4 x = nd.array([[1,2],[3,4]])
 5 print("x=")
 6 print(x)
 7 
 8 x.attach_grad()
 9 with ag.record():
10     y = x**2
11     z = y**2 + y
12 
13 z.backward()
14 
15 print("x.grad=")
16 print(x.grad) #打印结果
17 
18 print("w=")
19 w = 4*x**3 + 2*x
20 print(w) # 验证结果
x=
[[ 1.  2.]
 [ 3.  4.]]
<NDArray 2x2 @cpu(0)>
x.grad=
[[   6.   36.]
 [ 114.  264.]]
<NDArray 2x2 @cpu(0)>
w=
[[   6.   36.]
 [ 114.  264.]]
<NDArray 2x2 @cpu(0)>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程

Python数据分析-数据预处理

主题 数据预处理 一、数据清洗 主要是删除原始数据集中无关的数据、重复的数据,平滑噪声数据,筛选掉与挖掘主题无关的数据,处理异常值缺失值等操作 1. 缺失...

73460
来自专栏xingoo, 一个梦想做发明家的程序员

动态规划

基本思想:将待求解问题分解成若干子问题,先求解子问题,然后从子问题的解中得到原问题的解。 与分治不同的是,经分解得到的子问题往往不是互相独立的。 若用分治法来解...

20350
来自专栏IT大咖说

死磕一周算法,我让服务性能提高 50%

内容来源:haolujun,https://www.cnblogs.com/haolujun/p/9527776.html

20350
来自专栏互联网杂技

Google用来处理海量文本去重的simhash算法原理及实现

simhash是Google用来处理海量文本去重的算法。 Google出品,你懂的。 simhash最牛逼的一点就是将一个文档,最后转换成一个64位的字节,暂且...

79580
来自专栏北京马哥教育

Numpy 隐含的四大陷阱,千万别掉进去了!

看起来效果不错。假设我们要对数据进行筛选,取第 1 列的第 1 行和第 3 行数据构成一个 2 x 1 的列向量。先看对 array 的做法:

27820
来自专栏CDA数据分析师

一篇文章教你如何用R进行数据挖掘

引言 R是一种广泛用于数据分析和统计计算的强大语言,于上世纪90年代开始发展起来。得益于全世界众多 爱好者的无尽努力,大家继而开发出了一种基于R但优于R基本文本...

40950
来自专栏ATYUN订阅号

数据清理的简要介绍

清理数据应该是数据科学(DS)或者机器学习(ML)工作流程的第一步。如果数据没有清理干净,你将很难在探索中的看到实际重要的部分。一旦你去训练你的ML模型,他们也...

15630
来自专栏微信模式识别中心技术分享

“变形金刚”为何强大:从模型到代码全面解析Google Tensor2Tensor系统

      Tensor2Tensor(T2T)是Google Brain Team在Github上开源出来的一套基于TensorFlow的深度学习系统。该系统...

3.2K90
来自专栏PPV课数据科学社区

如何用spss做一般(含虚拟变量)多元线性回归

回归一直是个很重要的主题。因为在数据分析的领域里边,模型重要的也是主要的作用包括两个方面,一是发现,一是预测。而很多时候我们就要通过回归来进行预测。关...

1.5K70
来自专栏WOLFRAM

用 Mathematica 生成正多面体链环

36370

扫码关注云+社区

领取腾讯云代金券