动手学mxnet系列之NDArray

在mxnet中,NDArray是所有运算的核心数据结构,mxnet中的所有数据均使用NDArray进行表示,NDarray有点类似于numpy中的ndarray,操作上面也与numpy很相似,但是NDArray提供了numpy.ndarray所不具备的操作,比如:GPU,CPU的切换,自动求梯度的运算等等,这也是为什么mxnet要重新封装一个NDArray的原因。

NDArray就好比盖房子的砖,砖有了自然可以盖房子了,所以利用NDArray你便可以实现所有的深度学习模型了,只是深度学习日新月异,如果每个模型都从NDArray开始写,那当然是比较麻烦的,所以MXnet或者gluon帮我们封装了一些函数可以直接使用,接下来我们都会逐一的了解,那么这一节我们先来仔细学习一下mxnet的NDArray:

特别说明:下面的操作只是NDArray的一些基本操作,
获取更多的操作还请查找MXNet文档:https://mxnet.incubator.apache.org/api/python/ndarray/ndarray.html

当然,我希望你可以跟我一起来敲如下的代码而不是看一遍就过去了,事实证明,敲一遍的效果会好很多

在mxnet中,使用NDArray需要引用nd包(nd是ndarray的缩写),如下:

from mxnet import nd

在引入nd包之后就可以愉快的使用NDArry了。

特别说明,下面代码中 ‘->’ 代表的是输出结果

1. 定义x为一个序列,这里与numpy一致,不同的是,这里返回的每个元素类型都是ndarray

x = nd.arange(12)   -> [0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.]

2. 当然我们可以打印出ndarray的shape以及size,这里的shape和size不要混淆了

x.shape      ->  (12 ,)
x.size       ->  12
x.context    -> x在CPU还是在GPU上

x.dtype      -> data type,即每个元素的类型
## 当然,我们也可以改变元素的类型
x = x.astype(‘float32’) ## 利用astype便可以改变元素的类型了。


3. 那么如果我们想要构建一个二维矩阵怎么办呢?可以考虑reshape函数

x = nd.arange(12)
x.reshape(shape=(3,4))
# 当然你同样可以省略shape参数,直接这样写:
x.reshape((3,4)) ## 不过不要忘记(3,4)这个括号

4. 如果我们想初始化一个值为0或者值为1的多维矩阵该怎么做呢?

zero = nd.zeros((2,3,4))  # 别忘记了是负数
one = nd.ones((2,3,4))

5. 那如何建立一个随机初始化的矩阵呢?

S = nd.random.normal(0,1,shape=(3,4)) # normal是高斯分布

6. 当然我们也可以直接利用list直接建立ndarray,如下:

Y = nd.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])

7. 在计算机视觉中,图像一般是3维的,但是在进行模型训练的时候,往往需要将多张图像组成一个batch,构成4维数组,ndarray当然支持,使用concat:

x=nd.random.normal(shape=(2,3,4))   ->    x.shape (2,3,4)
y=nd.random.normal(shape=(2,3,4))   ->    y.shape (2,3,4)
z=nd.concat(x,y,dim=0)              ->    z.shape (4,3,4)
# 因为concat是不改变维度的,那么如果构建一个batch呢?利用expand_dims函数
x = nd.expand_dims(x, axis=0)      ->     x.shape (1,2,3,4) 
y = nd.expand_dims(y, axis=0)      ->     y.shape (1,2,3,4)
z=nd.concat(x,y,dim=0)             ->     z.shape (2,2,3,4)

8. ndarray天然支持常用的数学计算,这里方法较多,可以查阅文档,里面有例子,使用会比较方便

S*Y
S/Y
S.exp()
S == Y
nd.dot(S,Y.T) ## 点乘比较常用,深度学习中矩阵计算就是使用的点乘,如果你从头编写神经网络,一定离不开点乘
nd.floor(S) ## 向下取整
nd.ceil(S) ## 向上取整
nd.argmax() ## 返回最大值的index
nd.topk() ## 返回topk

9. ndarray与numpy的相互转换

# ndarray -> numpy

C = S.asnumpy()

# numpy -> ndarray

p = np.ones((2,3))
d = nd.array(p)

# 同样的,我们也可以直接返回一个标量
x = nd.ones((1,), dtype='int32')
y = x.asscalar() ## 这里注意,必须是1维的才可以使用,二维会报错。

10. 前面我们说了,NDArray可以自动计算梯度,那么如何使用呢?

1. 引用包   :from mxnet import autograd
2. 定义变量 : x = nd.arange(4).reshape((4,1))
3. 关联梯度,默认变量是不为梯度在内存开空间的,如果想要计算梯度,需要进行梯度关联,这样程序才会在内存上为变量开梯度的空间,如下:
x.attach_grad()

4. 计算的时候,使用autograd.record()记录梯度,如下是点乘的计算。
with autograd.record():
    y = 2 * nd.dot(x.T,x)
5. 使用backward()计算梯度: y.backward()

总结到一起就是如下:

from mxnet import autograd
x = nd.arange(4).reshape((4,1))
x.attach_grad()
with autograd.record():
    y = 2 * nd.dot(x.T,x)
y.backward()

11. 关于CPU与GPU的切换

x = nd.random.normal(shape=(3,4))  ## 默认在CPU内存中
y = nd.random.normal(shape=(3,4), ctx=mx.gpu(0)) ## 利用ctx指定对应的GPU
x = x.as_in_context(mx.gpu(0)) ## 利用as_in_context进行CPU到GPU的切换

12. 复制也是常用的操作,利用copy()可以避免浅拷贝的尴尬

x = nd.array([1,2,3])
y = x.copy()
## 为什么要使用copy()呢?因为在python中,默认的copy是浅拷贝,如果直接y=x,当x改变的时候,y会跟着改变,这就会出现错误。

特别说明:之上只是NDArray的一些基本操作,
获取更多的操作还请查找MXNet文档https://mxnet.incubator.apache.org/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值