Python 全栈体系【四阶】(三十四)

news2024/11/16 8:58:43

第五章 深度学习

六、PaddlePaddle 图像分类

4. 思路及实现

请添加图片描述

4.1 数据集介绍

来源:爬虫从百度图片搜索结果爬取

内容:包含 1036 张水果图片,共 5 个类别(苹果 288 张、香蕉 275 张、葡萄 216 张、橙子 276 张、梨 251 张)

图像预处理时,将其中 10%作为测试数据,90%作为训练数据

4.2 总体步骤

数据预处理:建立分类文件,建立训练集、测试集

训练与模型评估

读取测试图片,进行预测

4.3 数据预处理

图片位于 5 个目录,遍历每个目录,将其中 90%写入训练集文件,10%写入测试集文件,文件中记录了图片的路径,用于数据读取器进行读取

生成 3 个文件:readme.json(汇总文件)、trainer.list(训练集)、test.list(测试集)

注意:

  • 数据集路径是否正确
  • 生成的汇总文件、训练集文件、测试集文件是否正确
4.4 模型结构

请添加图片描述
在这里插入图片描述

加载模型并预测

在这里插入图片描述

4.5 案例 1:利用 CNN 实现图片分类
4.5.1 数据预处理部分
# 利用深层CNN实现水果分类
# 数据集:爬虫从百度图片搜索结果爬取
# 内容:包含1036张水果图片,共5个类别(苹果288张、香蕉275张、葡萄216张、橙子276张、梨251张)

############################# 预处理部分 ################################
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 = {} # 记录每个类别有哪些图片  key:水果名称  value:图片路径构成的列表

# 将图片路径存入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

# 将name_data_list字典中的内容写入文件
## 清空训练集和测试集文件
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 = 0
    num = 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 += 1 # 计数器加1

print("数据预处理完成.")
4.5.2 模型训练与评估
import paddle
import paddle.fluid as fluid
import numpy
import sys
import os
from multiprocessing import cpu_count
import time
import matplotlib.pyplot as plt

def train_mapper(sample):
    """
    根据传入的样本数据(一行文本)读取图片数据并返回
    :param sample: 元组,格式为(图片路径,类别)
    :return:返回图像数据、类别
    """
    img, label = sample # img为路径,label为类别
    if not os.path.exists(img):
        print(img, "图片不存在")

    # 读取图片内容
    img = paddle.dataset.image.load_image(img)
    # 对图片数据进行简单变换,设置成固定大小
    img = paddle.dataset.image.simple_transform(im=img, # 原始图像数据
                                                resize_size=128, # 图像要设置的大小
                                                crop_size=128, # 裁剪图像大小
                                                is_color=True, # 彩色图像
                                                is_train=True) # 随机裁剪
    # 归一化处理,将每个像素值转换到0~1
    img = img.astype("float32") / 255.0
    return img, label  # 返回图像、类别

# 从训练集中读取数据
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) # 返回图片路径、类别(整数)
    return paddle.reader.xmap_readers(train_mapper, # 将reader读取的数进一步处理
                                      reader, # reader读取到的数据传递给train_mapper
                                      cpu_count(), # 线程数量
                                      buffered_size) # 缓冲区大小

