HelloPaddle01-从头搭建图像识别模型教程

Posted Charlotte数据挖掘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HelloPaddle01-从头搭建图像识别模型教程相关的知识,希望对你有一定的参考价值。


关注&置顶“Charlotte数据挖掘


每日9:00,干货速递!


By    Charlotte77


前言:本文属于付费征稿,作者为HelloGitHub组织,每两周更新一篇PaddlePaddle教程,写的非常详细,可以直接按照教程操作~有对PaddlePaddle感兴趣的同学们也可以投稿哦~



一、图像识别、Cifar-10、PaddlePaddle 简介


1.1 图像识别

计算机视觉领域最基础也是最简单的一项任务,目的就是识别一张图中的目标属于什么种类。


1.2 Cifar-10 数据集

Cifar-10 数据集,一个小型的公开的图像分类的数据集,是从一个数量较多的无标注的数据集TinyImage(小图) 标注而来,共分为10类,下图可以直观的看到图像和种类:



既然是从 TinyImage 而来,Cifar 数据集的图像尺寸是比较小的,高宽的尺寸为 32x32。从上图中也可以看出来,有些图肉眼已经很难分辨是什么。但是今天我们要让程序自己来识别每张图是什么。肉眼不易识别的图片通过程序来识别,听起来还是挺酷的。但是实现起来很简单,原理也通俗易懂,只要你对数学有一定的了解、会一些 Python 的编程基础,跟着我一步步编写和运行就可以实现了。


继续说 Cifar-10 数据集,整个数据集分为训练集和测试集:

  1. 训练集 50000 张图,每类 10000 张

  2. 测试集 10000张图,每类1000张


Python版本数据点击下载 来下载,下载好了解压,在数据文件夹 cifar-10-batches-py 可以看到训练集分为 5 个批次,分别为 data_batch[1-5],详细的信息可以通过 readme.html 来看到。


1.3 PaddlePaddle


百度研发并开源的一个深度学习框架,我上手后使用的整体感觉较 TensorFlow 好用、方便一些。但上手难度要高于 PyTorch。在官方介绍中 Paddle 对于大规模工业生产、大数据集环境具有较大优势。由于我们本系列的教程主要以上手 Paddle 为主,而且本机环境也不是多机多卡的环境,所以还没体验过大规模多机多卡的并行训练,就不再着重介绍这一块了。


在百度近些年的积累和开发迭代 Paddle的进程中, Paddle在各个人工智能方向提供的预训练资源相对比较丰富。尤其是 NLP 领域,其中ERNIE 在中文NLP 各项任务中更是超越Google 1 8年网红模型BERT,具体信息可以去 Paddle 官方仓库 查看。


Paddle 文档全面清晰,同时对新手还有一定的福利 —— “PaddlePaddle 用户可领取免费 Tesla V100 在线算力资源、高效训练模型,每日登陆即送 12 小时,连续 5 天运行再加送 48小时。”对于刚进入深度学习没有 GPU 资源的同学来说,可以说是十分人性化了。我出机器让你用 Paddle 也是看到了百度要把 Paddle 做好的决心。


总的来说 PaddlePaddle 作为百度官方主推和维护的深度学习框架,在项目维护、资源更新、框架升级等方面具有强大的保障。在此基础上 Paddle 在易用上、工业生产上、用户量等方面一定会更上一层楼。那么就让我们“笨鸟先飞”,跟随HelloPaddle 系列教程,体验下 Paddle 的魅力吧!


二、PaddlePaddle图像分类


OK.下面我们开始进入正题,使用Paddle搭建一个深度学习模型来实现图像分类。

图像分类一直是人工智能和模型识别领域重要的一项任务,那么该如何让机器自己能图像分类呢?


首先,我们需要对数字图像有一定的了解,数字图像本质上是由大量数字组成的像素矩阵,比如我们上面说的Cifar-10的每张图其实对机器来说便是一个(32,32,3)的矩阵,这个矩阵中并非所有数字都对机器有用,存在大量的冗余,那么我们可以对这个矩阵进行抽取关键信息,假设我们这是一个简单的分类任务,分类所需的变换只是线性的,即 *y=a1*x1+a2*x2..+b*,这里的x1,x2..是我们抽取的关键信息,而对于同一类图像,我们认为抽取到的关键信息是相似的,不同类的图像抽取的信息是不同的,极端一点,我们假设同一类图像抽取的关键信息都是相同的,那么对于同一映射关系*y=a1*x1+a2*x2..+b*,同一类的图得到的结果是相同的,不同类的图得到的结果是不同的,由此,机器便可以通过一个函数得到分类的结果。


