《深度学习》CNN 数据增强、保存最优模型 实例详解

news2025/2/23 17:45:35

目录

一、数据增强

1、什么是数据增强

2、目的

3、常用的数据增强方法

4、数据预处理

用法:

5、使用数据增强增加训练数据

二、保存最优模型

1、什么是保存最优模型

2、定义CNN模型

运行结果:

3、设置训练模式

4、设置测试模式、保存最优模型

5、开始训练模型

运行结果:

6、最优模型


一、数据增强

1、什么是数据增强

        数据增强(data augmentation)是指通过对原始训练数据进行一系列变换扩充,生成新的训练样本,以增加训练数据的多样性和数量,从而提升深度学习模型的泛化能力鲁棒性

2、目的

        模拟真实世界中的不同情况和变化,使模型对各种情况都能准确识别和预测。

3、常用的数据增强方法

        图像旋转:随机旋转图像一定角度,模拟不同角度观察物体的情况。

        图像翻转:随机水平或垂直翻转图像,模拟不同方向观察物体的情况。

        图像缩放:随机调整图像尺寸,模拟物体距离不同的情况。

        图像平移:随机平移图像一定距离,模拟物体在不同位置的情况。

        图像剪切:随机裁剪图像一部分,模拟物体遮挡的情况。

        图像亮度、对比度、饱和度调整:随机调整图像的亮度、对比度和饱和度,模拟不同光照条件下的情况。

        噪声添加:随机向图像中添加噪声,模拟真实世界中的噪声干扰。

        随机扰动:随机对图像进行拉伸、扭曲等几何变换,模拟物体形状的变化。

4、数据预处理

        用法:
import torch
from torch.utils.data import DataLoader,Dataset  # 导入打包加载库,Dataset表示数据集的抽象概念,可以被自定义的数据集继承和实现
import numpy as np
from PIL import Image
from torchvision import transforms

data_transforms = {'train':    # 训练集  也可以使用PIL库  smote 训练集
                transforms.Compose([  # transforms.Compose用于将多个图像预处理操作整合在一起
                transforms.Resize([300,300]),   # 使图像变换大小
                transforms.RandomRotation(45),   # 随机旋转,-42到45度之间随机选
                transforms.CenterCrop(256),    # 从中心开始裁剪[256.256]
                transforms.RandomHorizontalFlip(p=0.5),  # 随机水平旋转,随机概率为0.5
                transforms.RandomVerticalFlip(p=0.5),  # 随机垂直旋转,随机概率0.5
                transforms.ColorJitter(brightness=0.2,contrast=0.1,saturation=0.1,hue=0.1),   # 随机改变图像参数,参数分别表示 亮度、对比度、饱和度、色温
                transforms.RandomGrayscale(p=0.1),  # 概率转换成灰度率,3通道就是R=G=B
                transforms.ToTensor(),   # 将PIL图像或NumPy ndarray转换为tensor类型,并将像素值的范围从[0, 255]缩放到[0.0, 1.0],默认把通道维度放在前面
                transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])  # 给定均值和标准差对图像进行标准化,前者为均值,后者为标准差,三个值表示三通道图像

                ]),
                'valid':  # 验证集
                    transforms.Compose([   # 整合图像处理的操作
                    transforms.Resize([256,256]),   # 缩放图像尺寸
                    transforms.ToTensor(),   # 转换为torch类型
                    transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])    # 标准化
                ])
} 

        注意:做了数据增强不代表模型训练效果一定会变好,大概率会变好

5、使用数据增强增加训练数据

class food_dataset(Dataset):   # food_dataset是自己创建的类名称,继承Dataset类
    def __init__(self,file_path,transform=None):   # 类的初始化,解析数据文件txt,file_path表示文件路径,transform可选的图像转换操作
        self.file_path = file_path  # 将文件地址传入self空间
        self.imgs = []
        self.labels = []
        self.transform = transform  # 将数据增强操作传入self空间
        with open(self.file_path) as f:  # 打开存放图片地址及其类别的文本文件train.txt,
            samples = [x.strip().split(' ') for x in f.readlines()]   # 遍历文件里的每一条数据,经过处理后存入sample列表,元祖的形式存放
            for img_path,label in samples:  # 遍历列表中的每个元组的每个元素
                self.imgs.append(img_path)   # 将图像的路径存入img列表
                self.labels.append(label)     # 将图片类别标签存入label列表