# 搭建CNN函数
# 结构:输入层 --> 卷积/激活/池化/dropout --> 卷积/激活/池化/dropout -->
#      卷积/激活/池化/dropout --> fc --> dropout --> fc(softmax)
def convolution_neural_network(image, type_size):
    """
    创建CNN
    :param image: 图像数据
    :param type_size: 输出类别数量
    :return: 分类概率
    """
    # 第一组 卷积/激活/池化/dropout
    conv_pool_1 = fluid.nets.simple_img_conv_pool(input=image, # 原始图像数据
                                                  filter_size=3, # 卷积核大小
                                                  num_filters=32, # 卷积核数量
                                                  pool_size=2, # 2*2区域池化
                                                  pool_stride=2, # 池化步长值
                                                  act="relu")#激活函数
    drop = fluid.layers.dropout(x=conv_pool_1, dropout_prob=0.5)

    # 第二组
    conv_pool_2 = fluid.nets.simple_img_conv_pool(input=drop, # 以上一个drop输出作为输入
                                                  filter_size=3, # 卷积核大小
                                                  num_filters=64, # 卷积核数量
                                                  pool_size=2, # 2*2区域池化
                                                  pool_stride=2, # 池化步长值
                                                  act="relu")#激活函数
    drop = fluid.layers.dropout(x=conv_pool_2, dropout_prob=0.5)

    # 第三组
    conv_pool_3 = fluid.nets.simple_img_conv_pool(input=drop, # 以上一个drop输出作为输入
                                                  filter_size=3, # 卷积核大小
                                                  num_filters=64, # 卷积核数量
                                                  pool_size=2, # 2*2区域池化
                                                  pool_stride=2, # 池化步长值
                                                  act="relu")#激活函数
    drop = fluid.layers.dropout(x=conv_pool_3, dropout_prob=0.5)

    # 全连接层
    fc = fluid.layers.fc(input=drop, size=512, act="relu")
    # dropout
    drop = fluid.layers.dropout(x=fc, dropout_prob=0.5)
    # 输出层(fc)
    predict = fluid.layers.fc(input=drop, # 输入
                              size=type_size, # 输出值的个数(5个类别)
                              act="softmax") # 输出层采用softmax作为激活函数
    return predict


# 定义reader
BATCH_SIZE = 32  # 批次大小
trainer_reader = train_r(train_list=train_file_path) #原始reader
random_train_reader = paddle.reader.shuffle(reader=trainer_reader,
                                            buf_size=1300) # 包装成随机读取器
batch_train_reader = paddle.batch(random_train_reader,
                                  batch_size=BATCH_SIZE) # 批量读取器
# 变量
image = fluid.layers.data(name="image", shape=[3, 128, 128], dtype="float32")
label = fluid.layers.data(name="label", shape=[1], dtype="int64")

# 调用函数,创建CNN
predict = convolution_neural_network(image=image, type_size=5)
# 损失函数:交叉熵
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.001)
optimizer.minimize(avg_cost) # 将损失函数值优化到最小

# 执行器
# place = fluid.CPUPlace()
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)

model_save_dir = "model/fruits/" # 模型保存路径
costs = [] # 记录损失值
accs = [] # 记录准确度
times = 0
batches = [] # 迭代次数

# 开始训练
for pass_id in range(40):
    train_cost = 0 # 临时变量,记录每次训练的损失值
    for batch_id, data in enumerate(batch_train_reader()): # 循环读取样本,执行训练
        times += 1
        train_cost, train_acc = exe.run(program=fluid.default_main_program(),
                                        feed=feeder.feed(data), # 喂入参数
                                        fetch_list=[avg_cost, accuracy])# 获取损失值、准确率
        if batch_id % 20 == 0:
            print("pass_id:%d, step:%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) # 记录迭代次数

# 训练结束后,保存模型
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.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()
4.5.3 预测
from PIL import Image

# 定义执行器
place = fluid.CPUPlace()
infer_exe = fluid.Executor(place)
model_save_dir = "model/fruits/" # 模型保存路径

# 加载数据
def load_img(path):
    img = paddle.dataset.image.load_and_transform(path, 128, 128, False).astype("float32")
    img = img / 255.0
    return img

infer_imgs = [] # 存放要预测图像数据
test_img = "./data/grape_1.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)
# 执行预测
results = infer_exe.run(infer_program, # 执行预测program
                        feed={feed_target_names[0]: infer_imgs}, # 传入待预测图像数据
                        fetch_list=fetch_targets) #返回结果
print(results)

result = numpy.argmax(results[0]) # 取出预测结果中概率最大的元素索引值
for k, v in name_dict.items(): # 将类别由数字转换为名称
    if result == v:  # 如果预测结果等于v, 打印出名称
        print("预测结果:", k) # 打印出名称

# 显示待预测的图片
img = Image.open(test_img)
plt.imshow(img)
plt.show()

5. 图像分类优化手段

5.1 样本优化

增大样本数量

数据增强

  • 形态变化:翻转、平移、随机修剪、尺度变换、旋转
  • 色彩变化:色彩抖动(错位的位移对图像产生的一种特殊效果)、图像白化(将图像本身归一化成 Gaussian(0,1) 分布)
  • 加入噪声:噪声扰动
5.2 参数优化

丢弃学习:按照一定比率丢弃神经元输出

权重衰减:通过为模型损失函数添加惩罚项使得训练的模型参数较小

批量正则化:在网络的每一层输入之前增加归一化处理,使输入的均值为 0,标准差为 1。目的是将数据限制在统一的分布下

变化学习率:学习率由固定调整为变化,例如由固定 0.001 调整为 0.1, 0.001, 0.0005

加深网络:加深网络可能提高准确率,也可能降低准确率,视具体情况而定

5.3 模型优化

更换更复杂、精度更高的网络模型。如由简单 CNN 更换为 VGG、GooLeNet、ResNet

5.4 利用 VGG 实现图像分类

在水果识别案例第二部分(模型搭建部分)增加如下代码:

# 创建VGG模型
def vgg_bn_drop(image, type_size):
    def conv_block(ipt, num_filter, groups, dropouts):
        # 创建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,#是否使用batch normal
                                         pool_type="max") # 池化类型
    conv1 = conv_block(image, 64, 2, [0.0, 0]) # 最后一个参数个数和组数量相对应
    conv2 = conv_block(conv1, 128, 2, [0.0, 0])
    conv3 = conv_block(conv2, 256, 3, [0.0, 0.0, 0.0])
    conv4 = conv_block(conv3, 512, 3, [0.0, 0.0, 0.0])
    conv5 = conv_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") # batch normal
    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和水果类别一致

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1620240.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NVIDIA Jetson jtop查看资源信息