从本质上来说,图像分类的原理就是如此简单,只不过关键信息提取不像我们说的这么简单,函数也并不是线性的变换关系而是更复杂,但是这并不妨碍我们这样理解。


接下来,我们进入实战,首先导入我们所需的一些python包:


import numpy as np 
import cv2 
import matplotlib.pyplot as plt 
import pickle 
import os 
import sys 
import paddle.fluid as fluid 
from PIL import Image


接下来,我们定义刚刚下载并解压的Cifar-10的目录路径:

1data_dir ='/home/meteo/xibin.yue/paddle/data/cifar-10-batches-py'


接下来,要多说几句了,对于一个深度学习模型的实现,大概可以分为几个步骤:


  1. 准备数据并对数据做一些预处理,写一个可以将数据传入模型的模块,一般情况下各个框架都封装了数据加载以及预处理模块,Paddle也有,但我们今天要自己写一个数据加载模块来加深理解。

  2. 搭建模型,各个框架也有现成的各种模型和预训练参数

  3. 定义优化目标函数,通常在机器学习里叫做“损失函数” ,loss function或者cost

  4. 定义优化器。优化器的定义这方面,每个框架都进行了封装,我们只要调用就可以了,但是具体的超参数的设置和参数调整需要我们根据训练情况来定,同时大家需要去理解和掌握一些概念,最基础的包括学习率、正则化、优化方法(包括SGD,Adadelta,Adam等)

  5. 训练和应用。训练的过程便是机器学习的过程,机器学习好了会将这部分记忆存储下来,再应用的时候调取这部分记忆就可以进行处理各种问题了。


首先是数据加载模块:Paddle中定义了几种数据读取方式,最基础的为reader,在reader之上,Paddle封装了readercreator和reader decorator。readercreator给我们返回一个reader,readerdecorator可以组合多个reader,这个功能在做数据或者特征组合的时候应该很有用,后面如果用到会讲到。重点在这个reader,Paddle的reader本质上是一个迭代器,使用yield实现,python的yield不是特别了解的可以去看一下,我基本理解为是一个迭代的return。

接下来我们来定义一个CifarDataReader,它本质上类似于Paddle的reader creator。


数据加载模块

class CifarDataReader(object):
    """Cifar-10 Data Reader. 
    Provide a reader to read cifar 10 data iterable.

    Attributes:
        root_dir: root dir for cifar-10 data
        data_property: data for train or for validation or test
        cycle: if return data cyclic
    """


    def __init__(self, root_dir, data_property='train', cycle=True): 
        self.root_dir = root_dir
        self.data_property = data_property
        self.cycle = cycle

    def _load_cifar(self, data_path):
        try:
            data_dict = pickle.load(open(data_path, 'rb'))  # cifar python data 是二进制格式,可以用pickle加载
            raw_data = data_dict['data']
            label_data = data_dict['labels']
            batch_anno = data_dict['batch_label']
            raw_data = raw_data.reshape(10000,3,32,32).astype(np.float32) / 255.
            return raw_data, label_data, batch_anno
        except Exception as e:
            print e

    def reader(self):
        while True:
            if self.data_property == 'train':
                for batch_id in range(16):   # 训练集共5个批次
                    file_path = os.path.join(self.root_dir, 'data_batch_%d' % batch_id)
                    raw_data, label_data, batch_anno = self._load_cifar(file_path)
#                     print 'BATCH INFO - %s' % batch_anno.upper()
                    length = raw_data.shape[0]
                    for i in range(length):
                        yield raw_data[i], label_data[i]
                if not self.cycle:   #如果不使用cycle 读完一遍跳出
                    break
            else:
                file_path = os.path.join(self.root_dir, 'test_batch')
                print file_path
                raw_data, label_data, batch_anno = self._load_cifar(file_path)
