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

举报
AI浩 发表于 2021/12/23 01:37:51 2021/12/23
【摘要】 摘要 本例采用猫狗大战的部分数据作为数据集,模型是自定义的模型。 训练 1、构建数据集 在data文件夹下面新家train和val文件夹,分别在train和val文件夹下面新家cat和dog文件夹,并将图片放进去。如图: 2、导入库 # 导入库import torch.nn.functional as Fimpo...

摘要

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

训练

  • 1、构建数据集

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

  • 2、导入库


  
  1. # 导入库
  2. import torch.nn.functional as F
  3. import torch.optim as optim
  4. import torch
  5. import torch.nn as nn
  6. import torch.nn.parallel
  7. import torch.optim
  8. import torch.utils.data
  9. import torch.utils.data.distributed
  10. import torchvision.transforms as transforms
  11. import torchvision.datasets as datasets
  • 3、设置超参数


  
  1. # 设置超参数
  2. BATCH_SIZE = 20
  3. EPOCHS = 10
  4. DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  • 4、图像处理与图像增强


  
  1. # 数据预处理
  2. transform = transforms.Compose([
  3.     transforms.Resize(100),
  4.     transforms.RandomVerticalFlip(),
  5.     transforms.RandomCrop(50),
  6.     transforms.RandomResizedCrop(150),
  7.     transforms.ColorJitter(brightness=0.5, contrast=0.5, hue=0.5),
  8.     transforms.ToTensor(),
  9.     transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
  10. ])
  • 5、读取数据和导入数据


  
  1. # 读取数据
  2. dataset_train = datasets.ImageFolder('data/train', transform)
  3. print(dataset_train.imgs)
  4. # 对应文件夹的label
  5. print(dataset_train.class_to_idx)
  6. dataset_test = datasets.ImageFolder('data/val', transform)
  7. # 对应文件夹的label
  8. print(dataset_test.class_to_idx)
  9. # 导入数据
  10. train_loader = torch.utils.data.DataLoader(dataset_train, batch_size=BATCH_SIZE, shuffle=True)
  11. test_loader = torch.utils.data.DataLoader(dataset_test, batch_size=BATCH_SIZE, shuffle=True)
  • 6、定义网络模型


  
  1. # 定义网络
  2. class ConvNet(nn.Module):
  3.     def __init__(self):
  4.         super(ConvNet, self).__init__()
  5.         self.conv1 = nn.Conv2d(3, 32, 3)
  6.         self.max_pool1 = nn.MaxPool2d(2)
  7.         self.conv2 = nn.Conv2d(32, 64, 3)
  8.         self.max_pool2 = nn.MaxPool2d(2)
  9.         self.conv3 = nn.Conv2d(64, 64, 3)
  10.         self.conv4 = nn.Conv2d(64, 64, 3)
  11.         self.max_pool3 = nn.MaxPool2d(2)
  12.         self.conv5 = nn.Conv2d(64, 128, 3)
  13.         self.conv6 = nn.Conv2d(128, 128, 3)
  14.         self.max_pool4 = nn.MaxPool2d(2)
  15.         self.fc1 = nn.Linear(4608, 512)
  16.         self.fc2 = nn.Linear(512, 1)
  17.     def forward(self, x):
  18.         in_size = x.size(0)
  19.         x = self.conv1(x)
  20.         x = F.relu(x)
  21.         x = self.max_pool1(x)
  22.         x = self.conv2(x)
  23.         x = F.relu(x)
  24.         x = self.max_pool2(x)
  25.         x = self.conv3(x)
  26.         x = F.relu(x)
  27.         x = self.conv4(x)
  28.         x = F.relu(x)
  29.         x = self.max_pool3(x)
  30.         x = self.conv5(x)
  31.         x = F.relu(x)
  32.         x = self.conv6(x)
  33.         x = F.relu(x)
  34.         x = self.max_pool4(x)
  35.         # 展开
  36.         x = x.view(in_size, -1)
  37.         x = self.fc1(x)
  38.         x = F.relu(x)
  39.         x = self.fc2(x)
  40.         x = torch.sigmoid(x)
  41.         return x
  42. modellr = 1e-4
  43. # 实例化模型并且移动到GPU
  44. model = ConvNet().to(DEVICE)
  45. # 选择简单暴力的Adam优化器,学习率调低
  46. optimizer = optim.Adam(model.parameters(), lr=modellr)
  • 7、调整学习率


  
  1. def adjust_learning_rate(optimizer, epoch):
  2.     """Sets the learning rate to the initial LR decayed by 10 every 30 epochs"""
  3.     modellrnew = modellr * (0.1 ** (epoch // 5))
  4.     print("lr:",modellrnew)
  5.     for param_group in optimizer.param_groups:
  6.         param_group['lr'] = modellrnew
  • 8、定义训练与验证方法


  
  1. # 定义训练过程
  2. def train(model, device, train_loader, optimizer, epoch):
  3.     model.train()
  4.     for batch_idx, (data, target) in enumerate(train_loader):
  5.         data, target = data.to(device), target.to(device).float().unsqueeze(1)
  6.         optimizer.zero_grad()
  7.         output = model(data)
  8.         # print(output)
  9.         loss = F.binary_cross_entropy(output, target)
  10.         loss.backward()
  11.         optimizer.step()
  12.         if (batch_idx + 1) % 10 == 0:
  13.             print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
  14.                 epoch, (batch_idx + 1) * len(data), len(train_loader.dataset),
  15.                        100. * (batch_idx + 1) / len(train_loader), loss.item()))
  16. # 定义测试过程
  17. def val(model, device, test_loader):
  18.     model.eval()
  19.     test_loss = 0
  20.     correct = 0
  21.     with torch.no_grad():
  22.         for data, target in test_loader:
  23.             data, target = data.to(device), target.to(device).float().unsqueeze(1)
  24.             output = model(data)
  25.             # print(output)
  26.             test_loss += F.binary_cross_entropy(output, target, reduction='mean').item()  # 将一批的损失相加
  27.             pred = torch.tensor([[1] if num[0] >= 0.5 else [0] for num in output]).to(device)
  28.             correct += pred.eq(target.long()).sum().item()
  29.         print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
  30.             test_loss, correct, len(test_loader.dataset),
  31.             100. * correct / len(test_loader.dataset)))

