基于Pytorch框架构建LeNet-5模型

news2024/9/20 16:58:29

Pytorch

  • 一、训练模型
    • 1.导入必要的库
    • 2.设置超参数
    • 3.数据预处理
    • 4.读取数据
  • 二、定义卷积神经网络
    • 1.定义卷积神经网络
    • 2.定义学习率
    • 3.实例化模型并且移动到GPU
    • 4.选择优化器
  • 三、定义调整学习率的函数
    • 1.定义调整学习率的函数
  • 四、训练模型
    • 1.设置模型为训练模式
    • 2.遍历训练数据加载器
    • 3.打印进度
  • 五、验证模型
    • 1.设置模型为验证模式
    • 2.初始化计数器
    • 3.遍历测试数据加载器
    • 4.计算准确率
    • 5.打印验证结果
  • 五、定义训练循环
    • 2.执行训练和验证
    • 3.保存模型

一、训练模型

1.导入必要的库

torch.nn.functional as F: 导入 PyTorch 的不带参数的函数模块,包含各种函数,如激活函数、池化层等。
torch.optim as optim: 导入 PyTorch 的优化器模块,用于定义优化器。
torch.cuda.is_available(): 导入 PyTorch 的 CUDA 模块,用于检查是否有可用的 CUDA GPU。
torch.device(‘cuda’ if torch.cuda.is_available() else ‘cpu’): 导入 PyTorch 的设备模块,用于定义计算设备。如果 CUDA GPU 可用,则定义为 ‘cuda’;否则定义为 ‘cpu’。

# 导入库
import torch.nn.functional as F
import torch.optim as optim
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.optim
import torch.utils.data
import torch.utils.data.distributed
import torchvision.transforms as transforms
import torchvision.datasets as datasets

2.设置超参数

定义超参数,这些参数将用于控制模型的训练过程。

以下是超参数的详细说明:
CH_SIZE: 定义了每个训练批次的样本数量。较大的批大小可以提高计算效率,但可能会增加内存需求。在这个例子中,批大小被设置为 20。
EPOCHS: 定义了训练过程中迭代的轮数。每个 epoch 表示数据集被完整地遍历了一次。在这个例子中,训练过程被设置为进行 10 个 epoch。
DEVICE: 定义了计算设备。如果环境中存在可用的 GPU,它会定义为 ‘cuda’;如果环境中没有可用的 GPU,它会定义为 ‘cpu’。

# 设置超参数
#每次的个数
BATCH_SIZE = 20
#迭代次数
EPOCHS = 10
#采用cpu还是gpu进行计算
DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

3.数据预处理

定义数据预处理步骤,这些步骤将被应用于每个图像上,以增强数据的多样性并标准化数据格式。
以下是预处理步骤的详细说明:
1)Resize(100): 将图片大小调整为 100x100 像素。
2)RandomVerticalFlip(): 随机垂直翻转图片。
3)RandomCrop(50): 从原始图片中随机裁剪一个大小为 50x50 的区域。
4)RandomResizedCrop(150): 从原始图片中随机裁剪一个大小为 150x150 的区域,并随机调整裁剪区域的缩放比例。
5)ColorJitter(brightness=0.5, contrast=0.5, hue=0.5): 随机调整图片的亮度、对比度和色调。
6)ToTensor(): 将 PIL 图像转换为 PyTorch 张量。
7)Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]): 对图像进行归一化处理,将每个通道的均值和标准差调整为 0.5。

# 定义数据预处理
transform = transforms.Compose([
    transforms.Resize(100),
    transforms.RandomVerticalFlip(),
    transforms.RandomCrop(50),
    transforms.RandomResizedCrop(150),
    transforms.ColorJitter(brightness=0.5, contrast=0.5, hue=0.5),
    transforms.ToTensor(),
    transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])

4.读取数据

使用 PyTorch 的数据加载和处理功能来读取数据集,并为训练和测试阶段准备数据加载器。