sudo -H pip install -U jetson-stats 安装好之后可能需要reboot 执行jtop: 时间久了可能会退出,可参考如下再次启动。 nvidiategra-ubuntu:~$ jtop The jtop.service is not active. Please run: sudo systemctl restart jtop.service nvidiategra-ub…

【古琴】倪诗韵古琴雷修系列(形制挺多的)

雷音系列雷修:“修”字取意善、美好的,更有“使之完美”之意。精品桐木或普通杉木制,栗壳色,纯鹿角霜生漆工艺。 方形龙池凤沼。红木配件,龙池上方有“倪诗韵”亲笔签名,凤沼下方,雁足上方居中位…

mPEG-Biotin,Methoxy PEG Biotin在免疫亲和层析、荧光标记和生物传感器等领域发挥关键作用

【试剂详情】 英文名称 mPEG-Biotin,Methoxy PEG Biotin 中文名称 聚乙二醇单甲醚生物素,甲氧基-聚乙二醇-生物素 外观性状 由分子量决定,固体或者粘稠液体。 分子量 0.4k,0.6k,1k,2k,3.…

Activiti7基础

Activiti7 一、工作流介绍 1.1 概念 工作流(Workflow),就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标…

2024-04-23 linux 查看内存占用情况的命令free -h和cat /proc/meminfo

一、要查看 Linux 系统中的内存占用大小,可以使用 free 命令或者 top 命令。下面是这两个命令的简要说明: 使用 free 命令: free -h这将显示系统当前的内存使用情况,包括总内存、已用内存、空闲内存以及缓冲区和缓存的使用情况。…

Git笔记-配置ssh

Git在Deepin中的ssh配置 一、环境二、安装1. 查看GitHub账户2. 配置 git3. 生成 ssh key 三、配置 一、环境 系统: Deepin v23 Git仓库:GitHub 二、安装 1. 查看GitHub账户 在设置界面看到自己的邮箱,这个邮箱就是后面会用到的邮箱 2. …

上位机图像处理和嵌入式模块部署(树莓派4b的一种固件部署方法)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 如果软件开发好了之后,下面就是实施和部署。对于树莓派4b来说,部署其实就是烧录卡和拷贝文件。之前我们烧录卡,…

Jenkins CI/CD 持续集成专题四 Jenkins服务器IP更换

一、查看brew 的 services brew services list 二、编辑 homebrew.mxcl.jenkins-lts.plist 将下面的httpListenAddress值修改为自己的ip 服务器,这里我是用的本机的ip 三 、重新启动 jenkins-lts brew services restart jenkins-lts 四 浏览器访问 http://10.85…

