NDArray与NumPy的多维数组相似,但NDArray提供了更多的功能:GPU和CPU的异步计算;自动求导。这使得NDArray能更好地支持机器学习。编程
from mxnet import ndarray as nd nd.zeros((3,4)) nd.ones((3,4)) nd.array([[1,2],[3,4]]) out: [[1. 2.][3. 4.]] <NDArray 2x2 @cpu(0)> nd.random_normal(0,1,shape=(3,4)) #标准正态分布 # 输出信息 y.shape y.size
按照相应元素运算数组
x+y x*y nd.exp(x)
矩阵的乘法框架
nd.dot(x, y.T)
当二元操做符左右两边ndarray形状不同时,系统会尝试将它们扩充到共同的形状。dom
a=nd.arange(3).reshape((3,1)) b=nd.arange(2),reshape((1,2)) print ('a+b', a+b) out: a+b: [[ 0. 1.] [ 1. 2.] [ 2. 3.]] <NDArray 3x2 @cpu(0)>
x=np.ones((2,3)) y=nd.array(x) # numpy->mxnet z=y.asnumpy() # mxnet->numpy
若是咱们写y=x+y,会开辟新的内存来存储计算结果,如:机器学习
x=nd.ones((3,4)) y=nd.ones((3,4)) before = id(y) y=y+x id(y)==before # False
能够经过[:]写到之间创建好的数组中异步
z=nd.zeros_like(y) before=id(z) z[:]=x+y id(z)==before # True
上述,系统仍是为x+y建立了临时空间,再复制给了z。为了不这个开销,能够使用操做符的全名版本并指定out参数函数
nd.elemwise_add(x,y,out=z) id(z)==before # True
#截取(Slicing)学习
x=nd.arange(0,9).reshape((3,3)) x[1:3] out: [[ 3. 4. 5.] [ 6. 7. 8.]] <NDArray 2x3 @cpu(0)> #改变指定位置的值 x[1,2]=9. #多维截取 x[1:2,1:3] #多维写入 x[1:2,1:3]=9. out: [[ 0. 1. 2.] [ 3. 9. 9.] [ 6. 7. 8.]] <NDArray 3x3 @cpu(0)>
import mxnet.ndarray as nd import mxnet.autograd as ag
x=nd.array([[1,2],[3,4]]) x.attach_grad() # ndarray的方法申请相应的空间 # 定义函数f=2x*x,显式要求mxnet记录咱们要求导的程序 with ag.record(): y=x*2 z=y*x # 经过z.backword()来进行求导,若是z不是一个标量,z.backward()等价于nd.sum(z).backward(). z.backward() print('x.grad: ',x.grad) x.grad == 4*x # output x.grad: [[4., 8.] [12., 16.]] <NDArray 2x2 @cpu(0)> [[ 1. 1.] [ 1. 1.]] <NDArray 2x2 @cpu(0)>
命令式的编程的一个便利之处是几乎能够对任意的可导程序进行求导,即便里面包含了 Python 的 控制流。对于计算图框架来讲,这个对应于动态图,就是图的结构会根据输入数据不一样而改变。spa
def f(a): b=a*2 while nd.norm(b).asscalar() < 1000: b=b*2 if nd.sum(b).asscalar() > 0: c=b else: c = 100 * b return c
使用record和backward求导scala
a = nd.random_normal(shape=3) a.attach_grad() with ag.record(): c = f(a) c.backward()
基于链式法则: $$\frac{dz}{dx} = \frac{dz}{dy}\frac{dy}{dx}$$ $\frac{dz}{dy}$就是$\frac{dy}{dx}$的头梯度,而计算$\frac{dz}{dy}$,头梯度则为默认值,即nd.ones_like(y)。咱们也能够手动指定头梯度。
with ag.record(): y = x * 2 z = y * x head_gradient = nd.array([[10, 1.], [.1, .01]]) z.backward(head_gradient) print(x.grad) # out x= [[1.,2.] [3.,4.]] <NDArray 2x2 @cpu(0)> x.grad= [[40., 8.] [12., 0.16]] <NDArray 2x2 @cpu(0)>