以下是代码的详细步骤:
1)dataset_train = datasets.ImageFolder(‘E:\xm\dataset\train’, transform): 创建一个ImageFolder数据集,用于加载和分类E:\xm\dataset\train目录中的图像。这个目录应该包含多个子目录,每个子目录代表一个类别,子目录中的图像将归属于该类别。transform变量包含了应用于每个图像的预处理操作。
2)print(dataset_train.imgs): 打印数据集中所有图像的文件路径和对应的类别索引。imgs是一个列表,每个元素是一个包含图像文件路径和类别索引的元组。
3)print(dataset_train.class_to_idx): 打印类别到索引的映射。class_to_idx是一个字典,键是类别名称,值是相应的索引。
4)dataset_test = datasets.ImageFolder(‘E:\xm\dataset\val’, transform): 创建一个ImageFolder数据集,用于加载和分类E:\xm\dataset\val目录中的验证图像。
5)print(dataset_test.class_to_idx): 这行代码打印验证数据集中类别到索引的映射。
6)train_loader = torch.utils.data.DataLoader(dataset_train, batch_size=BATCH_SIZE, shuffle=True): 创建一个训练数据加载器。DataLoader类接受一个数据集和一个批处理大小batch_size,以及一个shuffle标志,表示是否在每次遍历数据集时随机打乱数据的顺序。
7)test_loader = torch.utils.data.DataLoader(dataset_test, batch_size=BATCH_SIZE, shuffle=True): 创建一个测试数据加载器。与训练数据加载器类似,但它也用于加载验证数据集。

# 读取数据
dataset_train = datasets.ImageFolder('E:\\xm\dataset\\train', transform)
print(dataset_train.imgs)
 
# 对应文件夹的label
print(dataset_train.class_to_idx)
dataset_test = datasets.ImageFolder('E:\\xm\dataset\\val', transform)
 
# 对应文件夹的label
print(dataset_test.class_to_idx)
 
# 导入数据
train_loader = torch.utils.data.DataLoader(dataset_train, batch_size=BATCH_SIZE, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset_test, batch_size=BATCH_SIZE, shuffle=True)

运行结果:
在这里插入图片描述

二、定义卷积神经网络

1.定义卷积神经网络

定义名为 ConvNet 的卷积神经网络类,它继承自 torch.nn.Module。这个类实现了一个简单的卷积神经网络结构,用于图像分类任务。

以下是网络结构的详细说明:
1)init(self): 构造函数中,定义了以下层:

  • 6 个卷积层(conv1 到 conv6),每个卷积层后面都跟着一个 ReLU 激活函数和 一个最大池化层(max_pool1 到max_pool4)。
  • 每个卷积层的输出通道数逐渐增加,从 32 到 128。
  • 两个全连接层(fc1 和 fc2),其中 fc1 具有512 个神经元,fc2 具有 1 个神经元(对应于二分类问题)。
  • 最后一个全连接层后面跟着一个 Sigmoid 激活函数。

2)forward(self, x): 前向传播函数接收输入 x,并依次通过以下层:

  • 6 个卷积和池化层的组合,用于提取图像特征。
  • 将最后一个池化层的输出特征图展平为一维向量。
  • 通过全连接层 fc1 和 fc2。
  • 通过 Sigmoid 激活函数生成最终输出。
