前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >1.试水:可定制的数据预处理与如此简单的数据增强(上)

1.试水:可定制的数据预处理与如此简单的数据增强(上)

原创
作者头像
SCP-173
发布2018-05-22 17:39:38
7982
发布2018-05-22 17:39:38
举报
文章被收录于专栏:AI黑科技工具箱AI黑科技工具箱

开了专栏后的第一篇文章0.伏笔:图像读取方式以及效率对比没想到反响如此强烈,我分析了一下,一方面是有各位大佬点赞支持,另一方面,大家对于MXNet以及其他大家平时都会用的包会非常感兴趣,也愿意去剖析它的用处与好处。我也调整了一下思路,之后的文章自己希望以一种初学探讨方式和大家进行分享,希望大家多讨论,多交流~

上篇文章讲了关于图像读取的方法和对比,有很多同学也提醒我,很多深度学习框架都开始采用比较高效的读取方法。的确如此,二进制读取方式和多线程是标配,不论是热门的pytorch、Tensorflow、Keras还是冷的不行的CNTK、chainer等,都在数据读取方面做了相应的优化,今天给大家重点介绍一下,MXNet+Gluon在数据预处理和数据增强方面是如何进行的。

说实话,在我仔细研究了MXNet和Gluon是如何进行数据加载与数据增强的,不得不佩服DMLC真的很良心,提供了如此简单的接口和又方便又多样的数据处理工具库。

在早期,我在学习MXNet的时候,觉得不论是文档(早期文档我就不吐槽了)还是官方教程都很奇怪,它的使用基础介绍主要分为两部分:一个NDArray的操作,一个是Symbol的接口。实际上从后来大多数Github上的例子中可以看出,大家使用的基本都是通过Symbol进行神经网络图模型的构建。

但事实上,MXNet不仅仅是一个深度学习神经网络工具箱,它本身设计的初衷是一个科学计算库,可以大批量通过显卡进行数学计算,同时又加入了自动求导(话说这不就成了反向传播BP了么?),使得整个工具库变得全面,比如DMLC早期想单独把这一部分剥离开,做成minpy。

好了闲话不说了,我们进入正题。

回忆起初高中学的大多数计算都属于前向计算方法,最简单如之类的y=a*b+1可以直接在MXNet实现,具体可以看看NDArray - Imperative tensor operations on CPU/GPU这一部分。

后来我在想,那NDArray中的其他工具是不是也不完全只有神经网络才能用,莫非也可以直接拿来做前向计算?我准备用卷积Convolution运算进行开刀。

了解的同学应该知道,Convolution运算实际上还有个别的名称:掩膜运算。我是本科自动化,在学信号处理、数字图像处理的时候,学过所谓的滤波算法,比如中值滤波、高斯滤波等等,实际上是狭义上的卷积运算。那么我今天尝试用MXNet中的NDArray的各种工具,提取一个图像边缘轮廓信息。

图像的知识,大家可以自己搜索,我直接用一个Prewitt算子对图像做滤波,实现边缘信息提取。Prewitt算子是这样的一个结构:

$$ \begin{matrix} -1 & 0 & 1 \\ -1 & 0 & 1 \\ -1 & 0 & 1 \end{matrix} \tag{1} $$

我们只需要做一次Convolution卷积运算,同时将他的卷积核心设置成上述的Prewitt算子就好。

我们还是用二进制编码的方式打开图像并加载图像:

代码语言:javascript
复制
from mxnet import image
img = image.imdecode(open('../data/train/cats/cat.1234.jpg','rb').read())
imshow(img.asnumpy())

接下来,我们需要将图像转一下格式,因为普通的图像是(width, height, channel)这样的格式,而在MXNet通用的格式是(batch_size, channel, width, height),所以我们直接采用MXNet中的nd操作就好。

代码语言:javascript
复制
from mxnet import nd
img = nd.transpose(img, (2,0,1))/255. # 调整三个维度的顺序(c,w,h)
img = nd.stack(img, axis=0) # 在前面加上一维度(1,c,w,h)
print("image shape is:", img.shape)

image shape is: (1, 272, 345, 3)

之后就是重头戏,我们调用卷积函数Convolution,但是卷积函数需要几个参量,一个是输入数据(这个我们有了),权重weight,偏置bias,卷积核大小kernel:

代码语言:javascript
复制
weight = nd.array([[-1,0,1],[-1,0,1],[-1,0,1]]) #采用 Prewitt算子
weight = weight.broadcast_to((1,3,3,3)) # 广播成(1,3,3,3)大小的卷积核
bias = nd.zeros((1)) #设置偏置
kernel=(3,3)

这样我们就直接调用我们的大玩具了:

代码语言:javascript
复制
out = mx.nd.Convolution(data=img, weight=weight, bias=bias, kernel=kernel, num_filter=1)

我们看看结果怎么样:

代码语言:javascript
复制
sam = out[0][0].asnumpy()
imshow(sam, cmap='gray')

真的好好玩啊!这就可以了?要是我把整个过程移到显卡上,是不是就可以批量加速了?!

我再试试其他算子,这是考虑对角情况的sobel算子

代码语言:javascript
复制
weight = nd.array([[[-1,-1,-1],[-1,8,-1],[-1,-1,-1]]]) #采用8方向的Sobel算子

(如果我换成二阶算子应该也是可以的吧?)

大家不妨把脑洞打开的再大些:如果我从训练好的模型中,抽取出这些权重,是不是就可以自己写一个inference了?那么我就可以各种权重可视化了?中间层可视化?莫非我还可以根据权重大小来做卷积核的裁剪?如果我想在网络中输入的训练数据是边缘轮廓数据,莫非也可以中mx.nd来做预处理?以前老师让我们做的边缘提取什么分析的是不是也可以这么直接做了?

(这些脑洞和想法,我会在后续的文章中继续介绍与实践)

反正MXNet的这些操作可以用显卡进行加速!!~~

那么在本篇文章的后半部分,我会详细说说,我们怎么在MXNet中定制我们自己的数据增强,并且也会顺带介绍几种MXNet的数据加载方法,敬请期待~~~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com