安装MXnet包,实现MNIST手写数体识别

我想写一系列深度学习的简单实战教程,用mxnet做实现平台的实例代码简单讲解深度学习常用的一些技术方向和实战样例。这一系列的主要内容偏向于讲解实际的例子,从样例和代码里中学习解决实际问题。我会默认读者有一定神经网络和深度学习的基础知识,读者在这里不会看到大段推导和理论阐述。基础理论知识十分重要,如果读者对理论知识有兴趣,可以参看已有的深度学习教程补充和巩固理论基础,这里http://deeplearning.net/reading-list/tutorials/有一些不错的理论教程,相关的理论知识在此不赘述。

MXnet: 轻量化分布式可移植深度学习计算平台

MXnet是一群聪明勇敢勤劳的年轻计算机科学家实现的开源深度学习计算平台,它是DMLC分布式机器学习通用工具包http://dmlc.ml/ 的重要部分(如果你知道xgboosthttps://github.com/dmlc/xgboost 这个并行GBT的实现,应该对DMLC也不会陌生)。MXnet的优点是,轻量化、可移植性高、也可轻松分布式并行,并且高效利用显存,更可以灵活的运行在移动设备上。它的代码和使用方法也简洁明了,适合学习实战。这么有意思的深度学习工具平台,大家快去点这个github连接给它加个星加个fork吧,传送门:https://github.com/dmlc/mxnet

安装MXnet

MXnet支持Linux,Windows和Mac平台。本文使用的主要平台是ubuntu 14.04 LTS。提醒注意,这一些系列教程使用CUDA平台做GPU运算,而在本文写作的时候CUDA暂时还不支持最新的ubuntu 15.10版本的环境和编译器(主要是gcc 5.2的编译器),所以强烈建议坚守14.04 LTS版本或者是最多到15.04版。

安装环境可以是带nVidia显卡的实体机器或者是带GPU的云服务器。如果选择实体机,请不要通过虚拟机安装,比如原生Windows下面跑个虚拟的Linux,因为多数虚拟机软件不支持直接调用本机显卡。如果选择云服务器,请一定选择GPU instance比如AWS的g2.2xlargeg2.8xlarge,或者是terminal.com的GPU instance。注意:terminal.com号称运行时可以改虚拟机的类型,但是纯CPU的虚拟机在运行时不能无缝切换到GPU,建议一开始就选择GPU instance。

以下安装步骤参考于官方文档:http://mxnt.ml/en/latest/build.html#building-on-linux,本文根据CUDA的安装和实际操作略有修改。

基本依赖的安装

MXnet的另一个优点就是它只需要很少的第三方包,它基本只需要gcc的编译器,BLAS以及可选安装OpenCV。这里如果还没有安装git可以顺道安装一下。

sudo apt-get update
sudo apt-get install -y build-essential git libblas-dev libopencv-dev
下载mxnet
git clone --recursive https://github.com/dmlc/mxnet

这里提醒注意一定不要忘记--recursive参数,因为mxnet依赖于DMLC通用工具包http://dmlc.ml/--recursive参数可以自动加载mshadow等依赖。这里暂时不要着急编译,我们还要装一下CUDA。

安装CUDA

这里提到的CUDA安装方法也适用于除MXnet之外的其他深度学习软件包。我们通过nVidia官方链接下载安装CUDA驱动和工具包,请前往https://developer.nvidia.com/cuda-downloads 选择对应的安装方式。国内读者建议网络安装方式deb(network),这样ubuntu会选择就近的国内的源安装,速度可能比较快。

如果用ubuntu 14.04,不用去官网,直接运行以下这些命令也可以调用官网下载(安装包较大需要耐心等待):

wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64/cuda-repo-ubuntu1404_7.5-18_amd64.deb
sudo dpkg -i cuda-repo-ubuntu1404_7.5-18_amd64.deb
sudo apt-get update
sudo apt-get install cuda

如果一切安装成功,可以用nvidia-smi命令查看你的显卡使用情况,一般空闲的显卡状态是这个样子的:

显卡型号取决于个人经济能力,不过mxnet的显存利用率高,一般一个4G的显卡就足够处理多数别的工具包要很多显存的问题。

可选安装:Mxnet也支持cuDNN,它是nVidia推出的深度学习加速工具包,能高效实现一些卷积等深度学习常用操作,在内存使用和计算速度上面能有所提高。大家可以到这里https://developer.nvidia.com/cudnn 申请开发者项目,如果批准通过可以下载安装cuDNN工具包,具体请参照nVidia官方教程。

编译支持GPU的MXnet

