当前位置:   article > 正文

Kaggle数据集猫狗分类(Pytorch+ResNet34预训练)99%以上正确率_狗猫训练集

狗猫训练集

关于训练集的介绍和数据划分可以参照上一个博客:

https://blog.csdn.net/qq_41685265/article/details/104895273

数据加载

  1. class DogCat(data.Dataset):
  2. def __init__(self, root, transforms=None, train=True, test=False):
  3. """
  4. 主要目标: 获取所有图片的地址,并根据训练,验证,测试划分数据
  5. """
  6. self.test = test
  7. imgs = [os.path.join(root, img) for img in os.listdir(root)]
  8. # test1: data/test1/8973.jpg
  9. # train: data/train/cat.10004.jpg
  10. if self.test:
  11. imgs = sorted(imgs, key=lambda x: int(x.split('.')[-2].split('/')[-1]))
  12. else:
  13. imgs = sorted(imgs, key=lambda x: int(x.split('.')[-2]))
  14. imgs_num = len(imgs)
  15. if self.test:
  16. self.imgs = imgs
  17. elif train:
  18. self.imgs = imgs[:int(0.7 * imgs_num)]
  19. else:
  20. self.imgs = imgs[int(0.7 * imgs_num):]
  21. if transforms is None:
  22. normalize = T.Normalize(mean=[0.485, 0.456, 0.406],
  23. std=[0.229, 0.224, 0.225])
  24. if self.test or not train:
  25. self.transforms = T.Compose([
  26. T.Resize(224),
  27. T.CenterCrop(224),
  28. T.ToTensor(),
  29. normalize
  30. ])
  31. else:
  32. self.transforms = T.Compose([
  33. T.Resize(256),
  34. T.CenterCrop(224),
  35. T.RandomHorizontalFlip(),
  36. T.ToTensor(),
  37. normalize
  38. ])
  39. def __getitem__(self, index):
  40. """
  41. 一次返回一张图片的数据
  42. """
  43. img_path = self.imgs[index]
  44. if self.test:
  45. label = int(self.imgs[index].split('.')[-2].split('/')[-1])
  46. else:
  47. label = 1 if 'dog' in img_path.split('/')[-1] else 0
  48. data = Image.open(img_path)
  49. data = self.transforms(data)
  50. return data, label
  51. def __len__(self):
  52. return len(self.imgs)

参数设置

有一些参数没有用得上

  1. class DefaultConfig(object):
  2. env = 'default' # visdom 环境
  3. vis_port = 8097 # visdom 端口
  4. model = 'ResNet34' # 使用的模型,名字必须与models/__init__.py中的名字一致
  5. train_data_root = '/media/cyq/CU/Ubuntu system files/dogs-vs-cats/train/' # 训练集存放路径
  6. test_data_root = '/media/cyq/CU/Ubuntu system files/dogs-vs-cats/test/' # 测试集存放路径
  7. load_model_path = None # 加载预训练的模型的路径,为None代表不加载
  8. batch_size = 48 # batch size
  9. use_gpu = True # user GPU or not
  10. num_workers = 4 # how many workers for loading data
  11. print_freq = 20 # print info every N batch
  12. debug_file = '/tmp/debug' # if os.path.exists(debug_file): enter ipdb
  13. result_file = 'result.csv'
  14. max_epoch = 10
  15. lr = 0.001 # initial learning rate
  16. lr_decay = 0.5 # when val_loss increase, lr = lr*lr_decay
  17. weight_decay = 0e-5 # 损失函数
  18. opt = DefaultConfig()

定义网络结构

  1. class ResNet34(nn.Module):
  2. """
  3. 实现主module:ResNet34
  4. ResNet34包含多个layer,每个layer又包含多个Residual block
  5. 用子module来实现Residual block,用_make_layer函数来实现layer
  6. """
  7. def __init__(self, num_classes=2):
  8. super(ResNet34, self).__init__()
  9. self.model_name = 'resnet34'
  10. # 前几层: 图像转换
  11. resnet34 = models.resnet34(pretrained=True)
  12. self.resnet = nn.Sequential(*list(resnet34.children())[:-1])
  13. self.fc = nn.Linear(in_features=512, out_features=num_classes)
  14. def forward(self, x):
  15. x = self.resnet(x)
  16. x = x.view(x.size(0), -1)
  17. x = self.fc(x)
  18. return x
  19. device = "cuda" if opt.use_gpu==True else "cpu"
  20. net = ResNet34()
  21. net.to(device)