9、训练并保存模型


  
  1. # 训练
  2. for epoch in range(1, EPOCHS + 1):
  3.     adjust_learning_rate(optimizer, epoch)
  4.     train(model, DEVICE, train_loader, optimizer, epoch)
  5.     val(model, DEVICE, test_loader)
  6. torch.save(model, 'model.pth')

完整代码:


  
  1. # 导入库
  2. import torch.nn.functional as F
  3. import torch.optim as optim
  4. import torch
  5. import torch.nn as nn
  6. import torch.nn.parallel
  7. import torch.optim
  8. import torch.utils.data
  9. import torch.utils.data.distributed
  10. import torchvision.transforms as transforms
  11. import torchvision.datasets as datasets
  12. # 设置超参数
  13. BATCH_SIZE = 20
  14. EPOCHS = 10
  15. DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  16. # 数据预处理
  17. transform = transforms.Compose([
  18.     transforms.Resize(100),
  19.     transforms.RandomVerticalFlip(),
  20.     transforms.RandomCrop(50),
  21.     transforms.RandomResizedCrop(150),
  22.     transforms.ColorJitter(brightness=0.5, contrast=0.5, hue=0.5),
  23.     transforms.ToTensor(),
  24.     transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
  25. ])
  26. # 读取数据
  27. dataset_train = datasets.ImageFolder('data/train', transform)
  28. print(dataset_train.imgs)
  29. # 对应文件夹的label
  30. print(dataset_train.class_to_idx)
  31. dataset_test = datasets.ImageFolder('data/val', transform)
  32. # 对应文件夹的label
  33. print(dataset_test.class_to_idx)
  34. # 导入数据
  35. train_loader = torch.utils.data.DataLoader(dataset_train, batch_size=BATCH_SIZE, shuffle=True)
  36. test_loader = torch.utils.data.DataLoader(dataset_test, batch_size=BATCH_SIZE, shuffle=True)
  37. # 定义网络
  38. class ConvNet(nn.Module):
  39.     def __init__(self):
  40.         super(ConvNet, self).__init__()
  41.         self.conv1 = nn.Conv2d(3, 32, 3)
  42.         self.max_pool1 = nn.MaxPool2d(2)
  43.         self.conv2 = nn.Conv2d(32, 64, 3)
  44.         self.max_pool2 = nn.MaxPool2d(2)
  45.         self.conv3 = nn.Conv2d(64, 64, 3)
  46.         self.conv4 = nn.Conv2d(64, 64, 3)
  47.         self.max_pool3 = nn.MaxPool2d(2)
  48.         self.conv5 = nn.Conv2d(64, 128, 3)
  49.         self.conv6 = nn.Conv2d(128, 128, 3)
  50.         self.max_pool4 = nn.MaxPool2d(2)
  51.         self.fc1 = nn.Linear(4608, 512)
  52.         self.fc2 = nn.Linear(512, 1)
  53.     def forward(self, x):
  54.         in_size = x.size(0)
  55.         x = self.conv1(x)
  56.         x = F.relu(x)
  57.         x = self.max_pool1(x)
  58.         x = self.conv2(x)
  59.         x = F.relu(x)
  60.         x = self.max_pool2(x)
  61.         x = self.conv3(x)
  62.         x = F.relu(x)
  63.         x = self.conv4(x)
  64.         x = F.relu(x)
  65.         x = self.max_pool3(x)
  66.         x = self.conv5(x)
  67.         x = F.relu(x)
  68.         x = self.conv6(x)
  69.         x = F.relu(x)
  70.         x = self.max_pool4(x)
  71.         # 展开
  72.         x = x.view(in_size, -1)
  73.         x = self.fc1(x)
  74.         x = F.relu(x)
  75.         x = self.fc2(x)
  76.         x = torch.sigmoid(x)
  77.         return x
  78. modellr = 1e-4
  79. # 实例化模型并且移动到GPU
  80. model = ConvNet().to(DEVICE)
  81. # 选择简单暴力的Adam优化器,学习率调低
  82. optimizer = optim.Adam(model.parameters(), lr=modellr)
  83. def adjust_learning_rate(optimizer, epoch):
  84.     """Sets the learning rate to the initial LR decayed by 10 every 30 epochs"""
  85.     modellrnew = modellr * (0.1 ** (epoch // 5))
  86.     print("lr:",modellrnew)
  87.     for param_group in optimizer.param_groups:
  88.         param_group['lr'] = modellrnew
  89. # 定义训练过程
  90. def train(model, device, train_loader, optimizer, epoch):
  91.     model.train()
  92.     for batch_idx, (data, target) in enumerate(train_loader):
  93.         data, target = data.to(device), target.to(device).float().unsqueeze(1)
  94.         optimizer.zero_grad()
  95.         output = model(data)
  96.         # print(output)
  97.         loss = F.binary_cross_entropy(output, target)
  98.         loss.backward()
  99.         optimizer.step()
  100.         if (batch_idx + 1) % 10 == 0:
  101.             print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
  102.                 epoch, (batch_idx + 1) * len(data), len(train_loader.dataset),
  103.                        100. * (batch_idx + 1) / len(train_loader), loss.item()))
  104. # 定义测试过程
  105. def val(model, device, test_loader):
  106.     model.eval()
  107.     test_loss = 0
  108.     correct = 0
  109.     with torch.no_grad():
  110.         for data, target in test_loader:
  111.             data, target = data.to(device), target.to(device).float().unsqueeze(1)
  112.             output = model(data)
  113.             # print(output)
  114.             test_loss += F.binary_cross_entropy(output, target, reduction='mean').item()  # 将一批的损失相加
  115.             pred = torch.tensor([[1] if num[0] >= 0.5 else [0] for num in output]).to(device)
  116.             correct += pred.eq(target.long()).sum().item()
  117.         print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
  118.             test_loss, correct, len(test_loader.dataset),
  119.             100. * correct / len(test_loader.dataset)))
  120. # 训练
  121. for epoch in range(1, EPOCHS + 1):
  122.     adjust_learning_rate(optimizer, epoch)
  123.     train(model, DEVICE, train_loader, optimizer, epoch)
  124.     val(model, DEVICE, test_loader)
  125. torch.save(model, 'model.pth')