MXnet需要打开一个编译和链接选项来支持CUDA。在前一步git clone得到的mxnet/目录里找到mxnet/make/子目录,把该目录下的config.mk复制到mxnet/目录,用文本编辑器打开,找到并修改以下三行:

USE_CUDA = 1
USE_CUDA_PATH = /usr/local/cuda

其中第二行是CUDA的安装目录。如果选择默认安装方式,它会在/usr/local/cuda或者是类似/usr/local/cuda-7.5这样的原始安装目录,如果是自定义目录的安装,请自行修改本条。

如果用户选择安装atlas或者openblas等其他BLAS的实现,需要额外的修改。如果ubuntu的atlas实现(sudo apt-get install libatlas-base-dev或者sudo apt-get install libopenblas-dev),需要修改为:

USE_BLAS = atlas 或者 openblas

修改之后,在mxnet/目录下编译(-j4是可选参数表示用4线程编译):

make -j4

注意:如果没有CUDA支持的显卡(比如Intel的Iris显卡或者AMD的R系列显卡)或者没有显卡,安装和编译GPU版本的mxnet会出错。解决方法是,把USE_CUDA = 1改回USE_CUDA = 0,并确保USE_OPENMP = 1,mxnet会自动编译CPU版本并使用OpenMP进行多核CPU计算。根据问题的不同,GPU版本对比CPU版一般会有20-30倍左右的加速。

安装Python支持

MXnet支持Python调用。简单来说就这么安装:

cd python; python setup.py install

建议使用python 2.7版本,需要预先安装setuptoolsnumpy(sudo apt-get install python-numpy)。如果你的系统安装Numpy有些困难,可以考虑安装Anaconda或者Miniconda之类的python发行版:

wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh
bash Miniconda-latest-Linux-x86_64.sh
(确认回答若干安装问题后)
conda install numpy

运行MNIST手写数字识别

2015年11月19日更新:这里的样例基于旧版mxnet/example的目录结构,新版的MNIST代码在mxnet/example/image-classification/下,可以通过--gpu (gpu_id)开启GPU计算选项,请自行更新并参见新版说明:https://github.com/dmlc/mxnet/tree/master/example/image-classification

当MXnet一切安装好之后,可以试试看一下最简单的例子,MNIST手写数字识别。MNIST数据集包含6万个手写数字的训练数据集以及1万个测试数据集,每个图片是28x28的灰度图。在mxnet/example/mnist里可以找到MXnet自带MNIST的识别样例,我们可以先运行一下试试:

cd mxnet/example/mnist
python mlp.py

mlp.py会自动下载MNIST数据集,在第一次运行的时候耐心等待一下。

注意mlp.py 默认使用CPU,训练过程可以跑起来但是很慢。我们已经安装了GPU,只需要修改一行代码,把FeedForward调用的CPU部分改成GPU即可让MXnet运行在GPU上:

model = mx.model.FeedForward(
        ctx = mx.cpu(), symbol = mlp, num_epoch = 20,
        learning_rate = 0.1, momentum = 0.9, wd = 0.00001)   

变成:

model = mx.model.FeedForward(
        ctx = mx.gpu(), symbol = mlp, num_epoch = 20,
        learning_rate = 0.1, momentum = 0.9, wd = 0.00001)   

再运行一下,是不是快多了呢?MXnet的优点就是接口简洁。运行的时候,nvidia-smi命令查看显卡状态差不多是这个样子的:

可以看到python进程在使用GPU,因为这是个比较小的问题同时MXnet的显存优化较好,GPU使用率30%到40%之间,显存占用67MB。

可能出现的问题

运行GPU例子的时候可能会遇到这样的问题:

ImportError: libcudart.so.7.0: cannot open shared object file: No such file 

这是因为没有把CUDA的动态链接库加入PATH里,解决方法是,可以在./bashrc里面加入:

export LD_LIBRARY_PATH=/usr/local/cuda-7.5/targets/x86_64-linux/lib/:$LD_LIBRARY_PATH

或者是在编译MXnet的时候,在config.mk里的

ADD_LDFLAGS = -I/usr/local/cuda-7.5/targets/x86_64-linux/lib/
ADD_CFLAGS =-I/usr/local/cuda-7.5/targets/x86_64-linux/lib/
MNIST代码简单讲解:设计一个最简单的多层神经网络

mlp.py实现的是一个多层感知器网络(multilayer perceptron (MLP) )或者叫多层神经网络。在MXnet里,实现一个MLP首先需要定义一下这个MLP的结构,比如在代码里一个三层网络的MLP就是这样的:

data = mx.symbol.Variable(‘data‘)
fc1 = mx.symbol.FullyConnected(data = data, name=‘fc1‘, num_hidden=128)
act1 = mx.symbol.Activation(data = fc1, name=‘relu1‘, act_type="relu")
fc2 = mx.symbol.FullyConnected(data = act1, name = ‘fc2‘, num_hidden = 64)
act2 = mx.symbol.Activation(data = fc2, name=‘relu2‘, act_type="relu")
fc3 = mx.symbol.FullyConnected(data = act2, name=‘fc3‘, num_hidden=10)
mlp = mx.symbol.Softmax(data = fc3, name = ‘mlp‘)

简单解释一下这几行代码:MNIST的数据集每组数据是28x28的灰度图像,差不多如下图:

每组数据就可以表示成一个长度为28x28=784的一维数组,数组的每个元素是这个像素的灰度值。MLP的每一层需要定义这一层节点的样式,比如fc1就是接受输入的第一层,它定义为一个全链接层mx.symbol.FullyConnected,通过data接受输入,这一层包含了128个节点(num_hidden)。每一层也需要定义激活函数Activation,比如第一层到第二层之间的激活函数就是relu(代表rectified linear unit或者叫Rectifier)ReLu是深度神经网络里最常见的一个激活函数,主要因为计算函数相对容易和梯度下降不会发散,并且由于MNIST的问题比较稀疏更适合ReLU。限于这里篇幅主要是为了介绍实现一个网络,关于ReLU的相关背景知识请参考wikipedia )和其他相关教程。第二层网络fc2和第一层相似,它接受fc1的数据作为输入,输出给第三层。第三层网络fc3和前两层类似,不一样的是它是个结果输出层,产生的是输入图片对应于0-9总共10个数字里每个数字的概率,所以它的num_hidden=10

设计好了网络结构之后,MXnet需要声明输入feature的格式,因为每个图片都是28x28大小,按照每个像素的灰度值展开成一列向量就是784维,我们可以告诉mxnet数据的输入尺寸是784,mnist_iterator是一个python generator一次提供100组数据给我们刚刚设计的MLP,参见同目录的data.py

train, val = mnist_iterator(batch_size=100, input_shape = (784,))

接下来就让MXnet建立并运行这个一个模型,就是这样简单,如果你会scikit-learn会感到很亲切,对不对(记得刚刚修改的指定GPU运行的那一行么?):

model = mx.model.FeedForward(
        ctx = mx.gpu(), symbol = mlp, num_epoch = 20,
        learning_rate = 0.1, momentum = 0.9, wd = 0.00001)
model.fit(X=train, eval_data=val)

到这里,大家就基本会实现一个多层感知器MLP,恭喜你们这是掌握深度学习的第一步。MXnet的方式比Caffe等其他工具要写个配置文件简单的多了。工业界和学术界的多数深度学习的实际问题都是围绕着设计多层感知器展开,在结构设计激活函数设计等方面有很多有意思的问题。