模型训练

  1. def val(model,dataloader):
  2. """
  3. 计算模型在验证集上的准确率等信息
  4. """
  5. model.eval()
  6. confusion_matrix = meter.ConfusionMeter(2)
  7. for ii, (val_input, label) in tqdm(enumerate(dataloader)):
  8. val_input = val_input.to(device)
  9. with torch.no_grad():
  10. score = model(val_input)
  11. confusion_matrix.add(score.detach().squeeze(), label.type(t.LongTensor))
  12. model.train()
  13. cm_value = confusion_matrix.value()
  14. accuracy = 100. * (cm_value[0][0] + cm_value[1][1]) / (cm_value.sum())
  15. return confusion_matrix, accuracy
  16. def train():
  17. # step1: configure model
  18. # net
  19. # step2: data
  20. train_data = DogCat(opt.train_data_root, train=True)
  21. # print(len(train_data))
  22. val_data = DogCat(opt.train_data_root, train=False)
  23. train_dataloader = DataLoader(train_data, opt.batch_size,
  24. shuffle=True, num_workers=opt.num_workers)
  25. val_dataloader = DataLoader(val_data, opt.batch_size,
  26. shuffle=False, num_workers=opt.num_workers)
  27. # step3: criterion and optimizer
  28. criterion = nn.CrossEntropyLoss()
  29. optimizer = torch.optim.SGD(filter(lambda p: p.requires_grad, net.parameters()), lr=opt.lr, momentum=0.9)
  30. lr = opt.lr
  31. # step4: meters
  32. loss_meter = meter.AverageValueMeter()
  33. confusion_matrix = meter.ConfusionMeter(2)
  34. previous_loss = 1e10
  35. # train
  36. for epoch in range(opt.max_epoch):
  37. # print(epoch)
  38. loss_meter.reset()
  39. confusion_matrix.reset()
  40. for input, label in train_dataloader:
  41. # train model
  42. input = input.to(device)
  43. target = label.to(device)
  44. optimizer.zero_grad()
  45. score = net(input)
  46. loss = criterion(score, target)
  47. loss.backward()
  48. optimizer.step()
  49. # meters update and visualize
  50. loss_meter.add(loss.item())
  51. # detach 一下更安全保险
  52. confusion_matrix.add(score.detach(), target.detach())
  53. # validate and visualize
  54. val_cm, val_accuracy = val(net, val_dataloader)
  55. # vis.plot('val_accuracy', val_accuracy)
  56. print("epoch:{epoch},lr:{lr},loss:{loss},train_cm:{train_cm},val_cm:{val_cm}".format(
  57. epoch=epoch, loss=loss_meter.value()[0], val_cm=str(val_cm.value()), train_cm=str(confusion_matrix.value()),
  58. lr=lr))
  59. cm_train = confusion_matrix.value()
  60. train_accuracy = 100. * (cm_train[0][0] + cm_train[1][1]) / (cm_train.sum())
  61. print("train-ACC: %.3f"%train_accuracy)
  62. print("val-ACC: %.3f"%val_accuracy)
  63. previous_loss = loss_meter.value()[0]

结果输出

由于使用了预训练的模型,因此网络在迭代到第二代时,验证机正确率已经超过了99%,在5-10代时,训练集精度已经在99.5%左右,下边从测试机中选出几个检验:

 模型的输出结果为:

  1. 1,4.009683834738098e-06
  2. 2,1.8512298538553296e-06
  3. 3,1.0709993148338981e-05
  4. 4,1.2812791283067781e-05
  5. 5,0.9999998807907104
  6. 6,0.999983549118042
  7. 7,0.9999879598617554
  8. 8,0.9999997615814209
  9. 9,0.9999997615814209
  10. 10,0.9999998807907104
  11. 11,0.9999719858169556
  12. 12,4.395487849251367e-06
  13. 13,0.9999877214431763
  14. 14,0.999725878238678
  15. 15,0.9999864101409912
  16. 16,0.9999921321868896

