天天看點

mxnet 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.]]

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.]]

與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.]]

#改變指定位置的值

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.]]

使用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.]]

[[ 1. 1.]

[ 1. 1.]]

對控制流求導

指令式的程式設計的一個便利之處是幾乎可以對任意的可導程式進行求導,即使裡面包含了 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.]]

x.grad=

[[40., 8.]

[12., 0.16]]