zoukankan      html  css  js  c++  java
  • mxnet:基础知识和一个简单的示例

    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)
    

    广播(Beoadcasting)

    当二元操作符左右两边ndarray形状不一样时,系统会尝试将它们扩充到共同的形状。

    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)>
    

    与NumPy的转换

    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)>
    

    使用autograd自动求导

    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 的 控制流。对于计算图框架来说,这个对应于动态图,就是图的结构会根据输入数据不同而改变。

    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求导

    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)>
    
  • 相关阅读:
    115. Distinct Subsequences
    Kafka介绍-copy
    Flume的简单介绍-copy
    storm简介、原理、概念-copy
    日志管理ELK-copy
    安装Nginx+Lua+OpenResty
    Nginx(四)------nginx 负载均衡-copy
    Nginx(一)------简介与安装-copy
    Nginx(二)nginx.conf 配置文件-copy
    Nginx(三)nginx 反向代理-copy
  • 原文地址:https://www.cnblogs.com/houkai/p/9500908.html
Copyright © 2011-2022 走看看