PaddlePaddle基本用法详解(二)、PaddelPaddle训练水果分类模型
PaddlePaddle基本用法详解(二)、PaddelPaddle训练分类模型
- 1、基本用法
- 2、训练水果分类模型
1、基本用法
2、训练水果分类模型
1、数据集预处理与模型定义代码:
import os###################################第一部分:水果预处理部分#################################
# 定义一组变量
name_dict = {"apple": 0, "banana": 1, "grape": 2, "orange": 3, "pear": 4} # 水果名称和数组对应字典
data_root_path = "data/fruits/" # 数据样本所在目录
test_file_path = data_root_path + "test.txt" # 测试集文件路径
train_file_path = data_root_path + "train.txt" # 训练集文件路径name_data_list = {} # 记录每个类别的图片路径
# 将文件路径存入临时字典
def save_train_test_file(path, name):if name not in name_data_list: # 当前水果没有在字典中,新增img_list = []img_list.append(path) # 将图片添加到列表name_data_list[name] = img_list # 将“名称-图片列表”键值对插入字典else: # 当前水果已经在字典中,添加到相应的列表name_data_list[name].append(path)# 遍历所有子目录,读取出所有图片文件,并插入字典、保存到测试集、训练集
dirs = os.listdir(data_root_path)
for d in dirs:full_path = data_root_path + d # 目录名称 + 子目录名称if os.path.isdir(full_path): # 目录imgs = os.listdir(full_path) # 列出子目录中的文件for img in imgs:save_train_test_file(full_path + "/" + img, # 图片文件完整路径d) # 子目录名称(类别名称)else: # 文件pass# 将字典中的内容保存文件中
with open(test_file_path, "w") as f: # 清空测试集文件pass
with open(train_file_path, "w") as f: # 清空训练集文件pass# 遍历字典,将内容写入文件
for name, img_list in name_data_list.items():i = 0num = len(img_list) # 每个类别图片数量print("%s: %d张图像" % (name, num))for img in img_list: # 遍历每个列表,将图片路径存入文件if i % 10 == 0: # 每10张写一张到测试集with open(test_file_path, "a") as f:line = "%s\t%d\n" % (img, name_dict[name])f.write(line) # 写入文件else: # 其它写入训练集with open(train_file_path, "a") as f:line = "%s\t%d\n" % (img, name_dict[name])f.write(line) # 写入文件i += 1print("数据预处理完成.")###################################第二部分:水果预处理部分################################
import paddle
import paddle.fluid as fluid
import numpy as np
import sys
import os
from multiprocessing import cpu_count
import matplotlib.pyplot as plt# 数据准备
## 定义reader
## train_mapper函数:对传入的图片路径进行读取,返回图像数据(多通道矩阵)、标签
def train_mapper(sample):img, label = sample # 将sample中值赋给img, labelif not os.path.exists(img):print(img, "图片文件不存在")# 读取图片文件img = paddle.dataset.image.load_image(img) # 读取图片# 对图像进行简单变换:修剪、设置大小,输出(3, 100, 100)张量img = paddle.dataset.image.simple_transform(im=img, # 原图像数据resize_size=100, # 重设图像大小为100*100crop_size=100, # 裁剪成100*100is_color=True, # 彩色图像is_train=True) # 是否用于训练,影响裁剪策略# 对图像数据进行归一化处理,像素的值全部计算压缩到0~1之间img = img.astype("float32") / 255.0return img, label # 返回图像数据、标签# 读取训练集文件,将路径、标签作为参数调用train_mapper函数
def train_r(train_list, buffered_size=1024):def reader():with open(train_list, "r") as f: # 打开训练集lines = [line.strip() for line in f] # 读取出所有样本行for line in lines:# 去掉每行的换行符,并根据tab字符进行拆分,得到两个字段img_path, lab = line.replace("\n", "").split("\t")yield img_path, int(lab)# xmap_readers高阶函数,作用是将reader产生的数据穿个train_mapper函数进行下一步处理return paddle.reader.xmap_readers(train_mapper, # 二次处理函数reader, # 原始readercpu_count(), # 线程数(和cpu数量一致)buffered_size) # 缓冲区大小BATCH_SIZE = 32 # 批次大小# 定义reader
train_reader = train_r(train_list=train_file_path)# train_file_path为训练集文件路径
random_train_reader = paddle.reader.shuffle(reader=train_reader, # 原始readerbuf_size=1300) # 缓冲区大小
batch_train_reader = paddle.batch(random_train_reader,batch_size=BATCH_SIZE) # 批量读取器
# 定义变量
image = fluid.layers.data(name="image", shape=[3, 100, 100], dtype="float32")
label = fluid.layers.data(name="label", shape=[1], dtype="int64")# 创建VGG模型
def vgg_bn_drop(image, type_size): # 其包含批归一化层与丢弃层def conv_bn_block(ipt, num_filter, groups, dropout):# 创建Convolution2d,BatchNorm,Dropout,Pool2d组return fluid.nets.img_conv_group(input=ipt, # 输入图像数据,【N,C,H,W】格式pool_stride=2, # 池化步长值pool_size=2, # 池化区域大小conv_num_filter=[num_filter] * groups, # 卷积核的数量(即组的数量*每一组卷积核的数量)conv_filter_size=3, # 卷积核大小conv_act="relu", # 激活函数conv_with_batchnorm=True, # 即卷积完成后是否要进行批量归一化操作pool_type="max" # 池化的类型)# VGG前面的5组卷积池化conv1 = conv_bn_block(image, 64, 2, [0.0, 0.0]) # 表示卷积核数量;2表示组数;[0.0,0.0]表示每组卷积的丢弃率conv2 = conv_bn_block(conv1, 128, 2, [0.0, 0.0])conv3 = conv_bn_block(conv2, 256, 3, [0.0, 0.0, 0.0])conv4 = conv_bn_block(conv3, 512, 3, [0.0, 0.0, 0.0])conv5 = conv_bn_block(conv4, 512, 3, [0.0, 0.0, 0.0])drop = fluid.layers.dropout(x=conv5, dropout_prob=0.2)fc1 = fluid.layers.fc(input=drop, size=512, act=None)bn = fluid.layers.batch_norm(input=fc1, act="relu")drop2 = fluid.layers.dropout(x=bn, dropout_prob=0.0)fc2 = fluid.layers.fc(input=drop2, size=512, act=None)predict = fluid.layers.fc(input=fc2,size=type_size,act="softmax")return predict# 调用上面的函数创建VGG
predict = vgg_bn_drop(image=image, type_size=5) # type_size和水果类别一致
# 损失函数
cost = fluid.layers.cross_entropy(input=predict, # 预测值label=label) # 真实值
avg_cost = fluid.layers.mean(cost)
# 计算准确率
accuracy = fluid.layers.accuracy(input=predict, # 预测值label=label) # 真实值
# 优化器
optimizer = fluid.optimizer.Adam(learning_rate=0.00001) # 自适应梯度下降优化器
optimizer.minimize(avg_cost)# 创建Executor
place = fluid.CUDAPlace(0) # GPU上执行
exe = fluid.Executor(place) # 执行器
exe.run(fluid.default_startup_program()) # 初始化变量# 定义feeder
feeder = fluid.DataFeeder(feed_list=[image, label], place=place)costs = [] # 记录损失值
accs = [] # 记录准确率
times = 0
batches = [] # 记录批次for pass_id in range(15):train_cost = 0for batch_id, data in enumerate(batch_train_reader()):times += 1train_cost, train_acc = exe.run(program=fluid.default_main_program(),feed=feeder.feed(data), # 喂入一个batch数据fetch_list=[avg_cost, accuracy]) # 获取结果if batch_id % 20 == 0:print("pass_id:%d, bat_id:%d, cost:%f, acc:%f" %(pass_id, batch_id, train_cost[0], train_acc[0]))accs.append(train_acc[0]) # 记录准确率costs.append(train_cost[0]) # 记录损失值batches.append(times) # 记录训练批次数# 保存模型
model_save_dir = "model/fruits/" # 模型保存路径
if not os.path.exists(model_save_dir): # 如果模型路径不存在则创建os.makedirs(model_save_dir)
fluid.io.save_inference_model(dirname=model_save_dir, # 保存路径feeded_var_names=["image"], # 使用模型需传入的参数target_vars=[predict], # 模型结果executor=exe) # 模型
print("模型保存完成.")# 训练过程可视化
plt.figure('training', facecolor='lightgray')
plt.title("training", fontsize=24)
plt.xlabel("iter", fontsize=20)
plt.ylabel("cost/acc", fontsize=20)
plt.plot(batches, costs, color='red', label="Training Cost")
plt.plot(batches, accs, color='green', label="Training Acc")
plt.legend()
plt.grid()
plt.savefig("train.png")
plt.show()
2、加载模型,预测图像
############################# 第三部分:加载模型,使用模型执行预测 ################################
from PIL import Imageimport paddle.fluid as fluid
import paddle
import numpy
import matplotlib.pyplot as pltdef load_img(path): # 从指定路径读取图片数据img = paddle.dataset.image.load_and_transform(path, # 图片路径100, 100, # resize图像大小、裁剪大小False # 是否用于训练)# 因为需要对图像进行归一化,所以需要将图像转变为float32的格式img = (img.astype("float32")) / 255.0 # 进行归一化return img# 定义执行器
place = fluid.CPUPlace() # 在预测时,计算量不大,所以没有必要在cuda上计算
infer_exe = fluid.Executor(place) # 创建执行器
model_save_dir= "model/fruits/" # 模型的保存路径infer_imgs = [] # 用来存放待预测图像数据
test_img = "putao.png" # 待预测图片路径
infer_imgs.append(load_img(test_img)) # 读取图像数据,添加到待预测的列表中
# 因为神经网络无法读取列表数据,所以需要将列表数据转换为数组数据输入神经网络
infer_imgs = numpy.array(infer_imgs) # 转换为数组# 加载保存的模型
infer_program,feed_target_names,fetch_targets= \fluid.io.load_inference_model(model_save_dir, # 模型保存路径infer_exe) # 要执行模型的Executor
# 使用模型执行预测
result = infer_exe.run(infer_program, # 预测的programfeed={feed_target_names[0]: infer_imgs}, # 喂入待预测的数据fetch_list=fetch_targets # 取得操作结果并返回)print(result) # 得到的result是一个各个分类概率的二维数组
"""
[array([[9.9999964e-01, 5.7820136e-24, 2.9262706e-10, 3.9078353e-07,1.4152669e-19]], dtype=float32)]
"""index=numpy.argmax(result[0])
name_dict = {"apple": 0, "banana": 1, "grape": 2, "orange": 3, "pear": 4}
# 遍历字典
for k,v in name_dict.items(): # 对分类字典进行迭代返回的是字典的键,值if index==v:print("预测结果为:",k)# 显示待预测的图片
img = Image.open(test_img)
plt.imshow(img)
plt.show()
PaddlePaddle基本用法详解(二)、PaddelPaddle训练水果分类模型相关推荐
- PaddlePaddle基本用法详解(一)、PaddelPaddle进行波士顿房价预测
PaddlePaddle基本用法详解(一).PaddelPaddle进行波士顿房价预测 # helloworld示例 import paddle.fluid as fluid # 创建两个类型为int ...
- 语音自训练平台技术详解,快速训练专属语音识别模型
语音自训练平台4月份公测以来,有1000多名用户创建了1600+模型,涉及医疗.金融.农业.教育.餐饮.物流.建筑.地产等多个行业,模型上线后应用到业务数据采集录入.音频关键词质检.智能语音助手.呼叫 ...
- java typedef的用法_Java 枚举用法详解(二)
枚举可以添加方法 在概念章节提到了,枚举值默认为从0开始的有序数值 .那么问题来了:如何为枚举显示的赋值. Java 不允许使用 = 为枚举常量赋值 如果你接触过C/C++,你肯定会很自然的想到赋值符 ...
- this指针的用法详解
C++中this指针的用法详解 2010-11-12 20:40:45 分类: C/C++ this指针的用处: 一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果.th ...
- this指针用法详解
C++中this指针的用法详解 2010-11-12 20:40:45 分类: C/C++ 1. this指针的用处: 一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果 ...
- Python中self用法详解
Python中self用法详解 https://blog.csdn.net/CLHugh/article/details/75000104 首页 博客 学院 下载 图文课 论坛 APP 问答 商城 V ...
- python中permute_PyTorch中permute的用法详解
PyTorch中permute的用法详解 permute(dims) 将tensor的维度换位. 参数:参数是一系列的整数,代表原来张量的维度.比如三维就有0,1,2这些dimension. 例: i ...
- ios开发读取剪切板的内容_iOS中管理剪切板的UIPasteboard粘贴板类用法详解
一.自带剪切板操作的原生UI控件在iOS的UI系统中,有3个控件自带剪切板操作,分别是UITextField.UITextView与UIWebView.在这些控件的文字交互处进行长按手势可以在屏幕视图 ...
- RxJava flatMap操作符用法详解
RxJava系列文章目录导读: 一.RxJava create操作符的用法和源码分析 二.RxJava map操作符用法详解 三.RxJava flatMap操作符用法详解 四.RxJava conc ...
最新文章
- 权限提升 T1548.002 绕过UAC
- GDB怎么调试使用.sh(shell脚本)启动的程序?(未完成,待测试)
- java继承类型的用法_详解Java中使用externds关键字继承类的用法
- JDK8新特性之重复注解
- 帮助孩子学会感恩_页数204_出版日期2015.03_完整版PDF电子书下载
- 模板引擎工作原理_广州seo了解下搜索引擎的工作原理是什么
- 不定宽高的div如何垂直居中
- node 更新_更新应用时,如何实现 K8s 零中断滚动更新?
- RMS数据采集分布式架构
- python绘制复杂表格_Matplotlib绘制表格
- CSS伪元素(以:after为例)插入图片
- Windows10视频文件没有预览图的解决办法
- 湖南省工信厅党组书记、厅长雷绍业一行莅临麒麟信安调研
- 秀和vs太田雄藏(依田纪基讲定式,欺骗感情)
- 如何利用Vue3管理系统实现动态路由和动态侧边菜单栏
- python中base64库用法详解
- 游戏开发者必须是骨灰级玩家吗?
- 寻找孪生素数 (20 分)
- IBM获5896项专利连续18年蝉联年度冠军
- Win10运行程序提示不受信任的解决方法【系统天地】
热门文章
- OLA音频变速算法的仿真与剖析
- android控制手机拍照代码,Android开发之手机拍照功能的实现(源代码分享)
- 详解eNSP中Trunk端口和Access端口收发数据的区别
- 先序遍历 中序遍历 后序遍历 层序遍历
- 2020年 ICLR 国际会议最终接受论文(poster-paper)列表(二)
- A*寻路算法讲解+源码DEMO演示
- Webapck 体系基础
- 量化对冲:智能对冲策略解析
- 2015.7.15(千股跌停,开盘及时出货。10:49由于绘制通道错误,错误加仓)
- electron 打包后启动应用报错:Error: ENOENT: no such file or directory, open ‘xxx/manifest.json‘‘