测试

完整代码:


  
  1. from __future__ import print_function, division
  2. from PIL import Image
  3. from torchvision import transforms
  4. import torch.nn.functional as F
  5. import torch
  6. import torch.nn as nn
  7. import torch.nn.parallel
  8. # 定义网络
  9. class ConvNet(nn.Module):
  10. def __init__(self):
  11. super(ConvNet, self).__init__()
  12. self.conv1 = nn.Conv2d(3, 32, 3)
  13. self.max_pool1 = nn.MaxPool2d(2)
  14. self.conv2 = nn.Conv2d(32, 64, 3)
  15. self.max_pool2 = nn.MaxPool2d(2)
  16. self.conv3 = nn.Conv2d(64, 64, 3)
  17. self.conv4 = nn.Conv2d(64, 64, 3)
  18. self.max_pool3 = nn.MaxPool2d(2)
  19. self.conv5 = nn.Conv2d(64, 128, 3)
  20. self.conv6 = nn.Conv2d(128, 128, 3)
  21. self.max_pool4 = nn.MaxPool2d(2)
  22. self.fc1 = nn.Linear(4608, 512)
  23. self.fc2 = nn.Linear(512, 1)
  24. def forward(self, x):
  25. in_size = x.size(0)
  26. x = self.conv1(x)
  27. x = F.relu(x)
  28. x = self.max_pool1(x)
  29. x = self.conv2(x)
  30. x = F.relu(x)
  31. x = self.max_pool2(x)
  32. x = self.conv3(x)
  33. x = F.relu(x)
  34. x = self.conv4(x)
  35. x = F.relu(x)
  36. x = self.max_pool3(x)
  37. x = self.conv5(x)
  38. x = F.relu(x)
  39. x = self.conv6(x)
  40. x = F.relu(x)
  41. x = self.max_pool4(x)
  42. # 展开
  43. x = x.view(in_size, -1)
  44. x = self.fc1(x)
  45. x = F.relu(x)
  46. x = self.fc2(x)
  47. x = torch.sigmoid(x)
  48. return x
  49. # 模型存储路径
  50. model_save_path = 'model.pth'
  51. # ------------------------ 加载数据 --------------------------- #
  52. # Data augmentation and normalization for training
  53. # Just normalization for validation
  54. # 定义预训练变换
  55. # 数据预处理
  56. transform_test = transforms.Compose([
  57. transforms.Resize(100),
  58. transforms.RandomVerticalFlip(),
  59. transforms.RandomCrop(50),
  60. transforms.RandomResizedCrop(150),
  61. transforms.ColorJitter(brightness=0.5, contrast=0.5, hue=0.5),
  62. transforms.ToTensor(),
  63. transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
  64. ])
  65. class_names = ['cat', 'dog'] # 这个顺序很重要,要和训练时候的类名顺序一致
  66. device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  67. # ------------------------ 载入模型并且训练 --------------------------- #
  68. model = torch.load(model_save_path)
  69. model.eval()
  70. # print(model)
  71. image_PIL = Image.open('dog.12.jpg')
  72. #
  73. image_tensor = transform_test(image_PIL)
  74. # 以下语句等效于 image_tensor = torch.unsqueeze(image_tensor, 0)
  75. image_tensor.unsqueeze_(0)
  76. # 没有这句话会报错
  77. image_tensor = image_tensor.to(device)
  78. out = model(image_tensor)
  79. pred = torch.tensor([[1] if num[0] >= 0.5 else [0] for num in out]).to(device)
  80. print(class_names[pred])

运行结果:

 

文章来源: wanghao.blog.csdn.net,作者:AI浩,版权归原作者所有,如需转载,请联系作者。

原文链接:wanghao.blog.csdn.net/article/details/110428926

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。