# 初始化:把图片目录加载到self.

    def __len__(self):    # 类实例化对象后,可以使用len函数测量对象的个数
        return len(self.imgs)   # 返回数据集中样本的总数

    def __getitem__(self, idx):   # 关键,可通过索引idx的形式获取每一个图片数据及标签
        image = Image.open(self.imgs[idx])   # 使用PIL库中的用法Image打开并识别图像,还不是tensor
        if self.transform:    # 判断是否有图像转换操作,上述定义默认为None,有则将pil图像数据转换为tensor类型
            image = self.transform(image)   # 图像处理为256*256,转换为tenor

        label = self.labels[idx]   # label还不是tensor
        label = torch.from_numpy(np.array(label,dtype=np.int64))  # 首先指定标签类型为int型,然后将其转换为numpy数组类型,然后再使用torch.from_numpy转换为torch类型
        return image,label  # 返回处理完的图片和标签

# 次数导入上述定义函数中的参数
training_data = food_dataset(file_path = './trainda.txt',transform = data_transforms['train'])
test_data = food_dataset(file_path ='./testda.txt',transform = data_transforms['valid'])
# 判断当前使用的是cpu好事gpu
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device")

其中trainda.txt文件内容为: (全篇博客使用

testda.txt文件内容:

        其中的每个文件地址都有其对应的图片,数据量较大,训练时间会较长,如需使用,可私信发送打包文件。

        整篇文章所有代码连接为一份完整代码。

二、保存最优模型

1、什么是保存最优模型

        保存最优模型指的是在训练过程中,根据某个指标(如验证集准确率或损失函数值)的表现,选择最好的模型参数并将其保存下来,然后形成一个文件,后缀名为pt\ppt\t7。

        在深度学习中,模型的训练过程通常是通过迭代优化算法(如梯度下降)来不断调整模型的参数,以最小化目标函数(如损失函数)。在每个训练周期结束后,会使用验证集或测试集对模型进行评估,计算模型在该指标上的性能。

2、定义CNN模型

from torch import nn

class CNN(nn.Module):
    def __init__(self):   # 翰入大小 (3,256,256)
        super(CNN,self).__init__()
        self.conv1 = nn.Sequential(   # 将多个层组合成一起。
            nn.Conv2d(    # 2d一般用于图像,3d用于视频数据(多一个时间维度),1d一般用于结构化的序
                in_channels=3,   # 图像通道个数,1表示灰度图(确定了卷积核 组中的个数)
                out_channels=16,   # 要得到几多少个特征图,卷积核的个数.
                kernel_size=5,   # 卷积核大小,5*5
                stride=1,   # 步长
                padding=2,   # 一般希望卷积核处理后的结果大小与处理前的数据大小相同,效果会比较好。那p
            ),   #  输出的特征图为 (16,256,256)
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),   # 进行池化操作(2x2 区域),输出结果为:(16,128,128)
        )
        self.conv2 = nn.Sequential(
            nn.Conv2d(16,32,5,1,2),   # 输出(32,128,128)
            nn.ReLU(),
            nn.MaxPool2d(2)  # 输出
        )
        self.conv3 = nn.Sequential(
            nn.Conv2d(32,128,5,1,2),
            nn.ReLU(),
        )
        self.out = nn.Linear(128*64*64,20)   # 全连接

    def forward(self,x):   # 前向传播
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)   # 输出(64,128,64,64)
        x = x.view(x.size(0),-1)
        output = self.out(x)
        return output   # 返回输出结果

model = CNN().to(device)  # 将卷积神经网络模型传入GPU
print(model)   # 打印当前模型的构造
        运行结果:

3、设置训练模式

