MXNet 中的库 NDArray 类似于 NumPy,区别在于 NDArray 可以利用 GPU 进行加速以及自动求梯度
创建 NDArray
from mxnet import nd
# 创建向量
x = nd.arange(12)
# 获得 x 的形状
x.shape
# 获得 x 中的元素数
x.size
# 将 x 改为 3x4 的矩阵
X = x.reshape((3,4)) # x.reshape((-1,4)) or x.reshape((3,-1))
# 各元素都为0,形状为 2,3,4 的张量
x = nd.zeros((2,3,4))
# 各元素为 1 的张量
nd.ones((2,3,4))
# 使用 list 初始化
nd.array([[1,2,3],[4,5,6]])
# 产生均值为0,标准差为1的正态分布
nd.random.normal(0,1,shape=(3,4))
运算
按元素运算
# 按元素乘法
x * y
# 按元素除法
x / y
# 按元素加法
x + y
# 按元素做指数运算
x.exp()
矩阵乘法
# 假设X、Y矩阵均为3行4列,则矩阵X与Y的转置相乘的结果为3行3列
nd.dot(X, Y.T)
矩阵连接
# 假设x和y都是3x4的矩阵,nd.concat将x和y连起来,dim=0表示扩展行
nd.concat(x, y, dim=0)
# dim=1表示扩展列
nd.concat(x, y, dim=1)
两个同形状的张量,可以按相同位置进行比较、判断是否相等,相等位1,否则为0,返回新的张量
x == y
对所有元素求和,返回值依然是一个 NDArray
x.sum()
可以将上式返回的 NDarray 转换为一个标量
x.sum().asscalar()
求标量中所有元素的L2范数(平方和再开更号)
x.norm()
广播机制
不同形状张量按元素运算,先复制元素使它们形状相同,再进行计算
x = nd.arange(3).reshape((3,1))
y = nd.arange(2).reshape((1,2))
x + y
索引
行或列的索引都从0开始,遵从左闭右开原则
# 获得某个元素,并重新赋值,第2行,第3列
X[1,2] = 9
# 获取第2、3行的所有元素
X[1:3]
# 截取一部分元素(第2、3行的所有元素),并重新赋值
X[1:3,:] = 12
NDArray 和 NumPy 互换
通过 array 将 NumPy 对象转换为 NDArray 对象
import numpy as np
P = np.ones((2,3))
D = nd.array(P)
D
将 NDArray 转换为 NumPy
D.asnumpy()
自动求梯度
梯度的概念
x 为一个向量 [x1,x2,…,xn]⊤\left[x_1,x_2,\dots,x_n\right]^\top[x1,x2,…,xn]⊤,关于 x 的函数 f(x)f(x)f(x) 的梯度可以表示为
∇f(x)=[∂f(x)∂x1,∂f(x)∂x2,…,∂f(x)∂xn]
\nabla f(x) = \left[ \frac{\partial f(x)}{\partial x_1}, \frac{\partial f(x)}{\partial x_2}, \dots, \frac{\partial f(x)}{\partial x_n} \right]
∇f(x)=[∂x1∂f(x),∂x2∂f(x),…,∂xn∂f(x)]
使用 MXNet 自动求梯度的步骤:
- 导入
autograd
库:from mxnet import autograd, nd
- 标记需要求梯度的参数
x.attach_grad()
,其中x
为参数,它是一个向量 autograd.record()
,记录求梯度的计算,默认情况下 MXNet 不会记录(可选)- 通过
backward
函数自动求梯度
例如我们对 y=2x⊤xy=2x^\top xy=2x⊤x 自动求梯度的代码如下
from mxnet import autograd, nd
x = nd.arange(4).reshape((4,1))
x.attach_grad()
with autograd.record():
y = 2 * nd.dot(x.T, x)
y.backward()
x.grad
----
output:
[[ 0.]
[ 4.]
[ 8.]
[12.]]
<NDArray 4x1 @cpu(0)>
本文来自《动手学深度学习》预备知识的读书笔记