#                 print 'BATCH INFO - %s' % batch_anno.upper()
                length = raw_data.shape[0]
                for i in range(length):
                    yield raw_data[i], label_data[i]
                if not self.cycle:
                    break

下面我们其实可以测试一下我们定义的CifarDataReader:

 1In [28]:
2
3demo_reader = CifarDataReader('/home/meteo/xibin.yue/paddle/data/cifar-10-batches-py',cycle=False)
4
5for item in demo_reader.reader():
6img = (item[0]* 255).transpose(1,2,0).astype(np.uint8)
7im = Image.fromarray(img)
8im.save('test_cv_channel.png'# 存一张备用
9print im.size
10plt.imshow(im)
11plt.show()
12break

output:

HelloPaddle01-从头搭建图像识别模型教程


可以看到,可以成功迭代的获取到数据,你能看出这是张青蛙么[汗]。但是这里感觉需要讲下图像的通道顺序问题,由于cifar-10原始数据是以二进制数据存储,我们读进来直接进行了reshape,这里的reshape之后的通道顺序其实为RGB,所以我们在训练的过程中其实是按照RGB的顺序训练的,这一点与Caffe不

同,caffe的用户这里需要注意一下,因为caffe底层其实是用的cv2,cv2加载图像的通道顺序为BGR,而PIL的Image库中直接open的图像的顺序为RGB,因此在训练好模型之后进行inference的时候,如果用到cv2进行图像加载,需要将BGR转化为RGB,而如果用Image读取的话,不需要这一步操作。


下面展示了Image和cv2读取图像的不同之处:

 1In [27]:
2
3img = cv2.imread('test_cv_channel.png')
4
5im = Image.fromarray(img)
6
7plt.imshow(im)
8
9plt.show()
10
11im2 = Image.open('test_cv_channel.png')
12
13plt.imshow(im2)



接下来我们用Paddle定义一个卷积神级网络,卷积神经网络-Convolutional NeuralNetwork,本质上是我们上面说的信息抽取模块,最早由两位生物学家提出,是一种一定意义上具有仿生学机理的网络,最初被用在视觉上,目前在语音以及NLP领域均有应用。卷积的概念也很早,在没有深度学习之前,做图像处理用到的各种算子、滤波器很多都是卷积操作。自Lecun提出Lenet之后,以及Hinton提出逐层初始化和训练,伴随着GPU和数据量的发展,深度学习飞速发展,因此也引领了这一波人工智能智能的浪潮。


卷积神经网络在前几年得到了长足的发展,包括网络结构的不断迭代优化、训练方法的优化、各种训练技巧等等,这里不再深入细讲了,讲起来就太多了。


在图像识别领域,由于早年ILSVRC比赛中ImageNet数据集,吸引了一批又一批的人提出了一个又一个经典的网络模型,如AlexNet、VGG、GoogleNet、ResNet、Densenet等等,识别准确率也一再被刷新。


今天我们用Paddle自己搭一个简单的网络,基本会用到卷积神经网络的主要操作,包括卷积、Pooling、Batch Noramlization、Dropout、FC、softmax等。


网络结构模块

def paddlenet(input):
    def conv_block(ipt, num_filter, groups, dropouts):
        return fluid.nets.img_conv_group(
            input=ipt,
            pool_size=2,
            pool_stride=2,
            conv_num_filter=[num_filter] * groups,
            conv_filter_size=3,
            conv_act='relu',
            conv_with_batchnorm=True,
            conv_batchnorm_drop_rate=dropouts,
            pool_type='max')  # 这里是Paddle官方封装的一个组合层,可以定义卷积参数,包括分组卷积、pooling参数、是否使用BN和Dropout 我们直接拿来用

    conv1 = conv_block(input, 321, [0.3])
    conv2 = conv_block(conv1, 641, [0.4]) 
    conv3 = conv_block(conv2, 1281, [0.4])  # 这里不分组,只许设定一个drop比例 如果用分组的话 需要设置多个
    fc1 = fluid.layers.fc(input=conv3, size=256, act=None)
    fc2 = fluid.layers.fc(input=fc1, size=512, act=None)
    predict = fluid.layers.fc(input=fc2, size=10, act='softmax')
    return predict

      上面我们没有用分组卷积,分组卷积或者channel之间的信息融合,大家可以去参考shufflenet以及后面的轻量化模型MobileNet等。其实分组卷积最早在AlexNet的时候就出现了,当时只是因为一块GPU无法完成训练,所以分在了两块GPU上,后面大家觉得channel之间需要进行信息共享和交换,便研究了各种分组卷积的模型。


下面是官网提供的vgg模型,大家可以作为参考。VGG模型大家也可以去网络学习一下。

 1def vgg_bn_drop(input):
2 def conv_block(ipt, num_filter, groups, dropouts):
3    return fluid.nets.img_conv_group(
4        input=ipt,
5        pool_size=2,
6        pool_stride=2,
7        conv_num_filter=[num_filter] * groups,
8        conv_filter_size=3,
9        conv_act='relu',
10        conv_with_batchnorm=True,
11        conv_batchnorm_drop_rate=dropouts,
12        pool_type='max')
13
14conv1 = conv_block(input, 64, 2, [0.3, 0])
15conv2 = conv_block(conv1, 128, 2, [0.4, 0])
16conv3 = conv_block(conv2, 256, 3, [0.4, 0.4, 0])
17conv4 = conv_block(conv3, 512, 3, [0.4, 0.4, 0])
18conv5 = conv_block(conv4, 512, 3, [0.4, 0.4, 0])
19
20drop = fluid.layers.dropout(x=conv5, dropout_prob=0.5)
21fc1 = fluid.layers.fc(input=drop, size=512, act=None)
22bn = fluid.layers.batch_norm(input=fc1, act='relu')
23drop2 = fluid.layers.dropout(x=bn, dropout_prob=0.5)
24fc2 = fluid.layers.fc(input=drop2, size=512, act=None)
25predict = fluid.layers.fc(input=fc2, size=10, act='softmax')
26return predict


定义好了网络模型,我们定义一个前馈过程得到网络输出结果:

1def inference_network():
2data_shape = [3, 32, 32]  #顺序为C-H-W
3images = fluid.layers.data(name='pixel', shape=data_shape, dtype='float32')
4predict = paddlenet(images)
5return predict


然后定义我们的优化目标,一般分类任务的优化目标都为最小化交叉熵损失(交叉熵损失不熟的同学,需要自行去了解),下面是代码:

1def train_network(predict):
2label = fluid.layers.data(name='label', shape=[1], dtype='int64')
3cost = fluid.layers.cross_entropy(input=predict, label=label)
4avg_cost = fluid.layers.mean(cost)
5accuracy = fluid.layers.accuracy(input=predict, label=label)
6return [avg_cost, accuracy]


接下来,我们定义优化器,包括优化方式、学习率、权重衰减等参数,Paddle官方给的是Adam方式,同时官网支持很多其他的方式,如Adadelta等,具体可以在Paddle优化方式查看。个人常用SGD,包含一些正则化项(weight decay),Paddle里面也支持加入一些正则化项,这里就不加了,优化器定义如下:


1def optimizer_program():
2 return fluid.optimizer.SGD(learning_rate=0.01)


上面我们定义了简单固定的学习率learning_rate=0.01,其实在训练过程中,固定学习率的方式无法寻找到最优点,因此会有很多学习率变化策略,Paddle里也给我们封装了一些,在learning_rate_schedule模块,后面我们可以讨论下这块。至此,我们的数据加载模块、模型、目标函数、优化器均已定义好,下面需要将他们串在一起,就可以训练了。


首先,我们定义使用GPU还是CPU,Paddle里这个变量基本都被命名为Place,意思大概是在哪里训练吧,但总感觉不如device更契合

1use_cuda = True
2place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
3BATCH_SIZE = 128下面我们来生成训练和测试用的data reader对象:

1train_cifar = CifarDataReader('/home/meteo/xibin.yue/paddle      /data/cifar-10-batches-py',cycle=False)
2test_cifar = CifarDataReader('/home/meteo/xibin.yue/paddle/data/cifar-10-batches-py',data_property='test',cycle=False)
3
4# 这里的paddle.batch和paddle.reader.shuffle是在reader上层包装了一下 batch返回一批数据 shuffle是随机顺序
5train_reader =      paddle.batch(paddle.reader.shuffle(train_cifar.reader,buf_size=10000),batch_size = BATCH_SIZE)
6test_reader = paddle.batch(test_cifar.reader,batch_size = BATCH_SIZE)

 1feed_order = ['pixel', 'label']
2
3main_program = fluid.default_main_program()
4start_program = fluid.default_startup_program()# 这里类似于           TensorFlow里的Graph 具体的还没有深入看
5
6main_program.random_seed = 90
7start_program.random_seed = 90
8
9# 前馈
10predict = inference_network()
11avg_cost, acc = train_network(predict)
12
13test_program = main_program.clone(for_test=True)
14
15optimizer = optimizer_program()
16optimizer.minimize(avg_cost)
17
18exe = fluid.Executor(place)
19
20# 训练轮数
21EPOCH_NUM = 10
 1# 这里定义一个在训练过程中测试集准确率的模块
2def train_test(program, reader):
3count = 0
4feed_var_list = [program.global_block().var(var_name) for var_name in feed_order]
5feeder_test = fluid.DataFeeder(feed_list=feed_var_list, place=place)
6test_exe = fluid.Executor(place)
7accumulated = len([avg_cost, acc]) * [0]
8for tid, test_data in enumerate(reader()):
9    avg_cost_np = test_exe.run(program=program,feed=feeder_test.feed(test_data),fetch_list=[avg_cost, acc])
10    accumulated = [x[0] + x[1][0] for x in zip(accumulated, avg_cost_np)]
11    count += 1
12return [x / count for x in accumulated]
 2def train_loop():
3feed_var_list_loop = [main_program.global_block().var(var_name) for var_name in feed_order]
4feeder = fluid.DataFeeder(feed_list=feed_var_list_loop, place=place)
5exe.run(start_program)
6
7step = 0
8for pass_id in range(EPOCH_NUM):  # 这里的pass_id 便是epoch
9    for step_id, data_train in enumerate(train_reader()):
10        avg_loss_value = exe.run(main_program,feed=feeder.feed(data_train),fetch_list=[avg_cost, acc])
11        if step_id % 100 == 0:
12            print(" Pass %d, Batch %d, Cost %f, Acc %f" % 
13                  (pass_id, step_id,avg_loss_value[0], avg_loss_value[1]))
14        else:
15            sys.stdout.write('.')
16            sys.stdout.flush()
17        step += 1
18
19    avg_cost_test, accuracy_test = train_test(test_program, reader=test_reader)
20    print(' Test with Pass {0}, Loss {1:2.2}, Acc {2:2.2}'.format(pass_id, avg_cost_test, accuracy_test))
21
22
23    fluid.io.save_inference_model('../weights', ["pixel"],[predict], exe) # 保存参数
24
25    if pass_id == EPOCH_NUM - 1:
26        print("kpis train_cost %f" % avg_loss_value[0])
27        print("kpis train_acc %f" % avg_loss_value[1])
28        print("kpis test_cost %f" % avg_cost_test)
29        print("kpis test_acc %f" % accuracy_test)

下面是输出结果:

 1train_loop()
2
3Pass 0, Batch 0, Cost 3.474087, Acc 0.140625
4...................................................................................................
5Pass 100, Batch 0, Cost 1.813744, Acc 0.421875
6...................................................................................................
7Pass 200, Batch 0, Cost 1.573293, Acc 0.367188
8...................................................................................................
9Pass 300, Batch 0, Cost 1.641935, Acc 0.351562
10........................................................................................../home/meteo/xibin.yue/paddle/data/cifar-10-batches-py/test_batch
11
12Test with Pass 0, Loss 1.9, Acc 0.28
13
14Pass 0, Batch 1, Cost 1.620478, Acc 0.398438
15...................................................................................................
16Pass 100, Batch 1, Cost 1.602701, Acc 0.421875
17...................................................................................................
18Pass 200, Batch 1, Cost 1.376074, Acc 0.492188
19...................................................................................................
20Pass 300, Batch 1, Cost 1.400322, Acc 0.507812
21........................................................................................../home/meteo/xibin.yue/paddle/data/cifar-10-batches-py/test_batch
22
23Test with Pass 1, Loss 1.8, Acc 0.35
24
25Pass 0, Batch 2, Cost 1.518327, Acc 0.453125
26...................................................................................................
27Pass 100, Batch 2, Cost 1.464380, Acc 0.507812
28 ..................................................................................................
29Pass 200, Batch 2, Cost 1.274296, Acc 0.523438
30   ...................................................................................................
31Pass 300, Batch 2, Cost 1.457271, Acc 0.437500
32........................................................................................../home/meteo/xibin.yue/paddle/data/cifar-10-batches-py/test_batch
33
34Test with Pass 2, Loss 1.7, Acc 0.39
35
36Pass 0, Batch 3, Cost 1.388974, Acc 0.484375
37...................................................................................................
38Pass 100, Batch 3, Cost 1.184492, Acc 0.593750
39...................................................................................................
40Pass 200, Batch 3, Cost 1.370192, Acc 0.476562
41...................................................................................................
42Pass 300, Batch 3, Cost 1.327766, Acc 0.609375
43........................................................................................../home/meteo/xibin.yue/paddle/data/cifar-10-batches-py/test_batch
44
45 Test with Pass 3, Loss 1.8, Acc 0.34
46
47 Pass 0, Batch 4, Cost 1.470855, Acc 0.500000
48...................................................................................................
49Pass 100, Batch 4, Cost 1.296775, Acc 0.562500
50...................................................................................................
51Pass 200, Batch 4, Cost 1.268556, Acc 0.531250
52...................................................................................................
53Pass 300, Batch 4, Cost 1.146190, Acc 0.593750
54........................................................................................../home/meteo/xibin.yue/paddle/data/cifar-10-batches-py/test_batch
55
56Test with Pass 4, Loss 1.6, Acc 0.44
57
58Pass 0, Batch 5, Cost 1.108460, Acc 0.656250
59...................................................................................................
60Pass 100, Batch 5, Cost 1.362371, Acc 0.492188
61...................................................................................................
62Pass 200, Batch 5, Cost 1.284810, Acc 0.515625
63...................................................................................................
64Pass 300, Batch 5, Cost 1.169709, Acc 0.601562
65........................................................................................../home/meteo/xibin.yue/paddle/data/cifar-10-batches-py/test_batch
66
67Test with Pass 5, Loss 1.6, Acc 0.46
68
69Pass 0, Batch 6, Cost 1.276461, Acc 0.523438
70...................................................................................................
71Pass 100, Batch 6, Cost 1.149449, Acc 0.546875
72...................................................................................................
73Pass 200, Batch 6, Cost 1.262985, Acc 0.507812
74...................................................................................................
75 Pass 300, Batch 6, Cost 1.390151, Acc 0.539062
76........................................................................................../home/meteo/xibin.yue/paddle/data/cifar-10-batches-py/test_batch
77
78Test with Pass 6, Loss 1.6, Acc 0.39
79
80Pass 0, Batch 7, Cost 1.289596, Acc 0.546875
81...................................................................................................
82Pass 100, Batch 7, Cost 1.213763, Acc 0.507812
83...................................................................................................
84Pass 200, Batch 7, Cost 1.081227, Acc 0.656250
85...................................................................................................
86Pass 300, Batch 7, Cost 0.916016, Acc 0.710938
87........................................................................................../home/meteo/xibin.yue/paddle/data/cifar-10-batches-py/test_batch
88
89Test with Pass 7, Loss 1.6, Acc 0.46
90
91Pass 0, Batch 8, Cost 1.269660, Acc 0.554688
92...................................................................................................
93Pass 100, Batch 8, Cost 1.135844, Acc 0.609375
94...................................................................................................
95Pass 200, Batch 8, Cost 1.377947, Acc 0.562500
96...................................................................................................
97Pass 300, Batch 8, Cost 1.230803, Acc 0.523438
98........................................................................................../home/meteo/xibin.yue/paddle/data/cifar-10-batches-py/test_batch
99
100Test with Pass 8, Loss 1.6, Acc 0.45
101
102Pass 0, Batch 9, Cost 1.196927, Acc 0.546875
103...................................................................................................
104Pass 100, Batch 9, Cost 1.078637, Acc 0.671875
105...................................................................................................
106Pass 200, Batch 9, Cost 1.040397, Acc 0.625000
107...................................................................................................
108Pass 300, Batch 9, Cost 1.370309, Acc 0.468750
109........................................................................................../home/meteo/xibin.yue/paddle/data/cifar-10-batches-py/test_batch
110
111Test with Pass 9, Loss 1.6, Acc 0.4
112kpis    train_cost  1.278773
113kpis    train_acc   0.587500
114kpis    test_cost   1.620999
115kpis    test_acc    0.399328



训练完毕后,我们就要看下训练的效果了,由于上面模型是我们随意搭建的,所以准确率不是特别高,这不重要,重要的是大家一起走完整个流程。好的,下面我们来写inference阶段代码,也就是给一张图,让机器识别这张图属于什么种类,当然给的图最好是我们训练的10类之中的图,如果不是的话就涉及到另外一个问题了无样本学习,这里我们不进行讨论。

1def load_image(infer_file):
2im = Image.open(infer_file)
3im = im.resize((32, 32), Image.ANTIALIAS)
4
5im = np.array(im).astype(np.float32)
6im = im.transpose((2, 0, 1))  # CHW
7im = im / 255.0
8im = np.expand_dims(im, axis=0)
9return im


 1def infer(params_dirname=None):
2from PIL import Image
3place = fluid.CUDAPlace(0if use_cuda else fluid.CPUPlace()
4exe = fluid.Executor(place)
5inference_scope = fluid.core.Scope()
6
7img = load_image('test_cv_channel.png')
8
9with fluid.scope_guard(inference_scope):
10    [inference_program, feed_target_names,fetch_targets] = fluid.io.load_inference_model(params_dirname, exe)
11    inference_transpiler_program = inference_program.clone()
12
13    # 这里我感觉我要多说一点,因为我在官方文档没有看到对这一块的讲解。这一块其实是Paddle对前馈过程的一个转译,包括将卷积层和BN层的融合,
14    # BN层和relu层的融合,提前对卷积参数做BN操作的处理,在前馈过程中就不再需要进行BN,主要目的是为了加速,我之前测过caffe的,提前将
15    # BN融合到卷积参数可以大幅提高速度,但是caffe需要自己做一步操作merge bn,而Paddle官方进行了封装,这一点很赞。
16    t = fluid.transpiler.InferenceTranspiler()
17    t.transpile(inference_transpiler_program, place)
18
19
20    results = exe.run(
21        inference_program,
22        feed={feed_target_names[0]: img},
23        fetch_list=fetch_targets)
24
25    transpiler_results = exe.run(
26        inference_transpiler_program,
27        feed={feed_target_names[0]: img},
28        fetch_list=fetch_targets)
29
30    # 这里做了个比较 证明转译前和转译后结果一致
31    assert len(results[0]) == len(transpiler_results[0])
32    for i in range(len(results[0])):
33        np.testing.assert_almost_equal(results[0][i], transpiler_results[0][i], decimal=5)
34
35    # infer label
36    label_list = [
37        "airplane""automobile""bird""cat""deer""dog""frog",
38        "horse""ship""truck"
39    ]
40
41    print("infer results: %s" % label_list[numpy.argmax(results[0])])


好了,上面定义好了我们的推断模块,下面我们运行一下,用到的图就是我们上面存下来的那只青蛙,让我们来看下结果:


1import numpy
2infer('../weights')!


output:

infer results: frog


好的,机器已经识别出这是只青蛙了,哈哈,朋友们,下期再会!





-点击右下角 告诉大家你“在看”-

 


以上是关于HelloPaddle01-从头搭建图像识别模型教程的主要内容,如果未能解决你的问题,请参考以下文章

PyTorch从头搭建并训练一个神经网络模型(图像分类CNN)

手把手教你搭建一个神经网络(图像分类)

从零开始搭建深度学习验证码识别模型

手把手教你搭建神经网络(图像分割)

10分钟搭建你的第一个图像识别模型 | 附完整代码

一文教你用paddlepaddle实现猫狗分类