使用PaddlePaddle2.0高层API完成基于VGG16的图像分类任务
下载安装命令 ## CPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle ## GPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu
本示例教程将会演示如何使用飞桨的卷积神经网络来完成目标检测任务。这是一个较为简单的示例,将会使用飞桨框架内置模型VGG16网络完成Cifar10数据集的图像分类任务。
一、PaddlePaddle2.0新亮点——高层API助力开发者快速上手深度学习飞桨致力于让深度学习技术的创新与应用更简单
1.模型组网更简单
对于新手来说,完全可以省去以往复杂的组网代码,一行代码便可以完成组网。
目前PaddlePaddle2.0-rc1的内置模型有:
‘ResNet’, ‘resnet18’, ‘resnet34’, ‘resnet50’, ‘resnet101’, ‘resnet152’, ‘VGG’, ‘vgg11’, ‘vgg13’, ‘vgg16’, ‘vgg19’, ‘MobileNetV1’, ‘mobilenet_v1’, ‘MobileNetV2’, ‘mobilenet_v2’, ‘LeNet’
使用一行代码便可以加载:
ModelName = paddle.vision.models.ModelName()
(将ModelName替换成上面的模型名称即可,模型名称后面别忘了加括号!!!)
2.模型训练更简单
PaddlePaddle2.0-rc1增加了paddle.Model高层API,大部分任务可以使用此API用于简化训练、评估、预测类代码开发。
使用两句代码便可以训练模型:
# 训练前准备 ModelName.prepare( paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters()), paddle.nn.CrossEntropyLoss(), paddle.metric.Accuracy(topk=(1, 2)) ) # 启动训练 ModelName.fit(train_dataset, epochs=2, batch_size=64, log_freq=200)
二、使用飞桨快速加载VGG网络并查看模型结构
Very Deep Convolutional Networks For Large-Scale Image Recognition 论文地址:https://arxiv.org/pdf/1409.1556.pdf
1.查看飞桨框架内置模型
import paddle print('飞桨框架内置模型:', paddle.vision.models.__all__)
飞桨框架内置模型: ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', 'resnet152', 'VGG', 'vgg11', 'vgg13', 'vgg16', 'vgg19', 'MobileNetV1', 'mobilenet_v1', 'MobileNetV2', 'mobilenet_v2', 'LeNet']
2.一行代码加载VGG16
vgg16 = paddle.vision.models.vgg16()
3.查看VGG16的网络结构及参数
paddle.summary(vgg16, (64, 3, 32, 32))
------------------------------------------------------------------------------- Layer (type) Input Shape Output Shape Param # =============================================================================== Conv2D-1 [[64, 3, 32, 32]] [64, 64, 32, 32] 1,792 ReLU-1 [[64, 64, 32, 32]] [64, 64, 32, 32] 0 Conv2D-2 [[64, 64, 32, 32]] [64, 64, 32, 32] 36,928 ReLU-2 [[64, 64, 32, 32]] [64, 64, 32, 32] 0 MaxPool2D-1 [[64, 64, 32, 32]] [64, 64, 16, 16] 0 Conv2D-3 [[64, 64, 16, 16]] [64, 128, 16, 16] 73,856 ReLU-3 [[64, 128, 16, 16]] [64, 128, 16, 16] 0 Conv2D-4 [[64, 128, 16, 16]] [64, 128, 16, 16] 147,584 ReLU-4 [[64, 128, 16, 16]] [64, 128, 16, 16] 0 MaxPool2D-2 [[64, 128, 16, 16]] [64, 128, 8, 8] 0 Conv2D-5 [[64, 128, 8, 8]] [64, 256, 8, 8] 295,168 ReLU-5 [[64, 256, 8, 8]] [64, 256, 8, 8] 0 Conv2D-6 [[64, 256, 8, 8]] [64, 256, 8, 8] 590,080 ReLU-6 [[64, 256, 8, 8]] [64, 256, 8, 8] 0 Conv2D-7 [[64, 256, 8, 8]] [64, 256, 8, 8] 590,080 ReLU-7 [[64, 256, 8, 8]] [64, 256, 8, 8] 0 MaxPool2D-3 [[64, 256, 8, 8]] [64, 256, 4, 4] 0 Conv2D-8 [[64, 256, 4, 4]] [64, 512, 4, 4] 1,180,160 ReLU-8 [[64, 512, 4, 4]] [64, 512, 4, 4] 0 Conv2D-9 [[64, 512, 4, 4]] [64, 512, 4, 4] 2,359,808 ReLU-9 [[64, 512, 4, 4]] [64, 512, 4, 4] 0 Conv2D-10 [[64, 512, 4, 4]] [64, 512, 4, 4] 2,359,808 ReLU-10 [[64, 512, 4, 4]] [64, 512, 4, 4] 0 MaxPool2D-4 [[64, 512, 4, 4]] [64, 512, 2, 2] 0 Conv2D-11 [[64, 512, 2, 2]] [64, 512, 2, 2] 2,359,808 ReLU-11 [[64, 512, 2, 2]] [64, 512, 2, 2] 0 Conv2D-12 [[64, 512, 2, 2]] [64, 512, 2, 2] 2,359,808 ReLU-12 [[64, 512, 2, 2]] [64, 512, 2, 2] 0 Conv2D-13 [[64, 512, 2, 2]] [64, 512, 2, 2] 2,359,808 ReLU-13 [[64, 512, 2, 2]] [64, 512, 2, 2] 0 MaxPool2D-5 [[64, 512, 2, 2]] [64, 512, 1, 1] 0 AdaptiveAvgPool2D-1 [[64, 512, 1, 1]] [64, 512, 7, 7] 0 Linear-1 [[64, 25088]] [64, 4096] 102,764,544 ReLU-14 [[64, 4096]] [64, 4096] 0 Dropout-1 [[64, 4096]] [64, 4096] 0 Linear-2 [[64, 4096]] [64, 4096] 16,781,312 ReLU-15 [[64, 4096]] [64, 4096] 0 Dropout-2 [[64, 4096]] [64, 4096] 0 Linear-3 [[64, 4096]] [64, 1000] 4,097,000 =============================================================================== Total params: 138,357,544 Trainable params: 138,357,544 Non-trainable params: 0 ------------------------------------------------------------------------------- Input size (MB): 0.75 Forward/backward pass size (MB): 309.99 Params size (MB): 527.79 Estimated Total Size (MB): 838.53 ------------------------------------------------------------------------------- {'total_params': 138357544, 'trainable_params': 138357544}
三、使用飞桨框架API加载数据集
飞桨框架将一些我们常用到的数据集作为领域API对用户进行开放,对应API所在目录为paddle.vision.datasets与paddle.text.datasets
目前已经收录的数据集有:
视觉相关数据集: [‘DatasetFolder’, ‘ImageFolder’, ‘MNIST’, ‘FashionMNIST’, ‘Flowers’, ‘Cifar10’, ‘Cifar100’, ‘VOC2012’]
自然语言相关数据集: [‘Conll05st’, ‘Imdb’, ‘Imikolov’, ‘Movielens’, ‘UCIHousing’, ‘WMT14’, ‘WMT16’]
1.快速加载数据集
使用一行代码即可加载数据集到本机缓存目录~/.cache/paddle/dataset:
paddle.vision.datasets.DataSetName()
将DataSetName替换成上述数据集名称即可,别忘了名称后面跟一个小括号!
from paddle.vision.transforms import ToTensor # 训练数据集 用ToTensor将数据格式转为Tensor train_dataset = paddle.vision.datasets.Cifar10(mode='train', transform=ToTensor()) # 验证数据集 val_dataset = paddle.vision.datasets.Cifar10(mode='test', transform=ToTensor())
2.对训练数据做数据增强
训练过程中有时会遇到过拟合的问题,其中一个解决方法就是对训练数据做增强,对数据进行处理得到不同的图像,从而泛化数据集。
查看飞桨框架提供的数据增强方法:
import paddle print('数据处理方法:', paddle.vision.transforms.__all__)
数据处理方法: ['BaseTransform', 'Compose', 'Resize', 'RandomResizedCrop', 'CenterCrop', 'RandomHorizontalFlip', 'RandomVerticalFlip', 'Transpose', 'Normalize', 'BrightnessTransform', 'SaturationTransform', 'ContrastTransform', 'HueTransform', 'ColorJitter', 'RandomCrop', 'Pad', 'RandomRotation', 'Grayscale', 'ToTensor', 'to_tensor', 'hflip', 'vflip', 'resize', 'pad', 'rotate', 'to_grayscale', 'crop', 'center_crop', 'adjust_brightness', 'adjust_contrast', 'adjust_hue', 'normalize']
from paddle.vision.transforms import Compose, Resize, ColorJitter, ToTensor, RandomHorizontalFlip, RandomVerticalFlip, RandomRotation import numpy as np from PIL import Image # 定义想要使用那些数据增强方式,这里用到了随机调整亮度、对比度和饱和度、图像翻转等 transform = Compose([ColorJitter(), RandomHorizontalFlip(), ToTensor()]) # 通过transform参数传递定义好的数据增项方法即可完成对自带数据集的应用 train_dataset = paddle.vision.datasets.Cifar10(mode='train', transform=transform) # 验证数据集 val_dataset = paddle.vision.datasets.Cifar10(mode='test', transform=transform)
这里需要注意的坑是,一定要把ToTensor()放在最后,否则会报错
检查数据集:
train_loader = paddle.io.DataLoader(train_dataset, batch_size=64, shuffle=True) for batch_id, data in enumerate(train_loader()): x_data = data[0] y_data = data[1] break print(x_data.numpy().shape) print(y_data.numpy().shape)
(64, 3, 32, 32) (64,)
四、使用高层API进行模型训练、验证与测试
飞桨框架提供了两种训练与预测的方法:
- 一种是用paddle.Model对模型进行封装,通过高层API如Model.fit()、Model.evaluate()、Model.predict()等完成模型的训练与预测;
- 另一种就是基于基础API常规的训练方式。
使用高层API只需要改动少量参数即可完成模型训练,对新手小白真的特别友好!
1.调用fit()接口来启动训练过程
import paddle from paddle.vision.transforms import ToTensor from paddle.vision.models import vgg16 # build model model = vgg16() # build vgg16 model with batch_norm model = vgg16(batch_norm=True) # 使用高层API——paddle.Model对模型进行封装 model = paddle.Model(model) # 为模型训练做准备,设置优化器,损失函数和精度计算方式 model.prepare(optimizer=paddle.optimizer.Adam(parameters=model.parameters()), loss=paddle.nn.CrossEntropyLoss(), metrics=paddle.metric.Accuracy()) # 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式 model.fit(train_dataset, epochs=10, batch_size=256, save_dir="vgg16/", save_freq=10, verbose=1)
The loss value printed in the log is the current step, and the metric is the average value of previous step. Epoch 1/10 step 196/196 [==============================] - loss: 2.3752 - acc: 0.1054 - 202ms/step save checkpoint at /home/aistudio/vgg16/0 Epoch 2/10 step 196/196 [==============================] - loss: 2.2819 - acc: 0.1114 - 203ms/step Epoch 3/10 step 196/196 [==============================] - loss: 2.2614 - acc: 0.1306 - 201ms/step Epoch 4/10 step 196/196 [==============================] - loss: 2.2229 - acc: 0.1822 - 195ms/step Epoch 5/10 step 196/196 [==============================] - loss: 1.9132 - acc: 0.1846 - 198ms/step Epoch 6/10 step 196/196 [==============================] - loss: 1.7738 - acc: 0.2000 - 194ms/step Epoch 7/10 step 196/196 [==============================] - loss: 1.8450 - acc: 0.2286 - 195ms/step Epoch 8/10 step 196/196 [==============================] - loss: 1.5770 - acc: 0.2782 - 198ms/step Epoch 9/10 step 196/196 [==============================] - loss: 1.5743 - acc: 0.3446 - 195ms/step Epoch 10/10 step 196/196 [==============================] - loss: 1.4283 - acc: 0.4043 - 201ms/step save checkpoint at /home/aistudio/vgg16/final
看到loss在明显下降、acc在明显上升,说明模型效果还不错,剩下需要慢慢调参优化
2.调用evaluate()在测试集上对模型进行验证
对于训练好的模型进行评估操作可以使用evaluate接口来实现,事先定义好用于评估使用的数据集后,可以简单的调用evaluate接口即可完成模型评估操作,结束后根据prepare中loss和metric的定义来进行相关评估结果计算返回。
# 用 evaluate 在测试集上对模型进行验证 eval_result = model.evaluate(val_dataset, verbose=1)
Eval begin... The loss value printed in the log is the current batch, and the metric is the average value of previous step. step 10000/10000 [==============================] - loss: 0.2509 - acc: 0.4379 - 10ms/step Eval samples: 10000
3.调用predict()接口进行模型测试
高层API中提供了predict接口来方便用户对训练好的模型进行预测验证,只需要基于训练好的模型将需要进行预测测试的数据放到接口中进行计算即可,接口会将经过模型计算得到的预测结果进行返回。
# 用 predict 在测试集上对模型进行测试 test_result = model.predict(val_dataset)
Predict begin... step 10000/10000 [==============================] - 10ms/step Predict samples: 10000
五、总结与展望——PaddlePaddle2.0 rc1入手指南
给大家总结一下我在使用PaddlePaddle2.0 rc1时遇到的坑,希望大家可以避免:
- 1.这个项目本来是使用VOC2012数据集进行目标检测任务的训练的,奈何VOC2012数据集的下载速度实在是太慢了,所以我果断放弃,希望后期可以找到解决办法
- 2.最好结合PaddlePaddle2.0的文档和GitHub上的源码来使用,特别是新手小白,不然出现一些报错可能会很难解决,可以多去GitHub上提issue
- 3.使用数据增强 Compose()方法时,切记!一定要把ToTensor()放在最后,这个问题看看源码就能解决
下载安装命令 ## CPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle ## GPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu六、个人介绍
北京联合大学 机器人学院 自动化专业 2018级 本科生 郑博培
百度飞桨开发者技术专家 PPDE
百度飞桨官方帮帮团、答疑团成员
深圳柴火创客空间 认证会员
百度大脑 智能对话训练师