def train(dataloader,model,loss_fn,optimizer):   # 传入参数 打包的数据,卷积模型,损失函数,优化器
    model.train()   # 表示模型开始训练
    batch_size_num = 1
    for x,y in dataloader:  # 遍历打包的图片及其对应的标签,其中batch为每一个数据的编号
        x,y = x.to(device), y.to(device)  # 把训练数据集和标签传入cpu或GPU
        pred = model.forward(x)   # 自动初始化 W权值
        loss = loss_fn(pred, y)   # 传入模型训练结果的预测值和真实值,通过交叉熵损失函数计算损失值L0

        optimizer.zero_grad()  # 梯度值清零
        loss.backward()     # 反向传播计算得到每个参数的梯度
        optimizer.step()    # 根据梯度更新网络参数

        loss = loss.item()   # 获取损失值
        if batch_size_num % 100 == 0:
            print(f"loss: {loss:>7f}[number:{batch_size_num}]")  # 打印损失值,右对齐,长度为7
        batch_size_num += 1    # 右下方传入的参数,表示训练轮数

4、设置测试模式、保存最优模型

best_acc = 0  # 初始化为0
def test(dataloader, model,loss_fn):   # 定义一个test函数,用于测试模型性能
    global best_acc    # 定义一个全局变量
    size = len(dataloader.dataset)   # 返回打包的图片总数
    num_batches = len(dataloader)   # 返回打包的包的个数
    model.eval()    # 表示模型进入测试模式
    test_loss,correct = 0,0   # 初始化两个值,一个用来存放总体损失值,一个存放预测准确的个数
    with torch.no_grad():   # 一个上下文管理器,关闭梯度计算。当你确认不会调用Tensor.backward()时可以减少
        for x,y in dataloader:  # 遍历数据加载器中测试集图片的图片及其标签
            x,y = x.to(device),y.to(device)   # 传入GPU
            pred = model.forward(x)   # 前向传播,返回预测结果
            test_loss += loss_fn(pred,y).item()  # 计算所有的损失值的和,item表示将tensor类型值转化为python标量
            correct += (pred.argmax(1)== y).type(torch.float).sum().item()   # 判断预测的值是等于真实值,返回布尔值,将其转换为0和1,然后求和
            # a = (pred.argmax(1)== y)  dim=1表示每一行中的最大值对应的索引号,dim=日表示每 b=(pred.argmax(1)==y).type(torch.float)

        test_loss /= num_batches   # 总体损失值除以数据条数得到平均损失值
        correct /= size   # 求准确率
        print(f"Test result:in Accuracy: {(100*correct)}%, Avg loss: {test_loss}")  # 表示准确率机器对应的损失值
        # acc_s.append(correct)
        # loss_s.append(test_loss)

# 保存最优模型的前2种方法,模型扩展名一般为:py\pth\t7
    if correct > best_acc:  # 如果新训练得到的准确率大于前面已经求出来的准确率
        best_acc = correct   # 将新的准确率传入值best_acc
# 1、保存模型参数方法:保存权重和偏置 torch.save(model.state_dict(),path)  (w,b)
#         print(model.state_dict().key())  # 输出模型名称 CNN
#         torch.save(model.state_dict(),'best.pth')

# 2、保存完整模型  保存包括模型的架构和参数(w,b,模型cnn)
        torch.save(model,'best.pt')


loss_fn = nn.CrossEntropyLoss()    # 创建交叉熵损失雨数对象,因为食物的类别是20
optimizer = torch.optim.Adam(model.parameters(),lr=0.001)   # 创建一个优化器,SGD为随机梯度下降,Adam为一种自适应优化器

5、开始训练模型

train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)  # 创建数据加载器,将训练集和测试集图片及其标签打包
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)

epochs = 150   # 设置模型训练的轮数,不停更新模型参数,找到最优值
acc_s = []  # 初始化了两个空列表,用于存储模型在每个epoch结束时的准确率和损失值
loss_s = []
for t in range(epochs):   # 遍历轮数
    print(f"Epoch {t+1}\n---------------------------")   # 表示轮数展示
    train(train_dataloader,model,loss_fn,optimizer)   # 调用函数train传入训练集数据加载器、初始化的模型、损失函数、优化器
    test(test_dataloader, model, loss_fn)  # 上述训练集训练完后有了初步的模型,现传入测试集然后在对其进行测试,然后保存模型,然后进行迭代轮数,每每遇到最大准确率则重新保存新的模型
        运行结果:

