• 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

  • 相关阅读:
    milvus数据库搜索
    CuratorFrameworkFactory.builder()方法可配置属性
    2023年天津美术学院专升本专业课报名缴费时间及考试安排
    Linux之shell条件测试
    深度学习常用概念
    Java注释
    [Linux] 数据链路层-----以太网帧协议、ARP协议
    03梯度下降
    MySQL 开发规范
    架构与思维:一定需要微服务么?
  • 原文地址:https://blog.csdn.net/llvyeriji/article/details/126078794