《深度学习》卷积神经网络 数据增强、保存最优模型 原理解析及实例实现

devtools/2024/10/19 4:20:46/

目录

一、数据增强

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 transformsdata_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.5transforms.RandomVerticalFlip(p=0.5),  # 随机垂直旋转,随机概率0.5transforms.ColorJitter(brightness=0.2,contrast=0.1,saturation=0.1,hue=0.1),   # 随机改变图像参数,参数分别表示 亮度、对比度、饱和度、色温transforms.RandomGrayscale(p=0.1),  # 概率转换成灰度率,3通道就是R=G=Btransforms.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打开并识别图像,还不是tensorif self.transform:    # 判断是否有图像转换操作,上述定义默认为None,有则将pil图像数据转换为tensor类型image = self.transform(image)   # 图像处理为256*256,转换为tenorlabel = self.labels[idx]   # label还不是tensorlabel = 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 nnclass 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*5stride=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 = 1for x,y in dataloader:  # 遍历打包的图片及其对应的标签,其中batch为每一个数据的编号x,y = x.to(device), y.to(device)  # 把训练数据集和标签传入cpu或GPUpred = model.forward(x)   # 自动初始化 W权值loss = loss_fn(pred, y)   # 传入模型训练结果的预测值和真实值,通过交叉熵损失函数计算损失值L0optimizer.zero_grad()  # 梯度值清零loss.backward()     # 反向传播计算得到每个参数的梯度optimizer.step()    # 根据梯度更新网络参数loss = loss.item()   # 获取损失值if batch_size_num % 100 == 0:print(f"loss: {loss:>7f}[number:{batch_size_num}]")  # 打印损失值,右对齐,长度为7batch_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)   # 传入GPUpred = 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\t7if 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.ppmy.cn/devtools/118531.html

相关文章

自然语言处理(jieba库分词)

1、完全切分法、正向最大匹配算法、逆向最大匹配算法和双向最大匹配算法 一、实验内容 一个好的NLP系统一定要有完备的词典,用于判断算法分出的词是否是具有实际意义的词。自定义一个词典,比如dic ["项目", "研究", "目的&q…

Python电能质量扰动信号分类(一)基于LSTM模型的一维信号分类

引言 本文基于Python仿真的电能质量扰动信号,先经过数据预处理进行数据集的制作和加载,然后通过Pytorch实现LSTM模型对扰动信号的分类。Python仿真电能质量扰动信号的详细介绍可以参考下文(文末附10分类数据集): Pyth…

如何构建鲁棒高性能 Prompt 的方法?

你好,我是三桥君 在当今时代,利用大型语言模型如ChatGPT进行文本生成和交互已成为一种趋势。然而,要充分发挥这些模型的能力,尤其是在生产环境中,我们需要精心设计和优化我们的提示词(prompt)。…

0基础跟德姆(dom)一起学AI 数据处理和统计分析08-日期类型处理,Matplotlib介绍

* 日期类型处理 * 获取日期中不同部分 * 日期运算 * 日期索引 * 生成日期时间序列 * 数据可视化介绍 * Matplotlib API介绍 * 直方图 * 散点图 --- 1.Pandas日期时间类型简介 * 概述 * 和其它语言类似, Python内置了datetime对象,可以在datetime库中…

关于Fake Location定位,运动世界校园问题

不好意思,之前那个文章其实是很早之前的,不知道为什么审核了很久一直没有通过,然后前几周莫名其妙点了一下重新发布,竟然发布成功了,这个方法已经失效了,要可以稳定,我建议是买一台root的手机&a…

Java网络编程、正则表达式、单例设计模式与Lombok

目录 Java网络编程、正则表达式、单例设计模式与Lombok Java网络编程 软件结构 网络基础知识 相关概念 IP地址 TCP协议和UDP协议介绍 TCP协议的三次握手和四次挥手 UDP协议编程 创建客户端 创建服务端 运行 TCP协议编程 创建客户端 创建服务端 运行 文件上传案例 创建客户端 创…

基于Hive和Hadoop的招聘分析系统

本项目是一个基于大数据技术的招聘分析系统,旨在为用户提供全面的招聘信息和深入的职位市场分析。系统采用 Hadoop 平台进行大规模数据存储和处理,利用 MapReduce 进行数据分析和处理,通过 Sqoop 实现数据的导入导出,以 Spark 为核…

前端框架的对比与选择,可以了解一下

在选择前端框架时,开发者需要考虑多个因素,包括项目的需求、团队的技术栈、开发周期、框架的学习曲线、社区支持以及未来维护的便利性等。以下是当前流行的几个前端框架的对比与选择建议: 一、React 特点: 组件化:R…