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形狀不同時,系統會嘗試將它們擴充到共同的形狀。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)>

與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 的 控制流。對於計算圖框架來講,這個對應於動態圖,就是圖的結構會根據輸入數據不一樣而改變。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)>
相關文章
相關標籤/搜索