(二)PaddlePaddle神经网络模型的搭建、保存、使用(VGG16模型、CIFAR数据集)

用PaddlePaddle搭建VGG16模型,使用CIFAR数据集。并对训练好的模型进行保存、调用、预测实际的图片的类别。

(一)VGG模型是AlexNet模型之后一个非常有名的模型。该模型进一步加宽、加深了网络结构,它的核心是5组卷积操作,每两组之间用最大值池化(Max-Pooling)降维。同一组内采用多次连续的3x3卷积,而同一组内卷积的卷积核数目一样,所以卷积层有11、13、16、19层几种模型:

在这里插入图片描述

CIFAR-10数据集包含10个类别数量的图片数据集,图像为32pxX32px正方形彩色图,但比ImageNet数据集中的图像小很多,所以需要对CIFAR-10图片做一定的处理,卷积部分引入了BN层、随机丢弃(Dropout)操作,具体作用:

在这里插入图片描述

(二)VGG16模型搭建:

# 模型训练与保存
import os
import shutil
import paddle
paddle.enable_static()
import paddle.dataset.cifar as cifar
import paddle.fluid as fluid

# 定义VGG16神经网络
def vgg16(input, class_dim=10):
    def conv_block(conv, num_filter, groups):
        for i in range(groups):
            conv = fluid.layers.conv2d(input=conv,
                                       num_filters=num_filter,
                                       filter_size=3,
                                       stride=1,
                                       padding=1,
                                       act='relu')
        return fluid.layers.pool2d(input=conv, pool_size=2, pool_type='max', pool_stride=2)

    conv1 = conv_block(input, 64, 2)   # 循环2次卷积
    conv2 = conv_block(conv1, 128, 2)  # 循环2次卷积
    conv3 = conv_block(conv2, 256, 3)  # 循环3次卷积
    conv4 = conv_block(conv3, 512, 3)  # 循环3次卷积
    conv5 = conv_block(conv4, 512, 3)  # 循环3次卷积
    # 针对VGG模型缺点,创建BN层和随机丢弃(Dropout)操作,随机丢弃一些神经元,使网络模型稀疏,抑制梯度弥散,起到正则化效果防止过拟合
    fc1 = fluid.layers.fc(input=conv5, size=512)   # 全连接层
    dp1 = fluid.layers.dropout(x=fc1, dropout_prob=0.5)
    fc2 = fluid.layers.fc(input=dp1, size=512)
    bn1 = fluid.layers.batch_norm(input=fc2, act='relu')
    fc2 = fluid.layers.dropout(x=bn1, dropout_prob=0.5)
    out = fluid.layers.fc(input=fc2, size=class_dim, act='softmax')
    return out

(三)定义输入层CIFAR数据特点、获取损失函数、复制测试程序、优化器优化、获取CIFAR数据、定义CPU执行器、定义喂入模型的数据导向feeder、训练模型、测试、创建路径保存模型。代码如下:

# 模型训练与保存
import os
import shutil
import paddle
paddle.enable_static()
import paddle.dataset.cifar as cifar
import paddle.fluid as fluid

# 定义VGG16神经网络
def vgg16(input, class_dim=10):
    def conv_block(conv, num_filter, groups):
        for i in range(groups):
            conv = fluid.layers.conv2d(input=conv,
                                       num_filters=num_filter,
                                       filter_size=3,
                                       stride=1,
                                       padding=1,
                                       act='relu')
        return fluid.layers.pool2d(input=conv, pool_size=2, pool_type='max', pool_stride=2)

    conv1 = conv_block(input, 64, 2)   # 循环2次卷积
    conv2 = conv_block(conv1, 128, 2)  # 循环2次卷积
    conv3 = conv_block(conv2, 256, 3)  # 循环3次卷积
    conv4 = conv_block(conv3, 512, 3)  # 循环3次卷积
    conv5 = conv_block(conv4, 512, 3)  # 循环3次卷积
    # 针对VGG模型缺点,创建BN层和随机丢弃(Dropout)操作,随机丢弃一些神经元,使网络模型稀疏,抑制梯度弥散,起到正则化效果防止过拟合
    fc1 = fluid.layers.fc(input=conv5, size=512)   # 全连接层
    dp1 = fluid.layers.dropout(x=fc1, dropout_prob=0.5)
    fc2 = fluid.layers.fc(input=dp1, size=512)
    bn1 = fluid.layers.batch_norm(input=fc2, act='relu')
    fc2 = fluid.layers.dropout(x=bn1, dropout_prob=0.5)
    out = fluid.layers.fc(input=fc2, size=class_dim, act='softmax')
    return out

# 定义输出层CIFAR数据集图片是32pxX32px的3通道彩色图。包括飞机、汽车等10个类别的60000张图片,每个类别6000张
# 定义输出层
image = fluid.data(name='image', shape=[None, 3, 32, 32], dtype='float32')
label = fluid.data(name='label', shape=[None, 1], dtype='int64')