0代表狗,1代表猫,很显然上边的数据的分类效果是很好的

代码

  1. # coding:utf8
  2. import os
  3. from PIL import Image
  4. from torch.utils import data
  5. import numpy as np
  6. from torchvision import transforms as T
  7. import torch as t
  8. import torch.nn as nn
  9. from torchvision import datasets, models, transforms
  10. from torch.utils.data import DataLoader
  11. from torchnet import meter
  12. from tqdm import tqdm
  13. import torch
  14. import csv
  15. class DogCat(data.Dataset):
  16. def __init__(self, root, transforms=None, train=True, test=False):
  17. """
  18. 主要目标: 获取所有图片的地址,并根据训练,验证,测试划分数据
  19. """
  20. self.test = test
  21. imgs = [os.path.join(root, img) for img in os.listdir(root)]
  22. # test1: data/test1/8973.jpg
  23. # train: data/train/cat.10004.jpg
  24. if self.test:
  25. imgs = sorted(imgs, key=lambda x: int(x.split('.')[-2].split('/')[-1]))
  26. else:
  27. imgs = sorted(imgs, key=lambda x: int(x.split('.')[-2]))
  28. imgs_num = len(imgs)
  29. if self.test:
  30. self.imgs = imgs
  31. elif train:
  32. self.imgs = imgs[:int(0.7 * imgs_num)]
  33. else:
  34. self.imgs = imgs[int(0.7 * imgs_num):]
  35. if transforms is None:
  36. normalize = T.Normalize(mean=[0.485, 0.456, 0.406],
  37. std=[0.229, 0.224, 0.225])
  38. if self.test or not train:
  39. self.transforms = T.Compose([
  40. T.Resize(224),
  41. T.CenterCrop(224),
  42. T.ToTensor(),
  43. normalize
  44. ])
  45. else:
  46. self.transforms = T.Compose([
  47. T.Resize(256),
  48. T.CenterCrop(224),
  49. T.RandomHorizontalFlip(),
  50. T.ToTensor(),
  51. normalize
  52. ])
  53. def __getitem__(self, index):
  54. """
  55. 一次返回一张图片的数据
  56. """
  57. img_path = self.imgs[index]
  58. if self.test:
  59. label = int(self.imgs[index].split('.')[-2].split('/')[-1])
  60. else:
  61. label = 1 if 'dog' in img_path.split('/')[-1] else 0
  62. data = Image.open(img_path)
  63. data = self.transforms(data)
  64. return data, label
  65. def __len__(self):
  66. return len(self.imgs)
  67. class DefaultConfig(object):
  68. env = 'default' # visdom 环境
  69. vis_port = 8097 # visdom 端口
  70. model = 'ResNet34' # 使用的模型,名字必须与models/__init__.py中的名字一致
  71. train_data_root = '/media/cyq/CU/Ubuntu system files/dogs-vs-cats/train/' # 训练集存放路径
  72. test_data_root = '/media/cyq/CU/Ubuntu system files/dogs-vs-cats/test/' # 测试集存放路径
  73. load_model_path = None # 加载预训练的模型的路径,为None代表不加载
  74. batch_size = 48 # batch size
  75. use_gpu = True # user GPU or not
  76. num_workers = 4 # how many workers for loading data
  77. print_freq = 20 # print info every N batch
  78. debug_file = '/tmp/debug' # if os.path.exists(debug_file): enter ipdb
  79. result_file = 'result.csv'
  80. max_epoch = 10
  81. lr = 0.001 # initial learning rate
  82. lr_decay = 0.5 # when val_loss increase, lr = lr*lr_decay
  83. weight_decay = 0e-5 # 损失函数
  84. opt = DefaultConfig()
  85. class ResNet34(nn.Module):
  86. """
  87. 实现主module:ResNet34
  88. ResNet34包含多个layer,每个layer又包含多个Residual block
  89. 用子module来实现Residual block,用_make_layer函数来实现layer
  90. """
  91. def __init__(self, num_classes=2):
  92. super(ResNet34, self).__init__()
  93. self.model_name = 'resnet34'
  94. # 前几层: 图像转换
  95. resnet34 = models.resnet34(pretrained=True)
  96. self.resnet = nn.Sequential(*list(resnet34.children())[:-1])
  97. self.fc = nn.Linear(in_features=512, out_features=num_classes)
  98. def forward(self, x):
  99. x = self.resnet(x)
  100. x = x.view(x.size(0), -1)
  101. x = self.fc(x)
  102. return x
  103. device = "cuda" if opt.use_gpu==True else "cpu"
  104. net = ResNet34()
  105. net.to(device)
  106. def val(model,dataloader):
  107. """
  108. 计算模型在验证集上的准确率等信息
  109. """
  110. model.eval()
  111. confusion_matrix = meter.ConfusionMeter(2)
  112. for ii, (val_input, label) in tqdm(enumerate(dataloader)):
  113. val_input = val_input.to(device)
  114. with torch.no_grad():
  115. score = model(val_input)
  116. confusion_matrix.add(score.detach().squeeze(), label.type(t.LongTensor))
  117. model.train()
  118. cm_value = confusion_matrix.value()
  119. accuracy = 100. * (cm_value[0][0] + cm_value[1][1]) / (cm_value.sum())
  120. return confusion_matrix, accuracy
  121. def train():
  122. # step1: configure model
  123. # net
  124. # step2: data
  125. train_data = DogCat(opt.train_data_root, train=True)
  126. # print(len(train_data))
  127. val_data = DogCat(opt.train_data_root, train=False)
  128. train_dataloader = DataLoader(train_data, opt.batch_size,
  129. shuffle=True, num_workers=opt.num_workers)
  130. val_dataloader = DataLoader(val_data, opt.batch_size,
  131. shuffle=False, num_workers=opt.num_workers)
  132. # step3: criterion and optimizer
  133. criterion = nn.CrossEntropyLoss()
  134. optimizer = torch.optim.SGD(filter(lambda p: p.requires_grad, net.parameters()), lr=opt.lr, momentum=0.9)
  135. lr = opt.lr
  136. # step4: meters
  137. loss_meter = meter.AverageValueMeter()
  138. confusion_matrix = meter.ConfusionMeter(2)
  139. previous_loss = 1e10
  140. # train
  141. for epoch in range(opt.max_epoch):
  142. # print(epoch)
  143. loss_meter.reset()
  144. confusion_matrix.reset()
  145. for input, label in train_dataloader:
  146. # train model
  147. input = input.to(device)
  148. target = label.to(device)
  149. optimizer.zero_grad()
  150. score = net(input)
  151. loss = criterion(score, target)
  152. loss.backward()
  153. optimizer.step()
  154. # meters update and visualize
  155. loss_meter.add(loss.item())
  156. # detach 一下更安全保险
  157. confusion_matrix.add(score.detach(), target.detach())
  158. # validate and visualize
  159. val_cm, val_accuracy = val(net, val_dataloader)
  160. # vis.plot('val_accuracy', val_accuracy)
  161. print("epoch:{epoch},lr:{lr},loss:{loss},train_cm:{train_cm},val_cm:{val_cm}".format(
  162. epoch=epoch, loss=loss_meter.value()[0], val_cm=str(val_cm.value()), train_cm=str(confusion_matrix.value()),
  163. lr=lr))
  164. cm_train = confusion_matrix.value()
  165. train_accuracy = 100. * (cm_train[0][0] + cm_train[1][1]) / (cm_train.sum())
  166. print("train-ACC: %.3f"%train_accuracy)
  167. print("val-ACC: %.3f"%val_accuracy)
  168. previous_loss = loss_meter.value()[0]
  169. train()
  170. torch.save(net, 'model.pkl')

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/385249?site
推荐阅读
相关标签
  

闽ICP备14008679号