6、最优模型

        训练结束得到当前训练的最优模型,其为pt\pth\t7文件,此时该文件即为当前模型,可直接调用该文件使用。

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

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

相关文章

RHCS认证-Linux(RHel9)-Ansible

文章目录 一、ansible 简介二 、ansible部署三、ansible服务端测试四 、ansible 清单inventory五、Ad-hot 点对点模式六、YAML语言模式七、RHCS-Ansible附:安装CentOS-Stream 9系统7.1 ansible 执行过程7.2 安装ansible,ansible-navigator7.2 部署ansibl…

点亮一个LED灯

一、任务分析 一个灯怎么样才会亮? 图中的小灯两端接正负极,小灯就会点亮,但是我们不能主动控制灯的亮灭,于是加入了开关。开关打开断开小灯正极,小灯就会熄灭,反之则点亮。 在板子上的灯是如何连接的&…

Spring Boot集成Redis向量数据库实现相似性搜索

1.什么是Redis向量数据库? Redis 是一个开源(BSD 许可)的内存数据结构存储,用作数据库、缓存、消息代理和流式处理引擎。Redis 提供数据结构,例如字符串、哈希、列表、集合、带范围查询的有序集合、位图、超对数日志、…

Qt开发-comboBox 所有槽函数介绍(2024.09)

activated(int): 触发于ComboBox中某一项被激活时,参数为该项的索引。 currentIndexChanged(QString)/currentIndexChanged(int): 当前选中项变化时触发,前者传递文本,后者传递索引。 currentTextChanged(QString): 当前选中项的文字变更时触…

Ubuntu 与Uboot网络共享资源

1、NFS 1.1 Ubuntu 下 NFS 服务开启 sudo apt-get install nfs-kernel-server rpcbind 等待安装完成,安装完成以后在用户根目录下创建一个名为“Linux”的文件夹,以后所有 的东西都放到这个“Linux”文件夹里面,在“Linux”文件夹里面新建…

Qt获取本机Mac地址、Ip地址

一、简述 今天给大家分享一个获取本机IP地址和Mac地址的方法,经过多次测试,台式机、笔记本等多个设备,暂时没有发现问题。 由于很多时候本地安装了虚拟机、蓝牙、无线网卡或者其他设备等,会有多个Mac地址,所以需要进…

【828华为云征文|如何轻松部署“未知表白墙”项目:华为云Flexus X实例指南】

文章目录 华为云 Flexus X 实例:开启高效云服务的新纪元部署【未知表白墙】项目准备工作具体操作指南服务器环境确认宝塔软件商店操作域名解析未知表白墙登录页修改管理员账号和密码未知表白墙管理页面基础设置表白管理 未知表白墙效果查看 总结 华为云 Flexus X 实…

c++924

2 #include <iostream> #include <cstring>using namespace std;class MyString { private:char *str; // 记录C风格的字符串int size; // 记录字符串的实际长度public:// 定义无参构造MyString() : size(0) {str new char[1];str[0] \0;cou…

Unity中Rigidbody 刚体组件和Rigidbody类是什么?

Rigidbody 刚体组件 Rigidbody 是 Unity 中的一个组件&#xff0c;它可以让你的游戏对象像真实世界中的物体一样移动和碰撞。想象一下&#xff0c;你有一个小球&#xff0c;你希望它像真实世界中的球一样滚动、弹跳和碰撞&#xff0c;那么你就可以给这个小球添加一个 Rigidbod…

JavaScript中的日期和时间

日期和时间 JS语言核心包括Date()构造函数&#xff0c;用来创建表示日期和时间的对象。提供了简单的API. 代码实现&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>3.1.5 日期和时间</title></hea…

3D模型在UI设计中应用越来越多,给UI带来了什么?