class ConvNet(nn.Module):
    def __init__(self):
        super(ConvNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, 3)
        self.max_pool1 = nn.MaxPool2d(2)
        self.conv2 = nn.Conv2d(32, 64, 3) 
        self.max_pool2 = nn.MaxPool2d(2) 
        self.conv3 = nn.Conv2d(64, 64, 3) 
        self.conv4 = nn.Conv2d(64, 64, 3) 
        self.max_pool3 = nn.MaxPool2d(2) 
        self.conv5 = nn.Conv2d(64, 128, 3) 
        self.conv6 = nn.Conv2d(128, 128, 3) 
        self.max_pool4 = nn.MaxPool2d(2) 
        self.fc1 = nn.Linear(4608, 512) 
        self.fc2 = nn.Linear(512, 1)
  
    def forward(self, x): 
        in_size = x.size(0) 
        x = self.conv1(x) 
        x = F.relu(x) 
        x = self.max_pool1(x) 
        x = self.conv2(x) 
        x = F.relu(x) 
        x = self.max_pool2(x) 
        x = self.conv3(x) 
        x = F.relu(x) 
        x = self.conv4(x) 
        x = F.relu(x) 
        x = self.max_pool3(x) 
        x = self.conv5(x) 
        x = F.relu(x) 
        x = self.conv6(x) 
        x = F.relu(x)
        x = self.max_pool4(x) 
        # 展开
        x = x.view(in_size, -1)
        x = self.fc1(x)
        x = F.relu(x) 
        x = self.fc2(x) 
        x = torch.sigmoid(x) 
        return x

2.定义学习率

定义模型的学习率为 0.0001。

modellr = 1e-4

3.实例化模型并且移动到GPU

创建 ConvNet 模型实例,并使用 to(DEVICE) 方法将其移动到指定的计算设备上。如果 DEVICE 是 ‘cuda’,则模型将被移动到 GPU;如果 DEVICE 是 ‘cpu’,则模型将被移动到 CPU。

# 实例化模型并且移动到GPU
model = ConvNet().to(DEVICE)

4.选择优化器

创建 Adam 优化器,其中 model.parameters() 表示模型的所有参数,lr=modellr 表示学习率为 0.0001。

# 选择简单暴力的Adam优化器,学习率调低
optimizer = optim.Adam(model.parameters(), lr=modellr)

三、定义调整学习率的函数

1.定义调整学习率的函数

这个函数实现一个简单的学习率衰减策略,它能够根据当前的 epoch 调整学习率。

1)定义学习率衰减规则:

  • modellrnew = modellr * (0.1 ** (epoch // 5)) :定义了一个学习率衰减规则,其中 modellr
    是初始学习率,0.1 ** (epoch // 5) 表示每 5 个 epoch 学习率减少 10 倍。

2)打印新学习率:

  • print(“lr:”,modellrnew):打印出新的学习率。

3)调整优化器的学习率:

  • for param_group in optimizer.param_groups:
    遍历优化器中的每个参数组,并将每个参数组的学习率设置为新学习率。
def adjust_learning_rate(optimizer, epoch):
 
    """Sets the learning rate to the initial LR decayed by 10 every 30 epochs"""
    modellrnew = modellr * (0.1 ** (epoch // 5)) 
    print("lr:",modellrnew) 
    for param_group in optimizer.param_groups: 
        param_group['lr'] = modellrnew

四、训练模型

1.设置模型为训练模式

将模型设置为训练模式,这样模型在计算梯度时会使用 Dropout 和 BatchNorm 层。

# 定义训练过程
def train(model, device, train_loader, optimizer, epoch):
    model.train() 

2.遍历训练数据加载器

遍历 train_loader 中的每个批次,并将数据和标签移动到指定的设备上。然后,它执行前向传播、计算损失、反向传播和更新模型参数。

for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device).float().unsqueeze(1)
optimizer.zero_grad()
output = model(data)

# print(output)
loss = F.binary_cross_entropy(output, target)
loss.backward()
optimizer.step()

3.打印进度

在每 10 个批次后打印当前的轮次、批次数、损失值和进度百分比,以便监控训练进度。

if (batch_idx + 1) % 10 == 0:
    print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
        epoch, (batch_idx + 1) * len(data), len(train_loader.dataset),
            100. * (batch_idx + 1) / len(train_loader), loss.item()))

五、验证模型

1.设置模型为验证模式

将模型设置为验证模式,这样模型在计算梯度时不会使用 Dropout 和 BatchNorm 层。

# 定义测试过程
def val(model, device, test_loader):
    model.eval()

2.初始化计数器

用于在每次迭代时累积损失、正确预测的数量和总样本数。

