【深度学习笔记】2.2数据 *** 作

【深度学习笔记】2.2数据 *** 作,第1张

【深度学习笔记】2.2数据 *** 作 【深度学习笔记】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  #通过shape属性来获取NDArray实例的形状
x.size  #通过size属性得到NDArray实例中元素(element)的总数
X = x.reshape((3, 4)) #使⽤reshape函数把⾏向量x的形状改为(3, 4),也就是⼀个3⾏4列的矩阵,并记作X。除了形状改变之外,X中的元素保持不变。
nd.zeros((2, 3, 4))  #创建⼀个各元素为0,形状为(2, 3, 4)的张量。实际上,之前创建的向量和矩阵都是特殊的张量。
nd.ones((3, 4))  #创建各元素为1的张量
Y = nd.array([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]) #通过Python的列表(list)指定需要创建的NDArray中每个元素的值
#随机⽣成NDArray中每个元素的值。下⾯我们创建⼀个形状为(3,4)的NDArray。它的每个元素都随机采样于均值为0、标准差为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) #使⽤dot函数做矩阵乘法,将X与Y的转置做矩阵乘法。由于X是3⾏4列的矩阵,Y转置为4⾏3列的矩阵,因此两个矩阵相乘得到3⾏3列的矩阵。

下⾯分别在⾏上(维度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 == Y为例,如果X和Y在相同位置的条件判断为真(值相等),那么新的NDArray在相同位置的值为1;反之为0
X.sum() #NDArray中的所有元素求和得到只有⼀个元素的NDArray
X.norm().asscalar() #通过asscalar函数将结果变换为Python中的标量

可以把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的两⾏(左闭右开)
X[1, 2] = 9 #指定NDArray中需要访问的单个元素的位置,如矩阵中⾏和列的索引,并为该元素重新赋值.把矩阵X中第2行,3列的元素换成9
X[1:2, :] = 12 #为⾏索引为1的每⼀列元素重新赋值
2.2.5 运算的内存开销

在前⾯的例⼦⾥我们对每个 *** 作新开内存来存储运算结果。举个例⼦,即使像Y = X + Y这样的运算,我们也会新开内存,然后将Y指向新内存。为了演⽰这⼀点,我们可以使⽤Python⾃带的id函数:如果两个实例的ID⼀致,那么它们所对应的内存地址相同;反之则不同。

before = id(Y)
Y = Y + X
id(Y) == before   #结果为False

如果想指定结果到特定内存,我们可以使⽤前⾯介绍的索引来进⾏替换 *** 作。在下⾯的例⼦中,我们先通过zeros_like创建和Y形状相同且元素为0的NDArray,记为Z。接下来,我们把X +Y的结果通过[:]写进Z对应的内存中。

Z = Y.zeros_like()
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

如果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 #导入numpy
P = np.ones((2, 3))  #创建一个2行3列的矩阵
D = nd.array(P)   #通过array函数把NumPy格式转为NDArray格式

D.asnumpy()  #通过asnumpy函数,把NDArray格式转为NumPy格式

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4827675.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-10
下一篇 2022-11-10

发表评论

登录后才能评论

评论列表(0条)

保存