基于OpenCL的深度学习工具:AMD MLP及其使用详解
本文介绍AMD深度学习团队开发的MLP学习工具软件的使用,为深度学习研究人员和开发商提供一个高性能、高易用性的深度学习的软硬件平台方案。AMD-MLP基于OpenCL,支持不同类型的GPU平台,并能通过多GPU扩展学习速度。
【编者按】深度学习是近年来迅速发展和突破的机器学习领域,具有非常广泛的应用前景。将服务器GPU应用到深度学习过程中,可以更好地推动深度学习技术研究和应用的发展。本文介绍AMD深度学习团队开发的MLP学习工具软件的使用,为深度学习研究人员和开发商提供一个高性能、高易用性的深度学习的软硬件平台方案。AMD-MLP基于OpenCL,支持不同类型的GPU平台,并能通过多GPU扩展学习速度。
深度学习神经网络简介
深度学习是人工智能的学科—机器学习的一个研究领域,是多种学习方法的集合。深度学习的各种学习方法都采用类似于人脑中的生物神经网络的结构建立模型,即较大层次和规模的人工神经网络(DNN),模拟人脑神经系统的信息处理和交换过程,实现对数据的分析和处理。
深度学习是近年来机器学习研究中获得最多关注的领域。业界一般认为,深度学习的快速发展和应用是以多伦多大学的Geoffrey Hinton教授发表在科学杂志上的一篇文章[1]开始的。自Hinton的文章以后,深度学习在语音识别、图像分类、自然语言处理等领域取得了不断的突破。尤其值得一提的是,由于采用深度学习技术,在ImageNet 图像分类2012年度的挑战赛中,top5 分类的最佳识别率达到了85%[2];并在最近,即2014年度的挑战赛中,top5分类的最佳识别率超过了93%[3],可见深度学习对图像识别领域的推动非常明显,足以让业界人心激动。
各种深度学习的模型结构读者可从Google上搜索得到。典型的DNN结构都会包括一个输入层,一个输出层和若干隐含层,不通类型的DNN会有不同类型的隐含层类型、功能、连接方式及具体学习策略和算法。典型的DNN有用于采用监督式学习方法,常用于图像分类的卷积神经网络[4](CNN)和采用非监督式学习方法,用于对深度网络模型参数进行预训练的深度信念网络(DBN)[4]。
MLP全称Multi-layer Perceptron(即多层感知机),是一种前向触发的人工神经网络结构。MLP特点是相邻两层的节点之间全连接,同一层的节点之间无连接,跨层之间无连接。MLP属于监督式学习技术,用误差向后传播的思想来学习神经网络模型的参数。MLP对标签数据进行学习的结果就是一个表示分类器或预测器的神经网络,可用于解决分类或回归问题。传统的MLP概念并不特指深度的神经网络,但由于实现技术的进步,目前我们所研究和采用的MLP网络都是网络层数比较多,节点规模比较大的网络结构,同时MLP采用的误差后向传播的思想以及其网络层中的非线性转换过程和监督式的深度学习模型完全一致,所以我们认为MLP是深度学习的一种方式。
MLP已经被用于语言识别,图像识别,机器翻译等领域,也可用于一些结构化、离散型数值的数据的特征识别,如网络包的类型识别[5]。
深度学习需要GPU加速
典型的深度神经网络由于层数多,结构复杂,节点数多,训练数据集大等特点,训练过程所需的时间特别长,通常以数日,数周,甚至数月来计算。计算型独立显卡(GPU)由于其计算单元数量大,并行处理能力强,可部署密度大等特点,几乎成为提高深度学习过程速度的一致选择。
作为高性能计算专业显卡提供商,AMD 长期致力于在高性能计算和大数据分析领域为用户和开发商伙伴提供软硬平台。AMD中国深度学习团队专门开发了AMD-MLP软件,帮助用户在AMD专业硬件平台上完成各种深度学习任务。本文所述开发是在AMD S9150 高性能显卡上开发的,S9150具有2816 个流处理器(44 个计算单元)、5.07 TFLOPS单精度负浮点计算能力、2.53 TFLOPS双精度浮点计算能力、 16G GDDR5 内存、320 GB/S 内存带宽,可以胜任大型DNN学习任务的运行。其16G内存完全足够存放目前为此参加ImageNet图像分类竞赛的有公开的大规模CNN模型的网络参数,避免了DNN学习过程中将网络模型参数分散到多个GPU所带来的算法复杂性。
AMD-MLP 深度学习技术
AMD-MLP是AMD中国异构计算部门开发的私有软件,其开发人员都是GPU计算和应用方面的专家,在使用异构计算技术提高软件性能方面有丰富的理解和实现经验,他们本着简单、实效、方便用户、注重性能的产品实现原则,为AMD-MLP带来了如下特点:
1) 完全的C++实现
全部的代码用C++类进行组织。用C++类的公共接口作为API,开发者用户无论是利用AMD-MLP进行数据学习,建立数据分类器;还是使用已产生的数据分类器开发识别型应用,编程都非常简单。
2) 基于开放标准实现
AMD- MLP 用OpenCL作为使用GPU进行通用计算的编程工具,来实现深度学习过程中的重要计算操作。由于OpenCL是开放标准的异构编程工具,其被AMD、Intel及Nvidia等多个厂家所实现,因此AMD-MLP 能在不同厂家的设备上运行,软件的移植性很好。clBlas是基于OpenCL实现的矩阵运算操作库,AMD-MLP中执行矩阵运算的地方直接用clBlas的接口实现,简化了编程。由于clBlas是实现开放标准的开源软件,其同样保证了AMD-MLP的可移植性。
3) 模块化,易于扩展,用户只需要开发自己的数据接口C++类就可使用MLP学习自己的数据
用戶在用AMD-MLP开发自己的分类器、识别器或预测器时,通常都会有和自己的应用领域相关的数据,甚至是自己的企业特定的数据源,由于这些数据的文件格式不一样,AMD-MLP不可能为所有用户都开发好数据使用接口,但AMD-MLP采用了高度模块化的设计,AMD-MLP通过实现一个DNNDataProvider对象提供了一个相对统一的数据访问接口和数据在内存中的格式,基于这个统一的接口,用户只需要做少量的开发工作(开发一个DNNDataProvider派生类) 识别其数据在文件中的格式并将其加载到内存即可,用户不需要关心数据在学习过程中如何被组织,传输和使用。AMD-MLP已经为手写数字识别数据源MNIST实现了一个数据接口,可作为用户实现自己数据源接口的参考。AMD-MLP的模块性还表现在其用分开的类实现了深度学习过程参数的配置的、神经网落状态SnapShot的功能,理解和使用都非常方便。
4) 支持多种计算设备
大规模的深度网络学习过程通常需要功能强大的独立显卡设备,但小型的神经网络及小型数据集的学习完全可以在集成显卡或CPU设备上进行,如作者本人就经常在AMD的A10 APU上进行MNIST数据集的学习。另外,使用学习好的分类器或预测器进行数据分类或函数数值预测时如果其对单个请求返回结果的实时性要求不高,分类或预测的神经网络计算过程完全可以用集成GPU或CPU设备来计算。为了满足这多种情况的需要,AMD-MLP 支持dGPU、iGPU、CPU三种设备,用户在使用时可灵活根据需要进行选择。
5) 支持灵活的网络结构和学习参数配置
用户使用AMD-MLP 进行神经网络学习的配置过程非常简单,只需要将网络结构和学习过程的控制参数写在一个文本文件中,每次学习时按需要进行修改即可。
6) 算法的灵活度
AMD-MLP对神经网络算法的支持比较灵活,允许用户按自己的需要进行选择,如在神经网络隐含层的激活(Activation)函数上,AMD MLP目前已经支持ReLu、TanH、Sigmoid和Softsign四种,允许用户通过配置文件进行选择,以满足不同数据学习的需要。另外AMD-MLP也允许用户通过配置文件对学习率参数进行动调整,并控制学习率调整的时机和速度。
7) 通过Checkpointing 支持对大规模数据的不间断学习
大规模的数据集的学习通常需要花很长的时间(几天,几周甚至几月),在这个过程中,如果计算机系统发生任何意外,学习过程就会从头开始。AMD-MLP 实现了一个高效率的异步CheckPointing机制,来周期性(如每30分钟)地对学习的中间结果进行Snapshot,保证当学习过程因计算机系统的故障而中断时,系统恢复后学习过程能从最近的Snapshot状态继续进行避免了大量的时间浪费。
8) 用多GPU来提高对大规模数据的训练速度
神经网络结构和数据集的规模越大,解决的数据问题越复杂,所需的学习时间就越长。过长的学习时间周期,不仅影响创建一个分类或预测结果的时间,还不利于神经网络学习过程中经常需要的参数调优工作。因此几乎大多数高效的神经网络学习软件除充分利用业界最先进的GPU设备外,还采用了各种方法来加速神经网络的学习过程。AMD-MLP实现了用多个GPU通过数据划分进行并行深度神经网络学习的训练过程,极大提高了利用神经网络技术能进行学习的数据的类型和规模。AMD中国异构计算部将在另外一篇文章中专门介绍AMD-MLP多GPU学习的实现方法。
使用AMD-MLP进行深度学习过程举例
下面的内容以利用MNIST数据集学习手写数字识别器为类,介绍怎样用AMD-MLP进行编程,执行数据集学习和测试的过程:
1) 分类问题理解
MLP能解决的典型问题包括分类和回归。分类包括二值分类和多类分类。手写数字的识别就是一个多类分类问题。具体而言,其输入是一个手写数字的图像,输出是代表0~9共10个数字的类别值。MLP的训练过程是监督式学习,其训练的策略是在输入数据集确定的条件下,用某种方法不断调整神经网络参数,使其标记在输出端出现的概率最大。为了和神经网络结构及训练策略要求的计算过程一致,在实际使用MLP时,MNIST的28x28的输入图像要转变成784-元的浮点向量;代表图像类型的标签也要转换成10-元的浮点数组,如 4要换成(0,0,0,1,0,0,0,0,0)。MLP训练的最后结果是输出一个参数确定的神经网络结构,这个神经网络结构能将任何一个28x28大小的图像,转换为10-元的浮点数组,在实际应用这个学习好的神经网络时,对任何一个28x28的输入图像,其对应的数字类别就是输出的10-元浮点数组中数值最大的元素的索引(即概率最大的类别)。
2) MNIST 手写识别数据集
MNIST手写识别数据集是网上可公开获取的用于手写体数字识别的数据集,其常常被用来测试深度学习软件。该数据集包括60000个样本规模的训练集,10000个样本规模的测试集,每个样本的都是标准的28x28大小的手写灰度数字图像,数据集和样本的格式有详细的描述,具体参考http://yann.lecun.com/exdb/mnist/ 。由于MNIST数据集简单易用,对于深度学习软件的开发者而言,用MNIST来初步检验测试自己软件解决分类问题的功能是一个不错的选择。MNIST网站上还公开了用各种不同类型机器学习方法进行手写识别在MNIST测试集上所达到的性能结果,其中的数据是很好的参考。
3) 代码步骤讲解
使用AMD-MLP的API进行神经网络学习的代码非常简单,下面两个截图中代码完整的展示了用AMD-MLP 进行MNIST数据集的学习和并测试学习后的识别率的过程。
对MNIST数据集进行学习的代码步骤如下:
- 创建 DNNMNistDataProvider类型的对象,启动该对象提供的MNIST数据访问服务功能。在这里该数据服务对象需要服务的数据是 MNIST的训练集。
- 创建MLPConfigProvider类型的对象,以读取MLP神经网络学习所需要的参数和网络结构信息.
- 创建MLPTrainerOCL类型的对象,该对象提供和MLP学习相关的全部操作。MLPTrainerOCL对象和MLPConfigProvider及DNNMNistDataProvider类型对象是关联的,因为其在执行MLP训练过程前需要从前者确定网络结构及训练过程的参数,在执行MLP训练过程中需要从后者不断读取MNIST训练数据
- 执行MLP训练过程,统计训练过程执行的时间,最后保存训练的结果。
用户的数据集及神经网络规模比较大时,如果需要使用多个GPU进行学习,只需要将代码中的MLPTrainerOCL替换成MLPTrainerMGpuMaster类即可,其中的一个构造参数指定GPU的数量。
使用MNIST测试集对训练的结果进行评估的代码步骤如下:
- 创建 DNNMNistDataProvider类型的对象,启动该对象提供的MNIST数据访问服务功能。在这里该数据服务对象需要服务的数据是 MNIST的测试集
- 创建MLPConfigProvider类型的对象,以读取以前训练好,保存起来的神经网络参数
- 创建MLPTesterOCL类型的对象,该对象提供和MLP训练后测试相关的全部操作。MLPTestOCL对象和MLPConfigProvideerr及DNNMNistDataProvider类型对象是关联的,因为其在执行MLP测试过程前需要从前者获取已经训练好的网络参数,在执行MLP测试过程中需要从后者不断读取MNIST测试数据
- 执行MLP测试过程,输出测试过程所达到的预测成功率,作为对训练过程评价的依据。
4) 神经网络结构和参数配置
AMD-MLP 的训练过程的配置非常简单,当然这和MLP网络结构本身相对简单有关。配置文件是一个按行定义的文本文件,其中既包括对神经网络结构的定义,也包括对训练过程的控制参数的指定。说明如下:
- Network Type 指定MLP神经网络要解决的问题的类型。这个参数通常影响神经网络输出层的计算方法。Network Type 的值可有 Multiple Classification, Binary Classification, Regression三种。
- Layers 指定MLP神经网络总的层数,注意这个层数包括了输入层。
- Input Layer, Hidden Layer, Output Layer 分别定义神经网络输入,隐含和输出层的参数。Input Layer要指的只有该层的节点数;Hidden Layer 可以有多个,每个隐含层需要指定节点数, 所用的激活方法以及该层的初始学习率;Output Layer的参数和Hidden Layer 类似,我们将其用不同的关键字标识,是因为其激活方法的设定有不同的意义。在我们的MNIST学习例子中,只有一个隐含层,其节点数为800;输入层的节点数为784,代表输入数据大小为28x28的图像;输出层的大小为10,代表分类问题的类别总数为10。
- Cost Function 指定输出层误差的反向传递方式。对于多值分类问题,其应该指定为CE,对二值分类或回归问题,其应该指定为SSE。
- Momentum 和Weight Decay 都是MLP学习的梯度下降法中,用来控制Weights和Biases参数更新的参数。
- Epochs 指定本次训练要执行的轮数,即全部数据要学习多少遍。
- Dynamic Tuning 指是否要对学习率参数进行动态调整。当该参数值为 true时,Start Epoch和Interval Epoch参数分别代表进行调整的起点和间隔。
用 AMD-MLP学习出的手写数字识别器演示
1) 演示程序
AMD设计了一个利用MLP做手写数字识别的演示程序,包含GPU及CPU版本的识别演示程序( 源码下载点击这里),是在Fedora 19下用Gtk3开发的,需要在有Gtk3的Linux下运行,其中CPU版本的程序在AMD或Intel的CPU上都可运行。这个压缩包中的二进制文件mlp_nnet.dat就是以前神经网络学习的输出,其中包含了神经网络的全部参数信息,它就代表了一个手写数字分类器。
2) 演示截图
总结
AMD-MLP 是由AMD异构计算部门深度学习团队开发的深度学习软件,经过专业设计,它使用非常方便。AMD-MLP在AMD的GPU平台上开发,但能帮助用户在不同类型的GPU平台上完成深度学习任务,并能通过多GPU扩展学习速度。AMD-MLP是目前不多的,基于OpenCL实现的深度学习软件。同时AMD异构计算团队正在在其他流行的深度学习框架如Torch7、Caffe等上进行工作,后续会推出自己的方案。