• dogs vs cats 二分类问题vgg16迁移学习


    在学习猫狗二分类问题时,我主要参考的是这篇博客:http://t.csdn.cn/J7L0n

    然后数据集下载的是:Dogs vs. Cats | Kaggle

    下载的数据集一共有25000张,这里采用CPU训练速度非常慢,25000张图片训练一次要4h,所以我们仅选取了200张dog,200张cat用来train,200张dog,200张cat作为test。(从原数据集的train中复制出自己的训练集)。

    数据集结构如下:

    • data1
      • train
        • cat(200)
        • dog(200)
      • test
        • cat(200)
        • dog(200)

    需要注意的是在以下代码中,train和test下必须要分类!

    文件:data1

    文件:dogs-vs-cats-迁移学习vgg16-train-small

    1. import torch
    2. import torchvision
    3. from torchvision import datasets,transforms,models
    4. import os
    5. import numpy as np
    6. import matplotlib.pyplot as plt
    7. from torch.autograd import Variable
    8. import time
    9. path='data1'
    10. transform=transforms.Compose([
    11. transforms.CenterCrop(224),
    12. transforms.ToTensor(),
    13. transforms.Normalize([0.5, 0.5, 0.5],[0.5, 0.5, 0.5])
    14. ])
    15. data_image={
    16. x:datasets.ImageFolder(root=os.path.join(path,x),
    17. transform=transform)
    18. for x in ["train","test"]
    19. }
    20. data_loader_image={
    21. x:torch.utils.data.DataLoader(dataset=data_image[x],
    22. batch_size=4,
    23. shuffle=True)
    24. for x in ["train","test"]
    25. }
    26. use_gpu=torch.cuda.is_available()
    27. print(use_gpu)
    28. classes=data_image["train"].classes #按文件夹名字分类
    29. classes_index=data_image["train"].class_to_idx #文件夹类名所对应的链值
    30. print(classes)
    31. print(classes_index)
    32. print("train data set:",len(data_image["train"]))
    33. print("test data set:",len(data_image["test"]))
    34. x_train,y_train=next(iter(data_loader_image["train"]))
    35. mean=[0.5, 0.5, 0.5]
    36. std=[0.5, 0.5, 0.5]
    37. img=torchvision.utils.make_grid(x_train)
    38. img=img.numpy().transpose((1,2,0))
    39. img=img*std+mean
    40. print([classes[i] for i in y_train])
    41. plt.imshow(img)
    42. plt.show()
    43. #选择预训练好的模型vgg16
    44. model=models.vgg16(pretrained=True)
    45. print(model)
    46. for parma in model.parameters():
    47. parma.requires_grad=False #预训练的网络不进行梯度更新
    48. #改变模型的全连接层,从原模型的1000个类到本项目的2个类
    49. model.classifier=torch.nn.Sequential(
    50. torch.nn.Linear(25088,4096),
    51. torch.nn.ReLU(),
    52. torch.nn.Dropout(p=0.5),
    53. torch.nn.Linear(4096,4096),
    54. torch.nn.ReLU(),
    55. torch.nn.Dropout(p=0.5),
    56. torch.nn.Linear(4096,2)
    57. )
    58. for index,parma in enumerate(model.classifier.parameters()):
    59. if index ==6:
    60. parma.requires_grad=True
    61. if use_gpu:
    62. model=model.cuda()
    63. print(parma)
    64. #定义代价函数和优化器
    65. cost=torch.nn.CrossEntropyLoss()
    66. optimizer=torch.optim.Adam(model.classifier.parameters())
    67. print(model)
    68. #开始训练模型
    69. n_epochs=1
    70. for epoch in range(n_epochs):
    71. since=time.time()
    72. print("Epoch{}/{}".format(epoch,n_epochs))
    73. print("-"*10)
    74. for param in ["train","test"]:
    75. if param == "train":
    76. model.train=True
    77. else:
    78. model.train=False
    79. running_loss=0.0
    80. running_correct=0
    81. batch=0
    82. for data in data_loader_image[param]:
    83. batch+=1
    84. x,y=data
    85. if use_gpu:
    86. x,y=Variable(x.cuda()),Variable(y.cuda())
    87. else:
    88. x,y=Variable(x),Variable(y)
    89. optimizer.zero_grad()
    90. y_pred=model(x)
    91. _,pred=torch.max(y_pred.data,1)
    92. loss=cost(y_pred,y)
    93. if param=="train":
    94. loss.backward()
    95. optimizer.step()
    96. running_loss+=loss.item() #running_loss+=loss.data[0]
    97. running_correct+=torch.sum(pred==y.data)
    98. if batch%10==0 and param=="train":
    99. print("Batch{},Train Loss:{:.4f},Train Acc:{:.4f}%".format(
    100. batch,running_loss/(4*batch),100*running_correct/(4*batch)))
    101. epoch_loss=running_loss/len(data_image[param])
    102. epoch_correct=100*running_correct/len(data_image[param])
    103. print("{}Loss:{:.4f},Correct:{:.4f}%".format(param,epoch_loss,epoch_correct))
    104. now_time=time.time()-since
    105. print("Training time is:{:.0f}m {:.0f}s".format(now_time//60,now_time%60))
    106. torch.save(model,'model.pth')
    107. #保存模型,备测试使用

    输出结果: 

    False
    ['cat', 'dog']
    {'cat': 0, 'dog': 1}
    train data set: 400
    test data set: 400
    ['cat', 'cat', 'dog', 'cat']
    

    VGG(
      (features): Sequential(
        (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (1): ReLU(inplace=True)
        (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (3): ReLU(inplace=True)
        (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (6): ReLU(inplace=True)
        (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (8): ReLU(inplace=True)
        (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (11): ReLU(inplace=True)
        (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (13): ReLU(inplace=True)
        (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (15): ReLU(inplace=True)
        (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (18): ReLU(inplace=True)
        (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (20): ReLU(inplace=True)
        (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (22): ReLU(inplace=True)
        (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (25): ReLU(inplace=True)
        (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (27): ReLU(inplace=True)
        (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (29): ReLU(inplace=True)
        (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
      )
      (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
      (classifier): Sequential(
        (0): Linear(in_features=25088, out_features=4096, bias=True)
        (1): ReLU(inplace=True)
        (2): Dropout(p=0.5, inplace=False)
        (3): Linear(in_features=4096, out_features=4096, bias=True)
        (4): ReLU(inplace=True)
        (5): Dropout(p=0.5, inplace=False)
        (6): Linear(in_features=4096, out_features=1000, bias=True)
      )
    )
    Parameter containing:
    tensor([-0.0110, -0.0124], requires_grad=True)
    VGG(
      (features): Sequential(
        (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (1): ReLU(inplace=True)
        (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (3): ReLU(inplace=True)
        (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (6): ReLU(inplace=True)
        (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (8): ReLU(inplace=True)
        (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (11): ReLU(inplace=True)
        (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (13): ReLU(inplace=True)
        (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (15): ReLU(inplace=True)
        (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (18): ReLU(inplace=True)
        (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (20): ReLU(inplace=True)
        (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (22): ReLU(inplace=True)
        (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (25): ReLU(inplace=True)
        (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (27): ReLU(inplace=True)
        (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (29): ReLU(inplace=True)
        (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
      )
      (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
      (classifier): Sequential(
        (0): Linear(in_features=25088, out_features=4096, bias=True)
        (1): ReLU()
        (2): Dropout(p=0.5, inplace=False)
        (3): Linear(in_features=4096, out_features=4096, bias=True)
        (4): ReLU()
        (5): Dropout(p=0.5, inplace=False)
        (6): Linear(in_features=4096, out_features=2, bias=True)
      )
    )
    Epoch0/1
    ----------
    Batch10,Train Loss:1.3042,Train Acc:60.0000%
    Batch20,Train Loss:1.0106,Train Acc:68.7500%
    Batch30,Train Loss:1.1665,Train Acc:74.1667%
    Batch40,Train Loss:1.1059,Train Acc:78.1250%
    Batch50,Train Loss:0.9046,Train Acc:81.0000%
    Batch60,Train Loss:1.4522,Train Acc:79.5833%
    Batch70,Train Loss:1.8163,Train Acc:80.7143%
    Batch80,Train Loss:1.6358,Train Acc:82.1875%
    Batch90,Train Loss:1.5268,Train Acc:82.5000%
    Batch100,Train Loss:1.4596,Train Acc:83.2500%
    trainLoss:1.4596,Correct:83.2500%
    testLoss:0.4573,Correct:92.7500%
    Training time is:4m 33s

    文件:dogs-vs-cats-迁移学习vgg16-test-small

    1. import os
    2. import torch
    3. import torchvision
    4. from torchvision import datasets,transforms,models
    5. import numpy as np
    6. import matplotlib.pyplot as plt
    7. from torch.autograd import Variable
    8. import time
    9. model=torch.load('model.pth')
    10. path='data1'
    11. transform=transforms.Compose([
    12. transforms.CenterCrop(224),
    13. transforms.ToTensor(),
    14. transforms.Normalize([0.5, 0.5, 0.5],[0.5, 0.5, 0.5])
    15. ])
    16. data_test_img=datasets.ImageFolder(
    17. root="data1/test/",
    18. transform=transform
    19. )
    20. data_loader_test_img=torch.utils.data.DataLoader(
    21. dataset=data_test_img,
    22. batch_size=16,
    23. shuffle=True
    24. )
    25. classes=data_test_img.classes
    26. image,label=next(iter(data_loader_test_img))
    27. images=Variable(image)
    28. y_pred=model(images)
    29. _,pred=torch.max(y_pred.data,1)
    30. print(pred)
    31. img=torchvision.utils.make_grid(image)
    32. img=img.numpy().transpose(1,2,0)
    33. mean=[0.5, 0.5, 0.5]
    34. std=[0.5, 0.5, 0.5]
    35. img=img*std+mean
    36. print("Pred Label:",[classes[i] for i in pred])
    37. plt.imshow(img)
    38. plt.show()

    输出: 

    tensor([1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1])
    Pred Label: ['dog', 'cat', 'cat', 'cat', 'cat', 'cat', 'cat', 'cat', 'cat', 'dog', 'dog', 'dog', 'dog', 'dog', 'dog', 'dog']
    

    200张cat和200张dog的训练效果已经很可观,有GPU条件下,可以采用更多的数据,效果会非常理想! 

    2022/7/30

  • 相关阅读:
    ​Mac还是Windows好?适合自己的可能才是最好的
    为什么你的static_assert不能按预期的工作?
    Java之面向对象(8)
    Prometheus+Grafana可视化监控【Nginx状态】
    CI/CD持续集成与持续交付(五)钉钉报警、ansible自动化构建部署
    实例说明接口测试的关键是什么?(含文档+视频)
    GPU性能优化与模型训练概览
    食品饮料行业数智化采购管理系统规范供应商管理,完善企业协同体系
    MATLB|基于复杂网络的配电系统微电网优化配置
    [附源码]java毕业设计超市收银系统论文
  • 原文地址:https://blog.csdn.net/llvyeriji/article/details/126078794