【深度学习笔记】2.2数据操作
在MXNet中,NDArray是?个类,也是存储和变换数据的主要?具。为了简洁,本书常将NDArray实例直接称作NDArray。如果你之前?过NumPy,你会发现NDArray和NumPy的多维数组?常类似。然而,NDArray提供GPU计算和?动求梯度等更多功能,这些使NDArray更加适合深度学习。
2.2.1创建NDArray
?先从MXNet导?ndarray模块。这?的nd是ndarray的缩写形式。
from mxnet import nd
然后我们?arange函数创建?个?向量。
x = nd.arange(12)
x.shape
x.size
X = x.reshape((3, 4))
nd.zeros((2, 3, 4))
nd.ones((3, 4))
Y = nd.array([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
nd.random.normal(0, 1, shape=(3, 4))
2.2.2 运算
NDArray?持?量的运算符(operator)。例如,我们可以对之前创建的两个形状为(3,4)的NDArray做按元素加法。所得结果形状不变。
X + Y
X * Y
X / Y
Y.exp()
nd.dot(X, Y.T)
下?分别在?上(维度0,即形状中的最左边元素)和列上(维度1,即形状中左起第?个元素)连结两个矩阵。可以看到,输出的第?个NDArray在维度0的?度(6)为两个输?矩阵在维度0的?度之和(3 + 3),而输出的第?个NDArray在维度1的?度(8)为两个输?矩阵在维度1的?度之和(4 + 4)。
nd.concat(X, Y, dim=0), nd.concat(X, Y, dim=1)
X == Y
X.sum()
X.norm().asscalar()
可以把Y.exp()、X.sum()、X.norm()等分别改写为nd.exp(Y)、nd.sum(X)、nd.norm(X)等
2.2.3 广播机制
前?我们看到如何对两个形状相同的NDArray做按元素运算。当对两个形状不同的NDArray按元素运算时,可能会触发?播(broadcasting)机制:先适当复制元素使这两个NDArray形状相同后再按元素运算。
A = nd.arange(3).reshape((3, 1))
B = nd.arange(2).reshape((1, 2))
由于A和B分别是3?1列和1?2列的矩阵,如果要计算A + B,那么A中第?列的3个元素被?播(复制)到了第?列,而B中第??的2个元素被?播(复制)到了第??和第三?。如此,就可以对2个3?2列的矩阵按元素相加。
A + B
2.2.4 索引
在NDArray中,索引(index)代表了元素的位置。NDArray的索引从0开始逐?递增。例如,?个3?2列的矩阵的?索引分别为0、1和2,列索引分别为0和1。在下?的例?中,我们指定了NDArray的?索引截取范围[1:3]。依据左闭右开指定范围的惯例,它截取了矩阵X中?索引为1和2的两?。
X[1:3]
X[1, 2] = 9
X[1:2, :] = 12
2.2.5 运算的内存开销
在前?的例??我们对每个操作新开内存来存储运算结果。举个例?,即使像Y = X + Y这样的运算,我们也会新开内存,然后将Y指向新内存。为了演?这?点,我们可以使?Python?带的id函数:如果两个实例的ID?致,那么它们所对应的内存地址相同;反之则不同。
before = id(Y)
Y = Y + X
id(Y) == before
如果想指定结果到特定内存,我们可以使?前?介绍的索引来进?替换操作。在下?的例?中,我们先通过zeros_like创建和Y形状相同且元素为0的NDArray,记为Z。接下来,我们把X +Y的结果通过[:]写进Z对应的内存中。
Z = Y.zeros_like()
before = id(Z)
Z[:] = X + Y
id(Z) == before
实际上,上例中我们还是为X + Y开了临时内存来存储计算结果,再复制到Z对应的内存。如果想避免这个临时内存开销,我们可以使?运算符全名函数中的out参数。
nd.elemwise_add(X, Y, out=Z)
id(Z) == before
如果X的值在之后的程序中不会复?,我们也可以? X[:] = X + Y 或者 X += Y 来减少运算的内存开销。
before = id(X)
X += Y
id(X) == before
2.2.6 NDArray和NumPy相互变换
我们可以通过array函数和asnumpy函数令数据在NDArray和NumPy格式之间相互变换。下?将NumPy实例变换成NDArray实例
import numpy as np
P = np.ones((2, 3))
D = nd.array(P)
D.asnumpy()
|