有读者会问,MLP是不是非要像MNIST手写数字识别这么设计。不是的,这个三层网络只是一个最简单的MLP的例子,这里每一层并不一定需要这样。设计一个更好更高效的多层神经网络和艺术一样没有止境。比如在MNIST同一个目录下的lenet.py就是用Yann Lecun设计的卷积网络实现数字识别,每层网络需要做的是ConvolutionActivationPooling(如果想知道这三个具体是什么,请参看他的深度学习教程,以后的文章里面可能也会提到。

当做课后作业,读者可以自己试试调一下mlp.py里不同的节点数和激活函数看看对数字识别率有什么提升,也可以增加num_epoch调整learning_rate等参数,在转发、评论或留言写下你们的设计方法和识别准确度(并没有奖励,嗯)。Kaggle针对MNIST数据集有一个教学比赛,读者可以用MXnet训练一个自己的MNIST模型,把结果提交上去比一比,记得说你是用MXnet做的哟,传送门:https://www.kaggle.com/c/digit-recognizer

后记

这篇文章是这一系列的第一篇,我本意是想写个MXnet的GPU安装方法,后来想想加个例子讲解一下各种模型顺便当做另外一种深度学习入门教程吧。后续的一些文章会挑选mxnet自带的例子,介绍一些常见的有意思的深度学习模型,比如RNN,LSTM,以及它们在MXnet里的实现,比如写个自动作词机模仿汪峰老师作词之类的。MXnet这么有意思的深度学习工具平台,大家快去这个github连接给它加个星加个fork吧,传送门:https://github.com/dmlc/mxnet

时间: 2024-09-30 05:47:01

安装MXnet包,实现MNIST手写数体识别的相关文章

MNIST手写数字图片识别(线性回归、CNN方法的手工及框架实现)(未完待续)

0-Background 作为Deep Learning中的Hello World 项目无论如何都要做一遍的. 代码地址:Github 练习过程中将持续更新blog及代码. 第一次写博客,很多地方可能语言组织不清,请多多提出意见..谢谢~ 0.1 背景知识: Linear regression CNN LeNet-5 AlexNet ResNet VGG 各种regularization方式 0.2 Catalog 1-Prepare 2-MNIST 3-LinearRegression 1-P

基于MNIST手写数字数据集的数字识别小程序

30行代码奉上!(MNIST手写数字的识别,识别率大约在91%,简单尝试的一个程序,小玩具而已) 1 import tensorflow.examples.tutorials.mnist.input_data as input_data 2 import tensorflow as tf 3 mnist = input_data.read_data_sets('/temp/', one_hot=True) 4 5 #设置 6 x = tf.placeholder(tf.float32,[None

win10下通过Anaconda安装TensorFlow-GPU1.3版本,并配置pycharm运行Mnist手写识别程序

折腾了一天半终于装好了win10下的TensorFlow-GPU版,在这里做个记录. 准备安装包: visual studio 2015: Anaconda3-4.2.0-Windows-x86_64: pycharm-community: CUDA:cuda_8.0.61_win10:下载时选择 exe(local) CUDA补丁:cuda_8.0.61.2_windows: cuDNN:cudnn-8.0-windows10-x64-v6.0;如果你安装的TensorFlow版本和我一样1.

MNIST手写数字数据库

手写数字库很容易建立,但是总会很浪费时间.Google实验室的Corinna Cortes和纽约大学柯朗研究所的Yann LeCun建有一个手写数字数据库,训练库有60,000张手写数字图像,测试库有10,000张. 请访问原站 http://yann.lecun.com/exdb/mnist/ 该数据库在一个文件中包含了所有图像,使用起来有所不便.如果我把每个图像分别保存,成了图像各自独立的数据库. 并在Google Code中托管. 如果你有需要,欢迎在此下载: http://yann.le

tensorflow笔记(四)之MNIST手写识别系列一

tensorflow笔记(四)之MNIST手写识别系列一 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7436310.html 前言 这篇博客将利用神经网络去训练MNIST数据集,通过学习到的模型去分类手写数字. 我会将本篇博客的jupyter notebook放在最后,方便你下载在线调试!推荐结合官方的tensorflow教程来看这个notebook! 1. MNIST数据集的导入 这里介绍一下MNIST,MNIST是在

Haskell手撸Softmax回归实现MNIST手写识别

Haskell手撸Softmax回归实现MNIST手写识别 前言 初学Haskell,看的书是Learn You a Haskell for Great Good, 才刚看到Making Our Own Types and Typeclasses这一章. 为了加深对Haskell的理解,便动手写了个Softmax回归.纯粹造轮子,只用了base. 显示图片虽然用了OpenGL,但是本文不会提到关于OpenGL的内容.虽说是造轮子, 但是这轮子造得还是使我受益匪浅.Softmax回归方面的内容参考

Tensorflow实践 mnist手写数字识别

minst数据集                                         tensorflow的文档中就自带了mnist手写数字识别的例子,是一个很经典也比较简单的入门tensorflow的例子,非常值得自己动手亲自实践一下.由于我用的不是tensorflow中自带的mnist数据集,而是从kaggle的网站下载下来的,数据集有些不太一样,所以直接按照tensorflow官方文档上的参数训练的话还是踩了一些坑,特此记录. 首先从kaggle网站下载mnist数据集,一份是

tensorflow 基础学习五:MNIST手写数字识别

MNIST数据集介绍: from tensorflow.examples.tutorials.mnist import input_data # 载入MNIST数据集,如果指定地址下没有已经下载好的数据,tensorflow会自动下载数据 mnist=input_data.read_data_sets('.',one_hot=True) # 打印 Training data size:55000. print("Training data size: {}".format(mnist.

matlab练习程序(神经网络识别mnist手写数据集)

记得上次练习了神经网络分类,不过当时应该有些地方写的还是不对. 这次用神经网络识别mnist手写数据集,主要参考了深度学习工具包的一些代码. mnist数据集训练数据一共有28*28*60000个像素,标签有60000个. 测试数据一共有28*28*10000个,标签10000个. 这里神经网络输入层是784个像素,用了100个隐含层,最终10个输出结果. arc代表的是神经网络结构,可以增加隐含层,不过我试了没太大效果,毕竟梯度消失. 因为是最普通的神经网络,最终识别错误率大概在5%左右. 迭