test_loss = 0
correct = 0
total = 0

3.遍历测试数据加载器

遍历 test_loader 中的每个批次,并将数据和标签移动到指定的设备上。然后,它执行前向传播并计算损失。由于模型处于验证模式,它不会计算梯度。同时,它累积损失、样本数和正确预测的数量。

  with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device).float().unsqueeze(1)
            output = model(data)
            test_loss += F.binary_cross_entropy(output, target, reduction='mean').item()
            pred = torch.tensor([[1] if num[0] >= 0.5 else [0] for num in output]).to(device)
            correct += pred.eq(target.long()).sum().item()
            total += target.size(0)  # 计算总数

4.计算准确率

accuracy = 100. * correct / total

5.打印验证结果

在验证过程结束时打印平均损失和准确率。

print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format(

test_loss, correct, total, 100 * correct / total))

说明:这个函数实现了一个基本的验证循环,它能够验证模型在测试数据集上的性能。在实际使用中,您可能需要根据您的具体任务调整超参数,并确保数据加载器的设置与模型的需求相匹配。

五、定义训练循环

1.调整学习率
在每个 epoch 开始时调整学习率。

# 训练
for epoch in range(1, EPOCHS + 1):
 
    adjust_learning_rate(optimizer, epoch)

2.执行训练和验证

在每个 epoch 中执行训练和验证过程。

   train(model, DEVICE, train_loader, optimizer, epoch) 
    val(model, DEVICE, test_loader)

3.保存模型

在训练结束后保存模型的状态字典。

torch.save(model.state_dict(), 'ConvNet.pth')

运行结果:
在这里插入图片描述
在这里插入图片描述

# 二、测试模型




import torch
from PIL import Image
import torchvision.transforms as transforms
from torchvision import models
from torch.autograd import Variable


# 定义数据预处理
transform_test = transforms.Compose([
    transforms.Resize(100),
    transforms.RandomVerticalFlip(),
    transforms.RandomCrop(50),
    transforms.RandomResizedCrop(150),
    transforms.ColorJitter(brightness=0.5, contrast=0.5, hue=0.5),
    transforms.ToTensor(),
    transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])

# 定义类别
classes = ['cat', 'dog']  # 替换为您的实际类别名称

# 检查是否有可用的 GPU
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 定义自定义的 VGG-19 模型
# 定义网络
class ConvNet(nn.Module):
    def __init__(self):
        super(ConvNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, 3)
        self.max_pool1 = nn.MaxPool2d(2)
        self.conv2 = nn.Conv2d(32, 64, 3)
        self.max_pool2 = nn.MaxPool2d(2)
        self.conv3 = nn.Conv2d(64, 64, 3)
        self.conv4 = nn.Conv2d(64, 64, 3)
        self.max_pool3 = nn.MaxPool2d(2)
        self.conv5 = nn.Conv2d(64, 128, 3)
        self.conv6 = nn.Conv2d(128, 128, 3)
        self.max_pool4 = nn.MaxPool2d(2)
        self.fc1 = nn.Linear(4608, 512)
        self.fc2 = nn.Linear(512, 1)
 
    def forward(self, x):
        in_size = x.size(0)
        x = self.conv1(x)
        x = F.relu(x)
        x = self.max_pool1(x)
        x = self.conv2(x)
        x = F.relu(x)
        x = self.max_pool2(x)
        x = self.conv3(x)
        x = F.relu(x)
        x = self.conv4(x)
        x = F.relu(x)
        x = self.max_pool3(x)
        x = self.conv5(x)
        x = F.relu(x)
        x = self.conv6(x)
        x = F.relu(x)
        x = self.max_pool4(x)
        # 展开
        x = x.view(in_size, -1)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = torch.sigmoid(x)
        return x


# 实例化 Resnet50 类

# 加载权重
model.load_state_dict(torch.load("ConvNet.pth"))
model.to(DEVICE)
model.eval()