# 获取分类器()指定分类大小为10
model = vgg16(image, 10)

# 获取损失函数和准确率函数
cost = fluid.layers.cross_entropy(input=model, label=label)
avg_cost = fluid.layers.mean(cost)
acc = fluid.layers.accuracy(input=model, label=label, k=1)

# 获取训练和测试程序
test_program = fluid.default_main_program().clone(for_test=True)

# 定义优化方法
optimizer = fluid.optimizer.MomentumOptimizer(learning_rate=1e-3,
                                              momentum=0.9)
opts = optimizer.minimize(avg_cost)

# 获取CIFAR数据
train_reader = paddle.batch(cifar.train10(), batch_size=32)
test_reader = paddle.batch(cifar.test10(), batch_size=32)

# 定义一个使用CPU的执行器
# place = fluid.CUDAPlace(0)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# 进行参数初始化
exe.run(fluid.default_startup_program())

# 定义feeder输入数据
feeder = fluid.DataFeeder(place=place, feed_list=[image, label])

# 开始训练和测试(循环训练一次,可训练多次)
for pass_id in range(1):
    # 进行训练
    for batch_id, data in enumerate(train_reader()):
        train_cost, train_acc = exe.run(program=fluid.default_main_program(),
                                        feed=feeder.feed(data),
                                        fetch_list=[avg_cost, acc])
        # 每100个batch打印一次信息
        if batch_id % 100 == 0:
            print('Pass:%d, Batch:%d, Cost:%0.5f, Accuracy:%0.5f' %
                  (pass_id, batch_id, train_cost[0], train_acc[0]))

    # 进行测试
    test_accs = []
    test_costs = []
    for batch_id, data in enumerate(test_reader()):
        test_cost, test_acc = exe.run(program=test_program,
                                      feed=feeder.feed(data),
                                      fetch_list=[avg_cost, acc])
        test_accs.append(test_acc[0])
        test_costs.append(test_cost[0])
    # 求测试结果的平均值
    test_cost = (sum(test_costs) / len(test_costs))
    test_acc = (sum(test_accs) / len(test_accs))
    print('Test:%d, Cost:%0.5f, Accuracy:%0.5f' % (pass_id, test_cost, test_acc))

    # 保存预测模型
    save_path = 'model\\persistable_model_01'
    # 删除旧的模型文件
    shutil.rmtree(save_path, ignore_errors=True)
    # 创建保持模型文件目录
    os.makedirs(save_path)
    # 保存预测模型
    fluid.io.save_inference_model(dirname=save_path,
                                  feeded_var_names=[image.name],
                                  target_vars=[model],
                                  executor=exe)

运行结果:

在这里插入图片描述

模型也顺利生成:

在这里插入图片描述

(四)调用上面训练得到模型,并使用该模型进行对一张汽车照片进行预测:

# 调用上面训练得到模型,并使用
import paddle.fluid as fluid
from PIL import Image
import numpy as np
import paddle
paddle.enable_static()

# 创建执行器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())

# 保存预测模型路径
save_path = 'model\\persistable_model_01'
# 从模型中获取预测程序(infer_program)、输入数据名称列表(feeded_var_names)、分类器(target_var)
[infer_program,
 feeded_var_names,
 target_var] = fluid.io.load_inference_model(dirname=save_path,
                                             executor=exe)
# 预处理图片
def load_image(file):
    im = Image.open(file)    # 打开图片
    im = im.convert("RGB")   # 如图片是4通道,运行报错,需将图片(4通道,多出是Alpha通道)转换成3通道图片
    im = im.resize((32, 32), Image.ANTIALIAS)   # 缩放尺寸,ANTIALIAS:高剂质量
    im = np.array(im).astype(np.float32)
    # PIL打开图片存储顺序为H(高度)W(宽度)C(通道)。
    # PaddlePaddle要求数据顺序为CHW,所以需要转换顺序。
    im = im.transpose((2, 0, 1))   #转换成通道、高度、宽度
    im = im / 255.0                #
    im = np.expand_dims(im, axis=0)   # 相应的axis=0轴上扩展维度
    return im

#获取需要预测的图片
img = load_image('F:\\PyQt_Serial_Assistant_Drive_Detect\\Friuts_Classify\\car.png')

# 执行预测
result = exe.run(program=infer_program,
                 feed={
    
    feeded_var_names[0]: img},
                 fetch_list=target_var)

# 显示图片并输出结果最大的label
# np.argsort函数功能:将result中的元素从小到大排列,[-1]即提取最大的值。
lab = np.argsort(result)[0][0][-1]

names = ['飞机', '汽车', '鸟', '猫', '鹿',
         '狗', '青蛙', '马', '船', '卡车']

print('预测结果标签为:%d, 名称为:%s, 概率为:%f' % (lab, names[lab], result[0][0][lab]))

需要预测的图片:

在这里插入图片描述

成功进行预测:

在这里插入图片描述

再预测多一张狗的图片:

在这里插入图片描述

预测结果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/K_AAbb/article/details/127366419