Pytorch自定义模型实现猫狗分类

简介: Pytorch自定义模型实现猫狗分类

摘要

本例采用猫狗大战的部分数据作为数据集,模型是自定义的模型。

训练

  • 1、构建数据集

在data文件夹下面新家train和val文件夹,分别在train和val文件夹下面新家cat和dog文件夹,并将图片放进去。如图:

tt.png

2、导入库

# 导入库

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

3、设置超参数

# 设置超参数

BATCH_SIZE = 20

EPOCHS = 10

DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

4、图像处理与图像增强

# 数据预处理

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])

])

5、读取数据和导入数据

# 读取数据

dataset_train = datasets.ImageFolder('data/train', transform)

print(dataset_train.imgs)

# 对应文件夹的label

print(dataset_train.class_to_idx)

dataset_test = datasets.ImageFolder('data/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)

6、定义网络模型

# 定义网络

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

modellr = 1e-4

# 实例化模型并且移动到GPU

model = ConvNet().to(DEVICE)

# 选择简单暴力的Adam优化器,学习率调低

optimizer = optim.Adam(model.parameters(), lr=modellr)

7、调整学习率

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

8、定义训练与验证方法

# 定义训练过程

def train(model, device, train_loader, optimizer, epoch):

   model.train()

   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()

       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()))

# 定义测试过程

def val(model, device, test_loader):

   model.eval()

   test_loss = 0

   correct = 0

   with torch.no_grad():

       for data, target in test_loader:

           data, target = data.to(device), target.to(device).float().unsqueeze(1)

           output = model(data)

           # print(output)

           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()

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

           test_loss, correct, len(test_loader.dataset),

           100. * correct / len(test_loader.dataset)))

9、训练并保存模型

# 训练

for epoch in range(1, EPOCHS + 1):

   adjust_learning_rate(optimizer, epoch)

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

   val(model, DEVICE, test_loader)

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

完整代码:

# 导入库

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

# 设置超参数

BATCH_SIZE = 20

EPOCHS = 10

DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# 数据预处理

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])

])

# 读取数据

dataset_train = datasets.ImageFolder('data/train', transform)

print(dataset_train.imgs)

# 对应文件夹的label

print(dataset_train.class_to_idx)

dataset_test = datasets.ImageFolder('data/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)

# 定义网络

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

modellr = 1e-4

# 实例化模型并且移动到GPU

model = ConvNet().to(DEVICE)

# 选择简单暴力的Adam优化器,学习率调低

optimizer = optim.Adam(model.parameters(), lr=modellr)

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

# 定义训练过程

def train(model, device, train_loader, optimizer, epoch):

   model.train()

   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()

       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()))

# 定义测试过程

def val(model, device, test_loader):

   model.eval()

   test_loss = 0

   correct = 0

   with torch.no_grad():

       for data, target in test_loader:

           data, target = data.to(device), target.to(device).float().unsqueeze(1)

           output = model(data)

           # print(output)

           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()

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

           test_loss, correct, len(test_loader.dataset),

           100. * correct / len(test_loader.dataset)))

# 训练

for epoch in range(1, EPOCHS + 1):

   adjust_learning_rate(optimizer, epoch)

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

   val(model, DEVICE, test_loader)

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

测试

完整代码:

from __future__ import print_function, division

from PIL import Image

from torchvision import transforms

import torch.nn.functional as F

import torch

import torch.nn as nn

import torch.nn.parallel

# 定义网络

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

# 模型存储路径

model_save_path = 'model.pth'

# ------------------------ 加载数据 --------------------------- #

# Data augmentation and normalization for training

# Just normalization for validation

# 定义预训练变换

# 数据预处理

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])

])

class_names = ['cat', 'dog']  # 这个顺序很重要,要和训练时候的类名顺序一致

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

# ------------------------ 载入模型并且训练 --------------------------- #

model = torch.load(model_save_path)

model.eval()

# print(model)

image_PIL = Image.open('dog.12.jpg')

#

image_tensor = transform_test(image_PIL)

# 以下语句等效于 image_tensor = torch.unsqueeze(image_tensor, 0)

image_tensor.unsqueeze_(0)

# 没有这句话会报错

image_tensor = image_tensor.to(device)

out = model(image_tensor)

pred = torch.tensor([[1] if num[0] >= 0.5 else [0] for num in out]).to(device)

print(class_names[pred])

运行结果:


tt.png