26版SPSS操作教程(高级教程第十三章)

前言 #今日世界读书日,宝子你,读书了嘛~ #本期内容:主成分分析、因子分析、多维偏好分析 #由于导师最近布置了学习SPSS这款软件的任务,因此想来平台和大家一起交流下学习经验,这期推送内容接上一次高级教程第十二章…

卓越体验的秘密武器:评测ToDesk云电脑、青椒云、天翼云的稳定性和流畅度

大家好,我是猫头虎。近两年随着大模型的火爆,我们本地环境常常难以满足运行这些大模型的硬件需求。因此,云电脑平台成为了一个理想的解决方案。今天,我将介绍并评测几款主流云电脑产品:ToDesk云电脑、天翼云电脑和青椒…

网络通信安全

一、网络通信安全基础 TCP/IP协议简介 TCP/IP体系结构、以太网、Internet地址、端口 TCP/IP协议简介如下:(from文心一言) TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议&#xff0…

PVE虚拟机隐藏状态栏虚拟设备

虚拟机启动后,状态栏会出现一些虚拟设备,点击弹出会导致虚拟机无法使用。 解决方案: 1、在桌面新建disable_virtio_removale.bat文件,内容如下: ECHO OFF FOR /f %%A IN (reg query "HKLM\SYSTEM\CurrentContro…

Docker容器化技术

Docker容器化技术 1.Docker概念 Docker是一个开源的应用容器引擎基于go语言实现Docker可以让开发者们打包他们的应用以及依赖包到一个轻量级的、可移植的容器中,然后发布到任何流行的Linux机器上容器是完全使用沙箱机制,相互隔离容器性能开销极低Docke…

Facebook的时间机器:回溯社交媒体的历史

1. 社交媒体的起源与早期模式 社交媒体的历史可以追溯到互联网的早期发展阶段。在Web 1.0时代,互联网主要是一个信息发布平台,用户主要是被动地接收信息。但随着Web 2.0的兴起,互联网逐渐转变为一个互动和参与的平台,社交媒体应运…

HTTP与SOCKS-哪种协议更适合您的代理需求?

网络代理技术是我们日常使用网络时必不可少的一项技术,它可以为我们提供隐私保护和负载均衡的能力,从而保证我们的网络通信更加安全和顺畅。而其中最主流的两种协议就是HTTP和SOCKS。虽然它们都是用于网络代理的协议,但在实际应用中却存在着一…

时间复杂度和空间复杂度是什么

如何衡量代码好坏,算法的考察到底是在考察什么呢? 衡量代码好坏有两个非常重要的标准就是:运行时间和占用空间,就是我们后面要说到的时间复杂度和空间复杂度,也是学好算法的重要基石。 确切的占内用存或运行时间无法进…

Seal^_^【送书活动第2期】——《Flink入门与实战》

Seal^_^【送书活动第2期】——《Flink入门与实战》 一、参与方式二、本期推荐图书2.1 作者简介2.2 编辑推荐2.3 前 言2.4 本书特点2.5 内容简介2.6 本书适用读者2.7 书籍目录 三、正版购买 一、参与方式 评论:"掌握Flink,驭大数据,实战…

想冲宇宙厂,直接挂了。。。

宇宙厂实际是字节,这个称呼是因为字节跳动主宰了宇宙内一切App,有点家大业大的意思。 今天分享一位字节春招凉经,问了一些数据库和Java八股,没出算法题,直接挂了,竟然最喜欢出算法题的字节,这次…

【嵌入式】“野指针”和“悬空指针”的奇淫拙劣

【嵌入式】“野指针”和“悬空指针”的奇淫拙劣 1. 前言1.1 授权须知 2. 野指针和悬空指针3.举例说明3.1 示例一:free 之后,没有让指针指向NULL3.1.1 代码解析3.1.2 运行代码的结果3.1.3 程序崩溃在哪? 3.2 悬空指针–释放后使用攻击 1. 前言…

JS----随机数字,字符,数组

随机数字 function random(min 0, max 100) {if (min > 0 && max > 0 && max > min) {const gab max - min 1return Math.floor(Math.random() * gab min)}return 0 }输入格式 随机字符 function randomStr (len 32) {var s for (; s.lengt…