# 定义预测函数
def predict_image(image_path):
    # 打开图片
    image = Image.open(image_path)
    # 应用预处理
    image = transform(image).unsqueeze(0)  # 添加batch维度
    # 转换为Variable(如果模型需要)
    image = Variable(image).to(DEVICE)
    # 获取模型预测
    output = model(image)
    _, prediction = torch.max(output.data, 1)
    return classes[prediction.item()]

# 上传的图片路径
uploaded_image_path = '44.jpg'
# 进行预测
predicted_class = predict_image(uploaded_image_path)

print(f"The uploaded image is predicted as: {predicted_class}")

运行结果:
在这里插入图片描述

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

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

相关文章

北邮《计算机网络》网络层笔记

文章目录 单词复习网络层前言路由算法(构造路由表的算法)静态路由算法自适应算法 拥塞控制QoS 服务质量(小小的一节)网络互联(还是小小的一节)Internet 单词复习 estimates boot off-line in advance refl…

揭秘循环购:消费即收益,如何助力商家月销百万?

大家好,我是吴军,今天要和大家分享一种颠覆性的商业模式——循环购。你是否听说过“消费1000送2000”这样的促销活动?是不是觉得太不可思议,商家岂不是在“送钱”?别急,让我为你揭开这背后的秘密。 循环购&…

web前端——HTML

目录 一、HTML概述 1.HTML是什么? 2.HTML具体化解释 二、HTML基本语法 1.声明 2. Head头标签 3.body身体标签 4.一个html的基本结构 5.标签 6.标签属性 ①属性的格式 ②属性的位置 ③添加多个属性 三、基本常用标签 1.超链接 2.图像标签 ①图像标…

从赛题切入谈如何学习数学建模