当前3D模型在UI设计中应用很多&#xff0c;极大地拓展了UI设计的发挥空间&#xff0c;也拓宽了UI的应用领域&#xff0c;本文分享下UI中引入3D模型到底能带来什么价值. 3D模型在UI设计中的应用可以给用户界面带来以下几个方面的好处&#xff1a; 更真实的视觉体验&#xff1a;…

【2024W36】肖恩技术周刊(第 14 期):什么是完美副业?

周刊内容: 对一周内阅读的资讯或技术内容精品&#xff08;个人向&#xff09;进行总结&#xff0c;分类大致包含“业界资讯”、“技术博客”、“开源项目”和“工具分享”等。为减少阅读负担提高记忆留存率&#xff0c;每类下内容数一般不超过3条。 更新时间: 星期天 历史收录:…

2016年国赛高教杯数学建模C题电池剩余放电时间预测解题全过程文档及程序

2016年国赛高教杯数学建模 C题 电池剩余放电时间预测 铅酸电池作为电源被广泛用于工业、军事、日常生活中。在铅酸电池以恒定电流强度放电过程中&#xff0c;电压随放电时间单调下降&#xff0c;直到额定的最低保护电压&#xff08;Um&#xff0c;本题中为9V&#xff09;。从充…

TAPD多类别需求管理

本文档将介绍&#xff1a;什么是 TAPD 多类别需求管理&#xff0c;以及如何配置或创建新的需求类别。 一、概述 在研发管理过程中&#xff0c;团队经常会遇到规模扩张、不同特性团队间研发模式差异化大等问题。以上问题导致团队中的需求无法进行统一管理。为解决上述情况&…

54 螺旋矩阵

解题思路&#xff1a; \qquad 这道题可以直接用模拟解决&#xff0c;顺时针螺旋可以分解为依次沿“右-下-左-上”四个方向的移动&#xff0c;每次碰到“边界”时改变方向&#xff0c;边界是不可到达或已经到达过的地方&#xff0c;会随着指针移动不断收缩。 vector<int>…

Adobe Illustrator吸管工具提取的颜色与原色之间存在色差

问题原因&#xff1a; 被提取颜色的对象是外部链接图片&#xff0c;对其提取的颜色会与AI中看到的颜色不同 如下图所示&#xff0c;中间的矩形与外部矩形的内部颜色存在色差 解决办法&#xff1a; 方法一&#xff1a;将该外部图片利用屏幕截图的形式&#xff0c;粘贴到AI中。…

【Linux】fork入门级使用

目录 一、前置准备 1、进程的基本概念 2、进程标识符PID、PPID 1&#xff09;pid介绍 2&#xff09;获取pid和ppid 二、fork函数 1、fork的基本介绍 1&#xff09;fork&#xff08;&#xff09;&#xff1a; 创建子进程 2&#xff09;对于函数具体的描述 3&#xff09…

深入探索卷积神经网络(CNN)

深入探索卷积神经网络&#xff08;CNN&#xff09; 前言图像的数字表示灰度图像RGB图像 卷积神经网络&#xff08;CNN&#xff09;的架构基本组件卷积操作填充&#xff08;Padding&#xff09;步幅&#xff08;Strides&#xff09; 多通道图像的卷积池化层全连接层 CNN与全连接…

应急响应--来不来得及走流程...

免责声明&#xff1a;本文仅做分享&#xff01; 应急响应详解 概述 应急响应是现代信息安全管理中的重要一环。随着网络威胁的日益复杂化&#xff0c;企业和组织必须具备快速响应安全事件的能力&#xff0c;以最大限度地减少数据泄露、业务中断以及经济损失。本文将从应急响应…

华为全联接大会2024 | 一文回顾华为云开发者联盟重磅干货

目录 华为开发者空间预置更多工具资源&#xff0c;带来丰富场景案例 携手鲲鹏、鸿蒙、昇腾等根生态&#xff0c;使能开发者创新 学习体验、内容体系全面升级&#xff0c;助力开发者高效学习根技术 参与丰富线上体验活动&#xff0c;赢取精美礼品 在刚刚结束的华为全联接大会…