【图像分类】使用经典模型进行图像分类

场景文字识别

图像相比文字能够提供更加生动、容易理解及更具艺术感的信息,是人们转递与交换信息的重要来源。图像分类是根据图像的语义信息对不同类别图像进行区分,是计算机视觉中重要的基础问题,也是图像检测、图像分割、物体跟踪、行为分析等其他高层视觉任务的基础,在许多领域都有着广泛的应用。如:安防领域的人脸识别和智能视频分析等,交通领域的交通场景识别,互联网领域基于内容的图像检索和相册自动归类,医学领域的图像识别等。

这里将介绍如何在PaddlePaddle下使用AlexNet、VGG、GoogLeNet、ResNet、Inception-v4、Inception-ResNet-v2和Xception模型进行图像分类。图像分类问题的描述和这些模型的介绍可以参考PaddlePaddle book。(https://github.com/PaddlePaddle/book/tree/develop/03.image_classification)

|1. 训练模型

[1]初始化

在初始化阶段需要导入所用的包,并对PaddlePaddle进行初始化。

import gzip

import argparse

import paddle.v2.dataset.flowers as flowers

import paddle.v2 as paddle

import reader

import vgg

import resnet

import alexnet

import googlenet

import inception_v4

import inception_resnet_v2

import xception

# PaddlePaddle init

paddle.init(use_gpu=False, trainer_count=1)

[2]定义参数和输入

设置算法参数(如数据维度、类别数目和batch size等参数),定义数据输入层image和类别标签lbl。 所用数据集是flowers(http://www.robots.ox.ac.uk/~vgg/data/flowers/102/)。花的种类是102,因此,CLASS_DIM=102。

# Use 3 * 331 * 331 or 3 * 299 * 299 for DATA_DIM in Inception-ResNet-v2.

DATA_DIM = 3 * 224 * 224

CLASS_DIM = 102

BATCH_SIZE = 128

image = paddle.layer.data(

name="image", type=paddle.data_type.dense_vector(DATA_DIM))

lbl = paddle.layer.data(

name="label", type=paddle.data_type.integer_value(CLASS_DIM))

[3]获得所用模型

这里可以选择使用AlexNet、VGG、GoogLeNet、ResNet、Inception-v4、Inception-ResNet-v2和Xception模型中的一个模型进行图像分类。通过调用相应的方法可以获得网络最后的Softmax层。

  • 使用AlexNet模型

指定输入层image和类别数目CLASS_DIM后,可以通过下面的代码得到AlexNet的Softmax层。

out = alexnet.alexnet(image, class_dim=CLASS_DIM)

  • 使用VGG模型

根据层数的不同,VGG分为VGG13、VGG16和VGG19。使用VGG16模型的代码如下:

out = vgg.vgg16(image, class_dim=CLASS_DIM)

类似地,VGG13和VGG19可以分别通过vgg.vgg13和vgg.vgg19方法获得。

  • 使用GoogLeNet模型

GoogLeNet在训练阶段使用两个辅助的分类器强化梯度信息并进行额外的正则化。因此googlenet.googlenet共返回三个Softmax层,如下面的代码所示:

out, out1, out2 = googlenet.googlenet(image, class_dim=CLASS_DIM)

loss1 = paddle.layer.cross_entropy_cost(

input=out1, label=lbl, coeff=0.3)

paddle.evaluator.classification_error(input=out1, label=lbl)

loss2 = paddle.layer.cross_entropy_cost(

input=out2, label=lbl, coeff=0.3)

paddle.evaluator.classification_error(input=out2, label=lbl)

extra_layers = [loss1, loss2]

对于两个辅助的输出,这里分别对其计算损失函数并评价错误率,然后将损失作为后文SGD的extra_layers。

  • 使用ResNet模型

ResNet模型可以通过下面的代码获取:

out = resnet.resnet_imagenet(image, class_dim=CLASS_DIM)

  • 使用Inception-v4模型

Inception-v4模型可以通过下面的代码获取, 本例中使用的模型输入大小为3 * 224 * 224 (原文献中使用的输入大小为3 * 299 * 299):

out = inception_v4.inception_v4(image, class_dim=CLASS_DIM)

  • 使用Inception-ResNet-v2模型

提供的Inception-ResNet-v2模型支持3 * 331 * 331和3 * 299 * 299两种大小的输入,同时可以自行设置dropout概率,可以通过如下的代码使用:

out = inception_resnet_v2.inception_resnet_v2(

image, class_dim=CLASS_DIM, dropout_rate=0.5, size=DATA_DIM)

注意,由于和其他几种模型输入大小不同,若配合提供的reader.py使用Inception-ResNet-v2时请先将reader.py中paddle.image.simple_transform中的参数为修改为相应大小。

  • 使用Xception模型

Xception模型可以通过下面的代码获取:

out = xception.xception(image, class_dim=CLASS_DIM)

[4]定义损失函数

cost = paddle.layer.classification_cost(input=out, label=lbl)

[5]创建参数和优化方法

# Create parameters

parameters = paddle.parameters.create(cost)

# Create optimizer

optimizer = paddle.optimizer.Momentum(

momentum=0.9,

regularization=paddle.optimizer.L2Regularization(rate=0.0005 *

BATCH_SIZE),

learning_rate=0.001 / BATCH_SIZE,

learning_rate_decay_a=0.1,

learning_rate_decay_b=128000 * 35,

learning_rate_schedule="discexp", )

通过 learning_rate_decay_a (简写a) 、learning_rate_decay_b (简写b) 和 learning_rate_schedule 指定学习率调整策略,这里采用离散指数的方式调节学习率,计算公式如下, n 代表已经处理过的累计总样本数,lr0 即为参数里设置的 learning_rate。

[6]定义数据读取

首先以花卉数据(http://www.robots.ox.ac.uk/~vgg/data/flowers/102/index.html)为例说明如何定义输入。下面的代码定义了花卉数据训练集和验证集的输入:

train_reader = paddle.batch(

paddle.reader.shuffle(

flowers.train(),

buf_size=1000),

batch_size=BATCH_SIZE)

test_reader = paddle.batch(

flowers.valid(),

batch_size=BATCH_SIZE)

若需要使用其他数据,则需要先建立图像列表文件。reader.py定义了这种文件的读取方式,它从图像列表文件中解析出图像路径和类别标签。

图像列表文件是一个文本文件,其中每一行由一个图像路径和类别标签构成,二者以跳格符(Tab)隔开。类别标签用整数表示,其最小值为0。下面给出一个图像列表文件的片段示例:

dataset_100/train_images/n03982430_23191.jpeg 1

dataset_100/train_images/n04461696_23653.jpeg 7

dataset_100/train_images/n02441942_3170.jpeg 8

dataset_100/train_images/n03733281_31716.jpeg 2

dataset_100/train_images/n03424325_240.jpeg 0

dataset_100/train_images/n02643566_75.jpeg 8

训练时需要分别指定训练集和验证集的图像列表文件。这里假设这两个文件分别为train.list和val.list,数据读取方式如下:

train_reader = paddle.batch(

paddle.reader.shuffle(

reader.train_reader('train.list'),

buf_size=1000),

batch_size=BATCH_SIZE)

test_reader = paddle.batch(

reader.test_reader('val.list'),

batch_size=BATCH_SIZE)

[7]定义事件处理程序

# End batch and end pass event handler

def event_handler(event):

if isinstance(event, paddle.event.EndIteration):

if event.batch_id % 1 == 0:

print "\nPass %d, Batch %d, Cost %f, %s" % (

event.pass_id, event.batch_id, event.cost, event.metrics)

if isinstance(event, paddle.event.EndPass):

with gzip.open('params_pass_%d.tar.gz' % event.pass_id, 'w') as f:

parameters.to_tar(f)

result = trainer.test(reader=test_reader)

print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics)

[8]定义训练方法

对于AlexNet、VGG、ResNet、Inception-v4、Inception-ResNet-v2和Xception,可以按下面的代码定义训练方法:

# Create trainer

trainer = paddle.trainer.SGD(

cost=cost,

parameters=parameters,

update_equation=optimizer)

GoogLeNet有两个额外的输出层,因此需要指定extra_layers,如下所示:

# Create trainer

trainer = paddle.trainer.SGD(

cost=cost,

parameters=parameters,

update_equation=optimizer,

extra_layers=extra_layers)

[9]开始训练

trainer.train(

reader=train_reader, num_passes=200, event_handler=event_handler)

|2.应用模型

模型训练好后,可以使用下面的代码预测给定图片的类别。

# load parameters

with gzip.open('params_pass_10.tar.gz', 'r') as f:

parameters = paddle.parameters.Parameters.from_tar(f)

file_list = [line.strip() for line in open(image_list_file)]

test_data = [(paddle.image.load_and_transform(image_file, 256, 224, False)

.flatten().astype('float32'), )

for image_file in file_list]

probs = paddle.infer(

output_layer=out, parameters=parameters, input=test_data)

lab = np.argsort(-probs)

for file_name, result in zip(file_list, lab):

print "Label of %s is: %d" % (file_name, result[0])

首先从文件中加载训练好的模型(代码里以第10轮迭代的结果为例),然后读取image_list_file中的图像。image_list_file是一个文本文件,每一行为一个图像路径。代码使用paddle.infer判断image_list_file中每个图像的类别,并进行输出。

|3. 使用预训练模型

为方便进行测试和fine-tuning,我们提供了一些对应于示例中模型配置的预训练模型,目前包括在ImageNet 1000类上训练的ResNet50、ResNet101和Vgg16,请使用models目录下的脚本model_download.sh进行模型下载,如下载ResNet50可进入models目录并执行"sh model_download.sh ResNet50",完成后同目录下的Paddle_ResNet50.tar.gz即是训练好的模型,可以在代码中使用如下两种方式进行加载模:

parameters = paddle.parameters.Parameters.from_tar(gzip.open('Paddle_ResNet50.tar.gz', 'r'))

parameters = paddle.parameters.create(cost)

parameters.init_from_tar(gzip.open('Paddle_ResNet50.tar.gz', 'r'))

注意事项

模型压缩包中所含各文件的文件名和模型配置中的参数名一一对应,是加载模型参数的依据。我们提供的预训练模型均使用了示例代码中的配置,如需修改网络配置,请多加注意,需要保证网络配置中的参数名和压缩包中的文件名能够正确对应。

原文发布于微信公众号 - PaddlePaddle(PaddleOpenSource)

原文发表时间:2018-03-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器学习算法工程师

从0 到1 实现YOLO v3(part two)

本部分是 从0到1 实现YOLO v3 的第二部分 的第二部分,前两部分主要介绍了YOLO的工作原理,包含的模块的介绍以及如何用pytorch搭建完整的YOL...

7744
来自专栏fangyangcoder

tensorflow笔记(二)之构造一个简单的神经网络

http://www.cnblogs.com/fydeblog/p/7425200.html

1272
来自专栏数据派THU

12张动图解析深度学习中的卷积网络

来源:机器人圈 本文长度为2178字,建议阅读4分钟 本文通过12张动图为你介绍深度学习中的卷积网络。 现如今,卷积神经网络在人工智能领域应用的广泛性及重要性可...

4339
来自专栏超智能体

YJango:TensorFlow高层API Custom Estimator建立CNN+RNN的演示

该文是YJango:TensorFlow中层API Datasets+TFRecord的数据导入的后续。

1.4K7
来自专栏决胜机器学习

从机器学习学python(四) ——numpy矩阵广播及一些技巧

从机器学习学python(四)——numpy矩阵广播及一些技巧 (原创内容,转载请注明来源,谢谢) 在学ng的深度学习微专业时,其中有几节课讲到numpy的一...

4384
来自专栏AI研习社

如何使用注意力模型生成图像描述?

我们的目标是用一句话来描述图片, 比如「一个冲浪者正在冲浪」。 本教程中用到了基于注意力的模型,它使我们很直观地看到当文字生成时模型会关注哪些部分。

2022
来自专栏IT派

教程 | 如何使用纯NumPy代码从头实现简单的卷积神经网络

在某些情况下,使用 ML/DL 库中已经存在的模型可能会很便捷。但为了更好地控制和理解模型,你应该自己去实现它们。本文展示了如何仅使用 NumPy 库来实现 C...

1382
来自专栏人工智能头条

Keras/Python深度学习中的网格搜索超参数调优(上)

7196
来自专栏大数据挖掘DT机器学习

用python实现支持向量机对婚介数据的用户配对预测

网上有人用libsvm2.89在Python2.6成功。(一定要libsvm2.89搭配python2.6,其他版本都不能成功,我就是浪费了大量时间在这里!) ...

3845
来自专栏磐创AI技术团队的专栏

十 | 门控循环神经网络LSTM与GRU(附python演练)

门控循环神经网络在简单循环神经网络的基础上对网络的结构做了调整,加入了门控机制,用来控制神经网络中信息的传递。门控机制可以用来控制记忆单元中的信息有多少需要保留...

1001

扫码关注云+社区

领取腾讯云代金券