1.引言 (1)今天学习了这个汪教授的这个视频,主要是对于一个赛题的介绍讲解,带领我们通过这个赛题知道数学建模应该学习哪些技能,以及这个相关的经验,我感觉这个还是让我自己受益匪浅的 (2&…

docker 配置与使用

目录 安装docker 作者遇到的问题1:安装docker 错误说明 解决方法: 作者遇到问题2:GPG密钥问题 问题说明 解决方法: 方法一:使用备用的GPG密钥服务器 方法二:使用国内镜像源 方法3:手动下…

项目性能优化之给dist文件夹中chunk-vendors.js做splitChunks分包,从而减少首屏加载时间

问题描述 我们项目做完,验收通过以后,就需要打包发布上线啦。于是我们执行命令:npm run build打dist包,打包完以后截图如下: 直接打包的chunk-vendors.js太大了 chunk-vendors.js文件太大了,所以我们需要将其优化一下,拆分一下 chunk-vendors.js是啥 chunk-vendors.j…

springboot+vue+mybatis穷游管理系统+PPT+论文+讲解+售后

随着现在网络的快速发展,网上管理系统也逐渐快速发展起来,网上管理模式很快融入到了许多企业的之中,随之就产生了“基于vue的穷游管理系统”,这样就让基于vue的穷游管理系统更加方便简单。 对于本基于vue的穷游管理系统的设计来说…

数据挖掘概览

数据挖掘(Data Mining)就是从大量的,不完全的,有噪声的,模糊的,随机的实际应用数据中,提取隐含在其中的,人们事先不知道的,但又是潜在有用的信息和知识的过程. 预测性数据挖掘 分类 定义:分类就是把一些新的数据项映射到给定类别中的某一个类别 分类流程&#x…

云层之间穿梭特效视频转场PR模板素材

12 个超赞的 Premiere Pro 云层穿梭特效视频转场模板 https://prmuban.com/39056.html 📽 你是否正在寻找一种方法,让你的视频更酷、更时尚、更吸引人?今天推荐的12个逼真的云层穿梭特效视频转场模板,绝对能为你的作品锦上添花 ✨…

微服务SpringCloud,SpringAliBaBa(2)

微服务02 1.网关路由 网络的关口,负责请求的路由、转发、身份校验。 有了网关之后,微服务的地址不用在暴露了,就暴露个网关地址。 快速入门 routes代表一套路由,pridicates是规则,对请求做出判断,看是哪…

《第一行代码 第3版》学习笔记——第十一章 网络技术

1 webview用法 class MainActivity : ComponentActivity() {SuppressLint("SetJavaScriptEnabled")override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {NetWorkDemoTheme {// A surface container using the bac…

史上最全整合nacos单机模式整合哈哈哈哈哈

Nacos 是阿里巴巴推出的一个新开源项目,它主要是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos提供了一组简单易用的特性集,帮助用户快速实现动态服务发现、服务配置、服务元数据及流量管理。 Nacos 的关键特性包括&#x…

线程池概念、线程池的不同创建方式、线程池的拒绝策略

文章目录 💐线程池概念以及什么是工厂模式💐标准库中的线程池💐什么是工厂模式?💐ThreadPoolExecutor💐模拟实现线程池 💐线程池概念以及什么是工厂模式 线程的诞生是因为,频繁的创…

【Linux】Socket阻塞和非阻塞、同步与异步

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;Linux系列专栏&#xff1a;Linux基础 &#x1f525; 给大家…

20240623日志:大模型压缩-sliceGPT

context 1. 剪枝方案图释2. 正交矩阵Q 1. 剪枝方案图释 Fig. 1.1 剪枝方案 图中的阴影是表示丢弃掉这部分数据。通过引入正交矩阵 Q Q Q使 Q ⊤ Q Q Q ⊤ I \mathrm{Q}^\top\mathrm{Q}\mathrm{Q}\mathrm{Q}^\top\mathrm{I} Q⊤QQQ⊤I&#xff0c;来大量缩减 X X X的列数和 W …

[职场] 保险理赔工作简历自我评价范文 #媒体#经验分享#笔记

保险理赔工作简历自我评价范文 保险行业是指将通过契约形式集中起来的资金&#xff0c;用以补偿被保险人的经济利益业务的行业。下面是保险理赔工作简历自我评价范文&#xff0c;供大家参考。 保险公司工作自我评价1 我已在__保险公司工作_个年头。在同事和领导的热情帮忙下&…

query2doc:用大模型做query检索拓展

原文&#xff1a; 前沿重器[38] | 微软新文query2doc&#xff1a;用大模型做query检索拓展 比较主流的检索方案&#xff1a; 字面检索&#xff08;sparse&#xff0c;稀疏&#xff09;向量检索&#xff08;dense&#xff0c;稠密&#xff09; query对文档文段的召回&#xff…

【消息队列】六万字长文详细带你RabbitMQ从入门到精通

目录 1、基础篇1.1 为什么要用消息队列MQ1.2 什么是消息队列&#xff1f;1.3 RabbitMQ体系结构介绍1.4 RabbitMQ安装1.5 Hello World1.5.1 目标1.5.2 具体操作 1.6 RabbitMQ用法1.6.1 Work Queues1.6.2 Publish/Subscribe1.6.3 Routing1.6.4 Topics1.6.5 工作模式小结 2. 进阶篇…

维度建模中的事实表

在维度建模中&#xff0c;根据粒度划分&#xff0c;数据表主要分为维度表和事实表。而事实表又可以分为三种类型&#xff1a;事务型事实表、周期快照型事实表和累计快照型事实表。本文将详细介绍这三种事实表&#xff0c;并提供相应的代码示例。 目录 1. 事务型事实表示例 2. 周…

推荐系统三十六式学习笔记:原理篇.模型融合13|经典模型融合办法:线性模型和树模型的组合拳

目录 为什么要融合&#xff1f;“辑度组合”原理逻辑回归梯度提升决策树GBDT二者结合 总结 推荐系统在技术实现上一般划分为三个阶段&#xff1a;挖掘、召回、排序 。 为什么要融合&#xff1f; 挖掘的工作是对用户和物品做非常深入的结构化分析&#xff0c;各个角度各个层面…