目录
相关文章
|
30天前
|
算法 PyTorch 算法框架/工具
Pytorch学习笔记(九):Pytorch模型的FLOPs、模型参数量等信息输出(torchstat、thop、ptflops、torchsummary)
本文介绍了如何使用torchstat、thop、ptflops和torchsummary等工具来计算Pytorch模型的FLOPs、模型参数量等信息。
145 2
|
2月前
|
机器学习/深度学习 存储 PyTorch
PyTorch自定义学习率调度器实现指南
本文将详细介绍如何通过扩展PyTorch的 ``` LRScheduler ``` 类来实现一个具有预热阶段的余弦衰减调度器。我们将分五个关键步骤来完成这个过程。
81 2
|
1月前
|
机器学习/深度学习 自然语言处理 监控
利用 PyTorch Lightning 搭建一个文本分类模型
利用 PyTorch Lightning 搭建一个文本分类模型
52 8
利用 PyTorch Lightning 搭建一个文本分类模型
|
1月前
|
机器学习/深度学习 自然语言处理 数据建模
三种Transformer模型中的注意力机制介绍及Pytorch实现:从自注意力到因果自注意力
本文深入探讨了Transformer模型中的三种关键注意力机制:自注意力、交叉注意力和因果自注意力,这些机制是GPT-4、Llama等大型语言模型的核心。文章不仅讲解了理论概念,还通过Python和PyTorch从零开始实现这些机制,帮助读者深入理解其内部工作原理。自注意力机制通过整合上下文信息增强了输入嵌入,多头注意力则通过多个并行的注意力头捕捉不同类型的依赖关系。交叉注意力则允许模型在两个不同输入序列间传递信息,适用于机器翻译和图像描述等任务。因果自注意力确保模型在生成文本时仅考虑先前的上下文,适用于解码器风格的模型。通过本文的详细解析和代码实现,读者可以全面掌握这些机制的应用潜力。
48 3
三种Transformer模型中的注意力机制介绍及Pytorch实现:从自注意力到因果自注意力
|
2月前
|
并行计算 PyTorch 算法框架/工具
基于CUDA12.1+CUDNN8.9+PYTORCH2.3.1,实现自定义数据集训练
文章介绍了如何在CUDA 12.1、CUDNN 8.9和PyTorch 2.3.1环境下实现自定义数据集的训练,包括环境配置、预览结果和核心步骤,以及遇到问题的解决方法和参考链接。
101 4
基于CUDA12.1+CUDNN8.9+PYTORCH2.3.1,实现自定义数据集训练
|
2月前
|
机器学习/深度学习 PyTorch 调度
在Pytorch中为不同层设置不同学习率来提升性能,优化深度学习模型
在深度学习中,学习率作为关键超参数对模型收敛速度和性能至关重要。传统方法采用统一学习率,但研究表明为不同层设置差异化学习率能显著提升性能。本文探讨了这一策略的理论基础及PyTorch实现方法,包括模型定义、参数分组、优化器配置及训练流程。通过示例展示了如何为ResNet18设置不同层的学习率,并介绍了渐进式解冻和层适应学习率等高级技巧,帮助研究者更好地优化模型训练。
129 4
在Pytorch中为不同层设置不同学习率来提升性能,优化深度学习模型
|
2月前
|
机器学习/深度学习 监控 PyTorch
PyTorch 模型调试与故障排除指南
在深度学习领域,PyTorch 成为开发和训练神经网络的主要框架之一。本文为 PyTorch 开发者提供全面的调试指南,涵盖从基础概念到高级技术的内容。目标读者包括初学者、中级开发者和高级工程师。本文探讨常见问题及解决方案,帮助读者理解 PyTorch 的核心概念、掌握调试策略、识别性能瓶颈,并通过实际案例获得实践经验。无论是在构建简单神经网络还是复杂模型,本文都将提供宝贵的洞察和实用技巧,帮助开发者更高效地开发和优化 PyTorch 模型。
40 3
PyTorch 模型调试与故障排除指南
|
1月前
|
存储 并行计算 PyTorch
探索PyTorch:模型的定义和保存方法
探索PyTorch:模型的定义和保存方法
|
3月前
|
机器学习/深度学习 PyTorch 编译器
PyTorch 与 TorchScript:模型的序列化与加速
【8月更文第27天】PyTorch 是一个非常流行的深度学习框架,它以其灵活性和易用性而著称。然而,当涉及到模型的部署和性能优化时,PyTorch 的动态计算图可能会带来一些挑战。为了解决这些问题,PyTorch 引入了 TorchScript,这是一个用于序列化和优化 PyTorch 模型的工具。本文将详细介绍如何使用 TorchScript 来序列化 PyTorch 模型以及如何加速模型的执行。
113 4
|
3月前
|
机器学习/深度学习 边缘计算 PyTorch
PyTorch 与边缘计算:将深度学习模型部署到嵌入式设备
【8月更文第29天】随着物联网技术的发展,越来越多的数据处理任务开始在边缘设备上执行,以减少网络延迟、降低带宽成本并提高隐私保护水平。PyTorch 是一个广泛使用的深度学习框架,它不仅支持高效的模型训练,还提供了多种工具帮助开发者将模型部署到边缘设备。本文将探讨如何将PyTorch模型高效地部署到嵌入式设备上,并通过一个具体的示例来展示整个流程。
466 1
下一篇
无影云桌面