编译:yxy
出品:ATYUN订阅号
AWS最近宣布发布了针对Keras 2的Apache MXNet后端,与使用多GPU的默认后端相比,它可以为你提供高达3倍的速度提升。它可以改进训练和推理性能。在这个版本中,你现在能够将经过训练的Keras(使用MXNet后端)模型导出为本地MXNet模型,而不必依赖于特定的语言绑定。这种新的导出模型功能允许你使用各种工具(这些工具属于MXNet生态系统的一部分)。
在本文中,我们将在MXNet模型服务器上演示Keras-MXNet模型的用法。我们训练模型以检测图像中的笑脸,然后使用MXNet模型服务器通过Web API将其托管以进行在线推理。MXNet模型服务器是一种提供深度学习模型的工具,支持MXNet和ONNX(Open Neural Network Exchange)模型,并处理产品中模型服务的各个方面,包括HTTP端点,可扩展性,实时度量等。
第1部分 – 使用Keras-MXNet训练模型
如上所述,我们将训练模型来检测笑脸。我们将按照这个由McCyle McDonald编写的SmileCNN开源存储库中提到的步骤来训练我们的模型。
链接:https://github.com/kylemcdonald/SmileCNN
首先,我们通过安装必要的软件包来设置环境。如果你基于CPU的机器运行:
代码语言:javascript复制pip install mxnet
代码语言:javascript复制
代码语言:javascript复制pip install keras-mxnet
对于安装了cuda 9.0的基于GPU的机器,运行“pip install mxnet-cu90”
注:可在此处访问Keras-MXNet上的详细安装说明。有GPU的计算机(例如AWS P或G实例类型)可提供更好的训练性能。这可以通过启动AWS Deep Learning AMIs来实现
安装说明:https://github.com/awslabs/keras-apache-mxnet/blob/master/docs/mxnet_backend/installation.md
AWS Deep Learning AMIs:https://aws.amazon.com/machine-learning/amis/
接下来,我们创建了一个SmileCNN存储库的分支,修改了笔记本并将它们转换为python文件,以适应我们现有的使用MXNet模型服务器进行推断的用例,。可以通过拷贝以下内容来访问修改后的文件:
代码语言:javascript复制git clone https://github.com/kalyc/SmileCNN
代码语言:javascript复制
代码语言:javascript复制 cd SmileCNN
该存储库包含三个python文件 – 数据集准备,训练和评估。
首先,我们使用以下命令为这些包安装所需的依赖项:
代码语言:javascript复制sudo python setup.py install
然后,我们通过运行数据集准备的文件来准备训练数据。
代码语言:javascript复制python datasetprep.py
链接:https://github.com/kalyc/SmileCNN/blob/master/datasetprep.py
运行此文件会下载训练数据集。该数据集是近40MB的非笑脸和笑脸的实例。数据集有一个包含每个正面和反面训练图像的文件夹。此脚本获取这些图像并将其大小从64 x 64调整到32 x 32像素。然后它将它们转换为numpy数组并更新其格式,以便Keras-MXNet使用。
数据准备好后,我们使用训练文件训练模型。目前,Keras-MXNet中的保存模型仅支持channels_first数据格式,根据Keras-MXNet性能指南,已知这种格式会有更好的性能。所以,需要更新Keras配置以使用channels_first图像数据格式:
可以在$ HOME / .keras / keras.json访问Keras配置文件
代码语言:javascript复制{
代码语言:javascript复制
代码语言:javascript复制“backend”:“mxnet”,
代码语言:javascript复制
代码语言:javascript复制“image_data_format”:“channels_first”
代码语言:javascript复制
代码语言:javascript复制}
接下来,我们使用to_channels_first()函数讲输入数据转换为channels_first格式(下方链接脚本24行)。
链接:https://github.com/kalyc/SmileCNN/blob/master/train.py#L24
代码语言:javascript复制import keras as k
代码语言:javascript复制X= k.utils.to_channels_first(X)
我们修改原始训练脚本以保存模型,第64行:
代码语言:javascript复制# Save the trained Keras Model as MXNet Model
代码语言:javascript复制keras.models.save_mxnet_model(model=model, prefix='smileCNN_model')
更新配置后,我们运行训练脚本。
代码语言:javascript复制python train.py
训练网络基于mnist_cnn示例构建。根据你的硬件配置,训练此模型需要不同的时长。在本例中,我们在基础深度学习AMI的p2.16xlarge上训练这个模型100个周期。花了大约3分钟。P实例附带GPU,从而加快了训练时间。在基于CPU的硬件上,训练可能需要更长时间。
代码语言:javascript复制Test accuracy:0.9638663504942575
训练完成后,save_mxnet_model()函数将返回以下输出:
代码语言:javascript复制MXNet Backend: Successfully exported the model as MXNet model!
代码语言:javascript复制MXNet symbolfile - smileCNN_model-symbol.json
代码语言:javascript复制MXNet paramsfile - smileCNN_model-0000.params
代码语言:javascript复制Modelinput data_namesand data_shapes are:
代码语言:javascript复制data_names : ['/conv2d_1_input1']
代码语言:javascript复制data_shapes : [DataDesc[/conv2d_1_input1,(4L,1L,32L,32L),float32,NCHW]]
注意:在上面的data_shapes中,第一个维度表示用于模型训练的batch_size。你可以根据你推理的batch_size,更改绑定模块的batch_size。
该save_mxnet_model()函数创建smileCNN_model-symbol和smileCNN_model-0000.params一旦成功保存模型文件。这些文件定义网络的结构和相关的权重。它们基本上定义了训练完成的MXNet模型。输入符号为/ conv2d_1_input1,形状为(4L,1,32,32)。
smileCNN_model-symbol.json和smileCNN_model-0000.params文件是在根目录生成的。
我们可以使用评估脚本测试模型的准确性。
代码语言:javascript复制python evaluation.py
如果一切设置正确,模型应该能够获取一个numpy数组并将结果预测为笑脸。
评估图像
代码语言:javascript复制('non-smiling','------------------------###-','smiling')
上面的结果清楚地表明图像被正确分类。评估脚本使用用Keras-MXNet保存的模型,并加载它以用于预测。
第2部分 – 使用MXNet模型服务器进行推理
接下来,让我们看看如何使用MXNet模型服务器(MMS)来提供此模型。
按照MMS快速入门指南,我们在我们的机器上设置MXNet模型服务器。
指南:https://github.com/awslabs/mxnet-model-server
在ubuntu上运行:
代码语言:javascript复制sudo apt-get install protobuf-compiler libprotoc-dev
代码语言:javascript复制
代码语言:javascript复制pip install mxnet-model-server
在mac上运行:
代码语言:javascript复制conda install-c
代码语言:javascript复制
代码语言:javascript复制conda-forge protobuf pip install mxnet-model-server
我们在SmileCNN存储库中创建了一个名为keras-mms的模型存档目录。我们将保存的训练模型的符号和参数文件移动到keras-mms目录中,该目录用于在MXNet模型服务器上托管模型推理。
代码语言:javascript复制cp smileCNN_model- * ./keras-mms/
代码语言:javascript复制
代码语言:javascript复制cd keras-mms/
注意:以下部分介绍了创建keras-mms目录中已存在的文件的过程。
模型存档目录(keras-mms)包含以下文件:
代码语言:javascript复制- signature.json
代码语言:javascript复制
代码语言:javascript复制- synset.txt
代码语言:javascript复制
代码语言:javascript复制- smileCNN_model-symbol.json
代码语言:javascript复制
代码语言:javascript复制- smileCNN_model-0000.params
代码语言:javascript复制
代码语言:javascript复制- custom_service.py
为了让MMS知道使用哪个输入符号和什么形状进行推理,我们使用save_mxnet_model()函数的输出,并将signature.json文件设置在同一目录中,如下所示:
代码语言:javascript复制{
代码语言:javascript复制 "inputs": [
代码语言:javascript复制 {
代码语言:javascript复制 "data_name":"/conv2d_1_input1",
代码语言:javascript复制 "data_shape": [0,1,32,32]
代码语言:javascript复制 }
代码语言:javascript复制 ],
代码语言:javascript复制 "input_type":"image/jpeg",
代码语言:javascript复制 "outputs": [
代码语言:javascript复制 {
代码语言:javascript复制 "data_name":"softmax",
代码语言:javascript复制 "data_shape": [0,1]
代码语言:javascript复制 }
代码语言:javascript复制 ],
代码语言:javascript复制 "output_type":"application/json"
代码语言:javascript复制}
签名(signature)指定推理所需的输入是JPEG图像。输出类型是JSON。输出数据形状在0和1之间变化,因为模型仅预测笑脸和非笑脸2个类。
我们将必要的synset.txt文件添加到列表标签中 – 每行一个标签,如MXNet-Model Server导出说明中所述。这个文件根据数据集的不同而不同,它包含一个模型可以预测的类的列表。
对于笑脸检测示例,类标签是:
代码语言:javascript复制non-smiling
代码语言:javascript复制smiling
然后,我们编写一个custom_service.py文件,该文件定义了自定义了预处理和后处理的推理。
代码语言:javascript复制"""CustomService defines a MXNet base vision service"""
代码语言:javascript复制from mms.model_service.mxnet_model_serviceimport MXNetBaseService
代码语言:javascript复制from mms.utils.mxnetimport image, ndarray
代码语言:javascript复制class CustomService(MXNetBaseService):
代码语言:javascript复制"""
代码语言:javascript复制CustomService defines a custom service for image classification task. In preprocess,
代码语言:javascript复制input image buffer is read to NDArray and resized respect to input shape in signature.
代码语言:javascript复制In post process, top-2 labels are returned.
代码语言:javascript复制"""
代码语言:javascript复制
代码语言:javascript复制 def _preprocess(self, data):
代码语言:javascript复制 img_list= []
代码语言:javascript复制 for idx, imgin enumerate(data):
代码语言:javascript复制 input_shape= self.signature['inputs'][idx]['data_shape'] #Input shape is NCHW
代码语言:javascript复制 [h, w]= input_shape[2:]
代码语言:javascript复制 img_arr= image.read(img,0)#Set flag to 0 for reading grayscale images
代码语言:javascript复制 img_arr= image.resize(img_arr, w, h)
代码语言:javascript复制 img_arr= image.transform_shape(img_arr)
代码语言:javascript复制 img_list.append(img_arr)
代码语言:javascript复制 return img_list
代码语言:javascript复制
代码语言:javascript复制 def _postprocess(self, data):
代码语言:javascript复制 assert hasattr(self,'labels'),
代码语言:javascript复制 "Can't find labels attribute. Did you put synset.txt file into "
代码语言:javascript复制 "model archive or manually load class label file in __init__?"
代码语言:javascript复制 return [ndarray.top_probability(d,self.labels, top=2)for din data]
然后,我们使用keras-mms目录中的文件使用以下命令生成MMS .model文件:
代码语言:javascript复制mxnet-model-export--model-name smileCNN--model-path。--service-file-path custom_service.py
这会生成smileCNN.model文件。简而言之,此文件包含将我们的模型作为带有MMS的Web服务运行所需的所有依赖项的东西。
最后,我们运行此命令来启动服务器:
代码语言:javascript复制mxnet-model-server--models smileCNN= smileCNN.model
现在模型服务器已启动并可以使用!是时候测试模型了!
注意:下面的所有图像都已按比例放大,以便查看
测试图像
测试1.JPG
代码语言:javascript复制curl-X POST http://127.0.0.1:8080/smileCNN/predict-F"/conv2d_1_input1=@test-1.jpg"
得出的预测:
代码语言:javascript复制{
代码语言:javascript复制 "prediction": [
代码语言:javascript复制 [
代码语言:javascript复制 {
代码语言:javascript复制 "class":"smiling",
代码语言:javascript复制 "probability":1.0
代码语言:javascript复制 },
代码语言:javascript复制 {
代码语言:javascript复制 "class":"non-smiling",
代码语言:javascript复制 "probability":0.0
代码语言:javascript复制 }
代码语言:javascript复制 ]
代码语言:javascript复制 ]
代码语言:javascript复制}
这就是使用Keras和MXNet后端训练模型并通过MXNet模型服务器进行推理的过程。
由于MXNet模型服务器对其进行舍入(round)时,模型的推断概率可能会出现偏差。
为了进一步评估模型,我们使用不同的示例对其进行测试。
测试2.JPG
代码语言:javascript复制curl-X POST http://127.0.0.1:8080/smileCNN/predict-F“/conv2d_1_input1=@test-2.jpg”
得出的预测
代码语言:javascript复制{
代码语言:javascript复制 "prediction": [
代码语言:javascript复制 [
代码语言:javascript复制 {
代码语言:javascript复制 "class":"non-smiling",
代码语言:javascript复制 "probability":1.0
代码语言:javascript复制 },
代码语言:javascript复制 {
代码语言:javascript复制 "class":"smiling",
代码语言:javascript复制 "probability":0.0
代码语言:javascript复制 }
代码语言:javascript复制 ]
代码语言:javascript复制 ]
代码语言:javascript复制}
我们可以看到这个简单的CNN模型所做的预测已经非常好了!
这是只是个做来玩的模型,但它是可以有实际应用的应用程序。例如,为了确保你的同事在进入办公室时总是面带微笑,你可以在办公室前门上方添加一个网络摄像头,需要笑脸才能进入大楼!:)(我认为,需要面带微笑才能离开大楼比较现实)
了解更多
Keras-MXNet的最新版本使用户以更高的速度训练大型模型,并以MXNet原生格式导出经过训练的模型,允许在多个平台上进行推理,包括MXNet模型服务。要了解更多相关信息,请访问下方链接。
https://github.com/awslabs/keras-apache-mxnet
https://github.com/awslabs/mxnet-model-server