• 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

  • 相关阅读:
    hadoop生态圈面试精华之HDFS部分
    WebGL 计算点光源下的漫反射光颜色
    Linux下gdb调试打印字符串
    REST framework serializer 数据data校验失败返回状态码
    第14章Linux实操篇-RPM与YUM
    java 类和对象(方法与方法重载)
    人工智能技术概述_2.人工智能关键技术
    Unity的unity_ObjectToWorld里的每一列分别代表什么意思?换个方向反向理解-更简单
    Mac app 公证处理流程
    汇编语言与微机原理 期末复习题整理(小题)
  • 原文地址:https://blog.csdn.net/llvyeriji/article/details/126078794