阅读 57

MXNet之NDArray 速查

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 为一个向量 \left[x_1,x_2,\dots,x_n\right]^\top,关于 x 的函数 f(x) 的梯度可以表示为

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

使用 MXNet 自动求梯度的步骤:

  1. 导入 autograd 库:from mxnet import autograd, nd
  2. 标记需要求梯度的参数 x.attach_grad(),其中 x 为参数,它是一个向量
  3. autograd.record(),记录求梯度的计算,默认情况下 MXNet 不会记录(可选)
  4. 通过 backward 函数自动求梯度

例如我们对 y=2x^\top 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)>
复制代码

本文来自《动手学深度学习》预备知识的读书笔记