zoukankan      html  css  js  c++  java
  • Pytorch-图像分类和CNN模型的迁移学习

    导包:

    1 import torch
    2 import torch.nn as nn
    3 import torch.nn.functional as F
    4 import torch.optim as optim
    5 from torchvision import datasets, transforms

    关于torchvision:

    torchvision主要包括一下几个包:

    • vision.datasets : 几个常用视觉数据集,可以下载和加载;
    • vision.models : 流行的模型,例如 AlexNet, VGG, and ResNet 以及 与训练好的参数;
    • vision.transforms : 常用的图像操作,例如:随机切割,旋转等;
    • vision.utils : 用于把形似 (3 x H x W) 的张量保存到硬盘中,给一个mini-batch的图像可以产生一个图像格网;

    设置参数:

    1 #设置超参数 
    2 torch.manual_seed(53113)  #cpu随机种子
    3 batch_size = test_batch_size = 32  
    4 
    5 #设置GPU参数 
    6 use_cuda = torch.cuda.is_available()  
    7 device = torch.device("cuda" if use_cuda else "cpu")  
    8 kwargs = {'num_workers': 0, 'pin_memory': True} if use_cuda else {}

    1.数据预处理

    torch.utils.data.DataLoader在训练模型时使用到此函数,用来把训练数据分成多个batch,此函数每次抛出一个batch数据,直至把所有的数据都抛出,也就是个数据迭代器。

    DataLoader中的transform参数:接受一个图像返回变换后的图像的函数,相当于图像先预处理下,常用的操作如 ToTensor, RandomCrop,Normalize等,他们可以通过transforms.Compose被组合在一起。

    • .ToTensor()将shape为(H, W, C)的nump.ndarray或img转为shape为(C, H, W)的tensor,其将每一个数值归一化到[0,1],其归一化方法比较简单,直接除以255即可。

    • .Normalize作用就是.ToTensor将输入归一化到(0,1)后,再使用公式”(x-mean)/std”,将每个元素分布到(-1,1) 
     1 train_loader = torch.utils.data.DataLoader(
     2     datasets.MNIST('./mnist_data',    #数据集
     3                    train=True,        #如果true,从training.pt创建数据集
     4                    download=True,     #如果ture,从网上自动下载
     5                    
     6                    transform=transforms.Compose([        
     7                               transforms.ToTensor(),                      
     8                               transforms.Normalize((0.1307,), (0.3081,)) # 所有图片像素均值和方差
     9                    ])), 
    10     batch_size = batch_size, 
    11     shuffle=True,  
    12     **kwargs)            #kwargs是上面gpu的设置
     1 test_loader = torch.utils.data.DataLoader(
     2     datasets.MNIST('./mnist_data', 
     3                    train=False,               #如果False,从test.pt创建数据集
     4                    transform=transforms.Compose([
     5                        transforms.ToTensor(),
     6                        transforms.Normalize((0.1307,), (0.3081,))
     7                    ])),
     8     batch_size=test_batch_size, 
     9     shuffle=True, 
    10     **kwargs)

    查看一下:

    1 print(train_loader.dataset[0][0].shape)            #torch.Size([1, 28, 28])

    2.创建模型

     1 class Net(nn.Module):
     2     def __init__(self):
     3         super(Net, self).__init__()
     4         self.conv1 = nn.Conv2d(1, 20, 5, 1)       #(in_channels, out_channels, kernel_size, stride=1)
     5         self.conv2 = nn.Conv2d(20, 50, 5, 1)      #上个卷积网络的out_channels,就是下一个网络的in_channels,所以这里是20
     6 
     7         self.fc1 = nn.Linear(4*4*50, 500)
     8         self.fc2 = nn.Linear(500, 10)             #10分类
     9 
    10     def forward(self, x):              #手写数字的输入维度,(N,1,28,28), N为batch_size
    11         x = F.relu(self.conv1(x))      # x = (N,20,24,24)
    12         x = F.max_pool2d(x, 2, 2)      # x = (N,20,12,12)
    13         x = F.relu(self.conv2(x))      # x = (N,50,8,8)
    14         x = F.max_pool2d(x, 2, 2)      # x = (N,50,4,4)
    15         x = x.view(-1, 4*4*50)         # x = (N,4*4*50)
    16         x = F.relu(self.fc1(x))        # x = (N,4*4*50)*(4*4*50, 500)=(N,500)
    17         x = self.fc2(x)                # x = (N,500)*(500, 10)=(N,10)
    18         return F.log_softmax(x, dim=1) #带log的softmax分类,每张图片返回10个概率

    模型初始化:

    1 lr = 0.01
    2 momentum = 0.5
    3 model = Net().to(device) #模型初始化
    4 optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum) #定义优化器

    3.训练函数

     1 def train(model, device, train_loader, optimizer, epoch, log_interval=100):
     2     model.train() 
     3     for batch_idx, (data, target) in enumerate(train_loader):
     4         data, target = data.to(device), target.to(device)
     5         optimizer.zero_grad() 
     6         output = model(data)              #输出的维度[N,10] 这里的data是函数的forward参数x
     7         loss = F.nll_loss(output, target) #这里loss求的是平均数,除以了batch
     8         loss.backward()
     9         optimizer.step()
    10         if batch_idx % log_interval == 0:
    11             print("Train Epoch: {} [{}/{} ({:0f}%)]	Loss: {:.6f}".format(
    12                 epoch, 
    13                 batch_idx * len(data),                #100*32
    14                 len(train_loader.dataset),            #60000
    15                 100. * batch_idx / len(train_loader), #len(train_loader)=60000/32=1875
    16                 loss.item()
    17             ))

    4.测试函数

     1 def test(model, device, test_loader):
     2     model.eval()
     3     test_loss = 0
     4     correct = 0
     5     with torch.no_grad():
     6         for data, target in test_loader:
     7             data, target = data.to(device), target.to(device)
     8             output = model(data)
     9             test_loss += F.nll_loss(output, target, reduction='sum').item()  #reduction='sum'代表batch的每个元素loss累加求和,默认是mean求平均
    10 
    11             pred = output.argmax(dim=1, keepdim=True)                        #pred.shape=torch.Size([32, 1])
    12 
    13             correct += pred.eq(target.view_as(pred)).sum().item()            #target.shape=torch.Size([32])
    14 
    15     test_loss /= len(test_loader.dataset)
    16 
    17     print('
    Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)
    '.format(
    18         test_loss, correct, len(test_loader.dataset),
    19         100. * correct / len(test_loader.dataset)))

    执行:

    1 epochs = 2
    2 for epoch in range(1, epochs + 1):
    3     train(model, device, train_loader, optimizer, epoch)
    4     test(model, device, test_loader)
    5 
    6 save_model = True
    7 if (save_model):
    8     torch.save(model.state_dict(),"mnist_cnn.pt")    #词典格式,model.state_dict()只保存模型参数

    训练结果:

     1 Train Epoch: 1 [0/60000 (0.000000%)]    Loss: 2.297938
     2 Train Epoch: 1 [3200/60000 (5.333333%)] Loss: 0.570356
     3 Train Epoch: 1 [6400/60000 (10.666667%)]        Loss: 0.207343
     4 Train Epoch: 1 [9600/60000 (16.000000%)]        Loss: 0.094465
     5 Train Epoch: 1 [12800/60000 (21.333333%)]       Loss: 0.178536
     6 Train Epoch: 1 [16000/60000 (26.666667%)]       Loss: 0.041227
     7 Train Epoch: 1 [19200/60000 (32.000000%)]       Loss: 0.136767
     8 Train Epoch: 1 [22400/60000 (37.333333%)]       Loss: 0.051781
     9 Train Epoch: 1 [25600/60000 (42.666667%)]       Loss: 0.112557
    10 Train Epoch: 1 [28800/60000 (48.000000%)]       Loss: 0.058771
    11 Train Epoch: 1 [32000/60000 (53.333333%)]       Loss: 0.085873
    12 Train Epoch: 1 [35200/60000 (58.666667%)]       Loss: 0.188629
    13 Train Epoch: 1 [38400/60000 (64.000000%)]       Loss: 0.092433
    14 Train Epoch: 1 [41600/60000 (69.333333%)]       Loss: 0.075023
    15 Train Epoch: 1 [44800/60000 (74.666667%)]       Loss: 0.038028
    16 Train Epoch: 1 [48000/60000 (80.000000%)]       Loss: 0.038069
    17 Train Epoch: 1 [51200/60000 (85.333333%)]       Loss: 0.052910
    18 Train Epoch: 1 [54400/60000 (90.666667%)]       Loss: 0.012891
    19 Train Epoch: 1 [57600/60000 (96.000000%)]       Loss: 0.033460
    20 
    21 Test set: Average loss: 0.0653, Accuracy: 9799/10000 (98%)
    22 
    23 Train Epoch: 2 [0/60000 (0.000000%)]    Loss: 0.057514
    24 Train Epoch: 2 [3200/60000 (5.333333%)] Loss: 0.030869
    25 Train Epoch: 2 [6400/60000 (10.666667%)]        Loss: 0.091362
    26 Train Epoch: 2 [9600/60000 (16.000000%)]        Loss: 0.059315
    27 Train Epoch: 2 [12800/60000 (21.333333%)]       Loss: 0.031055
    28 Train Epoch: 2 [16000/60000 (26.666667%)]       Loss: 0.012735
    29 Train Epoch: 2 [19200/60000 (32.000000%)]       Loss: 0.104735
    30 Train Epoch: 2 [22400/60000 (37.333333%)]       Loss: 0.132139
    31 Train Epoch: 2 [25600/60000 (42.666667%)]       Loss: 0.010015
    32 Train Epoch: 2 [28800/60000 (48.000000%)]       Loss: 0.012915
    33 Train Epoch: 2 [32000/60000 (53.333333%)]       Loss: 0.038762
    34 Train Epoch: 2 [35200/60000 (58.666667%)]       Loss: 0.015236
    35 Train Epoch: 2 [38400/60000 (64.000000%)]       Loss: 0.163834
    36 Train Epoch: 2 [41600/60000 (69.333333%)]       Loss: 0.064514
    37 Train Epoch: 2 [44800/60000 (74.666667%)]       Loss: 0.007881
    38 Train Epoch: 2 [48000/60000 (80.000000%)]       Loss: 0.074057
    39 Train Epoch: 2 [51200/60000 (85.333333%)]       Loss: 0.209342
    40 Train Epoch: 2 [54400/60000 (90.666667%)]       Loss: 0.018052
    41 Train Epoch: 2 [57600/60000 (96.000000%)]       Loss: 0.012391
    42 
    43 Test set: Average loss: 0.0460, Accuracy: 9851/10000 (99%)
    View Code

    5.CNN模型的迁移学习

    很多时候当我们需要训练一个新的图像分类任务,我们不会完全从一个随机的模型开始训练,而是利用_预训练_的模型来加速训练的过程。我们经常使用在ImageNet上的预训练模型。

    以下两种方法做迁移学习:

    • fine tuning:从一个预训练模型开始,我们改变一些模型的架构,然后继续训练整个模型的参数;
    • feature extraction:不再改变预训练模型的参数,而是只更新我们改变过的部分模型参数。我们之所以叫它feature extraction是因为我们把预训练的CNN模型当做一个特征提取模型,利用提取出来的特征做来完成我们的训练任务;

    以下是构建和训练迁移学习模型的基本步骤:

    • 初始化预训练模型;
    • 把最后一层的输出层改变成我们想要分的类别总数;
    • 定义一个optimizer来更新参数;
    • 模型训练;

    导包:

    1 import numpy as np
    2 import torchvision
    3 from torchvision import datasets, transforms, models
    4 
    5 import matplotlib.pyplot as plt
    6 import time
    7 import os
    8 import copy
    9
    10input_size = 224

    我们会使用hymenoptera_data数据集,下载,然后放在当前代码目录下。这个数据集包括两类图片,bees 和 ants这些数据都被处理成了可以使用ImageFolder <https://pytorch.org/docs/stable/torchvision/datasets.html#torchvision.datasets.ImageFolder>来读取的格式。我们只需要把data_dir设置成数据的根目录,然后把model_name设置成我们想要使用的预训练模型: [resnet, alexnet, vgg, squeezenet, densenet, inception]

    5.1查看数据

     1 data_dir = "./hymenoptera_data"
     2 batch_size = 32
     3 
     4 #os.path.join() 连接路径,相当于.../data_dir/train
     5 all_imgs = datasets.ImageFolder(os.path.join(data_dir, "train"),
     6                                 transforms.Compose([
     7                               transforms.RandomResizedCrop(input_size), #把每张图片变成resnet需要输入的维度224
     8                           transforms.RandomHorizontalFlip(),
     9                           transforms.ToTensor(),
    10                       ]))
    11 loader = torch.utils.data.DataLoader(all_imgs, batch_size=batch_size, shuffle=True, num_workers=0)        #训练数据分batch,变成tensor迭代器
    12 
    13 img = next(iter(loader))[0]         #这个img是一个batch的tensor
    14 print(img.shape)                    #torch.Size([32, 3, 224, 224])
     1 unloader = transforms.ToPILImage()  #.ToPILImage() 把tensor或数组转换成图像
     2 
     3 plt.ion()                           #交互模式,默认是交互模式,可以不写
     4 
     5 def imshow(tensor, title=None):
     6     image = tensor.cpu().clone()    # we clone the tensor to not do changes on it
     7     image = image.squeeze(0)      
     8     
     9     image = unloader(image)         #tensor转换成图像
    10     plt.imshow(image)
    11     if title is not None:
    12         plt.title(title)
    13     plt.pause(1)                    #可以去掉看看,只是延迟显示作用
    14 
    15 plt.figure()
    16 imshow(img[8], title='Image') 
    17 imshow(img[9], title='Image')

    关于torchvision.transforms.ToPILImage()见:https://blog.csdn.net/qq_37385726/article/details/81811466

    关于plt.ion()和plt.ioff()见:https://blog.csdn.net/SZuoDao/article/details/52973621

    Tip:查看对应文件夹的图片label;

    1 print(all_imgs.class_to_idx)        # {'ants': 0, 'bees': 1}

    查看所有图片的路径和对应的label;

    1 print(all_imgs.imgs)

    输出列表的其中一个元素为('./hymenoptera_data\train\ants\0013035.jpg', 0)

    5.2数据预处理(把训练集和验证集分batch转换成迭代器)

     1 data_transforms = {
     2     "train": transforms.Compose([
     3         transforms.RandomResizedCrop(input_size),
     4         transforms.RandomHorizontalFlip(),
     5         transforms.ToTensor(),
     6         transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
     7     ]),
     8     "val": transforms.Compose([
     9         transforms.Resize(input_size),
    10         transforms.CenterCrop(input_size),
    11         transforms.ToTensor(),
    12         transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    13     ]),
    14 }
    15 print("Initializing Datasets and Dataloaders...")
    16 
    17 # Create training and validation datasets
    18 image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in ['train', 'val']}
    19 # Create training and validation dataloaders
    20 dataloaders_dict = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=batch_size, shuffle=True, num_workers=0) for x in ['train', 'val']}    #把迭代器存放到字典里作为value,key是train和val,后面调用key即可
    21 
    22 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    测试一下:

     1 inputs, labels=next(iter(dataloaders_dict["train"])) #一个batch
     2 print(inputs.shape)               #torch.Size([32, 3, 224, 224])
     3 print(labels)
     4 # tensor([0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1,
     5 #         1, 0, 0, 0, 1, 1, 1, 0])
     6 
     7 for inputs, labels in dataloaders_dict["train"]:
     8     print(labels.size()) #最后一个batch不足32
     9 # torch.Size([32])
    10 # torch.Size([32])
    11 # torch.Size([32])
    12 # torch.Size([32]) 
    13 # torch.Size([32])
    14 # torch.Size([32])
    15 # torch.Size([32])
    16 # torch.Size([20])

    5.3加载resnet模型并修改全连接层

     1 model_name = "resnet"
     2 num_classes = 2
     3 num_epochs = 10
     4 feature_extract = True       #只更新修改的层
     5 
     6 def set_parameter_requires_grad(model, feature_extracting):
     7     if feature_extracting:
     8         for param in model.parameters():
     9             param.requires_grad = False        #提取的参数梯度不更新
    10 
    11 def initialize_model(model_name, num_classes, feature_extract, use_pretrained=True):
    12     if model_name == "resnet":
    13         model_ft = models.resnet18(pretrained=use_pretrained)       #如果True,从imagenet上返回预训练的模型和参数       
    14         set_parameter_requires_grad(model_ft, feature_extract)      #提取的参数梯度不更新
    15 
    16         num_ftrs = model_ft.fc.in_features               #model_ft.fc是resnet的最后全连接层,(fc): Linear(in_features=512, out_features=1000, bias=True),num_ftrs值为512             
    17         model_ft.fc = nn.Linear(num_ftrs, num_classes)   #out_features=1000 改为 num_classes=2 
    18         
    19         input_size = 224                                 #resnet18网络输入图片维度是224,resnet34,50,101,152也是
    20         
    21     return model_ft, input_size
    22 
    23 model_ft, input_size = initialize_model(model_name, num_classes, feature_extract, use_pretrained=True)
    24 # print(model_ft)

    看下有哪些参数:

    1 for name,param in model_ft.named_parameters():
    2     print(name) 
     1 conv1.weight
     2 bn1.weight
     3 bn1.bias
     4 layer1.0.conv1.weight
     5 layer1.0.bn1.weight
     6 layer1.0.bn1.bias
     7 layer1.0.conv2.weight
     8 layer1.0.bn2.weight
     9 layer1.0.bn2.bias
    10 layer1.1.conv1.weight
    11 layer1.1.bn1.weight
    12 layer1.1.bn1.bias
    13 layer1.1.conv2.weight
    14 layer1.1.bn2.weight
    15 layer1.1.bn2.bias
    16 layer2.0.conv1.weight
    17 layer2.0.bn1.weight
    18 layer2.0.bn1.bias
    19 layer2.0.conv2.weight
    20 layer2.0.bn2.weight
    21 layer2.0.bn2.bias
    22 layer2.0.downsample.0.weight
    23 layer2.0.downsample.1.weight
    24 layer2.0.downsample.1.bias
    25 layer2.1.conv1.weight
    26 layer2.1.bn1.weight
    27 layer2.1.bn1.bias
    28 layer2.1.conv2.weight
    29 layer2.1.bn2.weight
    30 layer2.1.bn2.bias
    31 layer3.0.conv1.weight
    32 layer3.0.bn1.weight
    33 layer3.0.bn1.bias
    34 layer3.0.conv2.weight
    35 layer3.0.bn2.weight
    36 layer3.0.bn2.bias
    37 layer3.0.downsample.0.weight
    38 layer3.0.downsample.1.weight
    39 layer3.0.downsample.1.bias
    40 layer3.1.conv1.weight
    41 layer3.1.bn1.weight
    42 layer3.1.bn1.bias
    43 layer3.1.conv2.weight
    44 layer3.1.bn2.weight
    45 layer3.1.bn2.bias
    46 layer4.0.conv1.weight
    47 layer4.0.bn1.weight
    48 layer4.0.bn1.bias
    49 layer4.0.conv2.weight
    50 layer4.0.bn2.weight
    51 layer4.0.bn2.bias
    52 layer4.0.downsample.0.weight
    53 layer4.0.downsample.1.weight
    54 layer4.0.downsample.1.bias
    55 layer4.1.conv1.weight
    56 layer4.1.bn1.weight
    57 layer4.1.bn1.bias
    58 layer4.1.conv2.weight
    59 layer4.1.bn2.weight
    60 layer4.1.bn2.bias
    61 fc.weight
    62 fc.bias
    View Code

    5.4查看需要更新的参数、定义优化器

     1 model_ft = model_ft.to(device)
     2  
     3 print("Params to learn:")
     4 if feature_extract:
     5     params_to_update = []                            #需要更新的参数存放在此
     6     for name,param in model_ft.named_parameters(): 
     7         if param.requires_grad == True:              #这里全连接层之前的层param.requires_grad == Flase,后面加的全连接层param.requires_grad == True 
     8             params_to_update.append(param)
     9             print("	",name)
    10 else:                                                #否则,所有的参数都会更新
    11     for name,param in model_ft.named_parameters():
    12         if param.requires_grad == True:
    13             print("	",name)
    14 
    15 optimizer_ft = optim.SGD(params_to_update, lr=0.001, momentum=0.9) #定义优化器
    16 criterion = nn.CrossEntropyLoss()                                  #定义损失函数

    执行结果:

    1 Params to learn:
    2          fc.weight
    3          fc.bias

    5.5定义训练模型

    训练和测试合在一起了

     1 def train_model(model, dataloaders, criterion, optimizer, num_epochs=5):
     2     since = time.time()
     3     val_acc_history = [] 
     4     best_model_wts = copy.deepcopy(model.state_dict())     #深拷贝上面resnet模型参数
     5     best_acc = 0.
     6     
     7     for epoch in range(num_epochs):
     8         print("Epoch {}/{}".format(epoch, num_epochs-1))
     9         print("-"*10)
    10         
    11         for phase in ["train", "val"]:
    12             running_loss = 0.
    13             running_corrects = 0.
    14             if phase == "train":
    15                 model.train()
    16             else: 
    17                 model.eval()
    18             
    19             for inputs, labels in dataloaders[phase]:        
    20                 inputs = inputs.to(device)               #inputs.shape = torch.Size([32, 3, 224, 224])
    21                 labels = labels.to(device)               #labels.shape = torch.Size([32])
    22                 
    23                 with torch.autograd.set_grad_enabled(phase=="train"):    #torch.autograd.set_grad_enabled梯度管理器,可设置为打开或关闭,phase=="train"值为True或False
    24                     outputs = model(inputs)              #outputs.shape = torch.Size([32, 10])
    25                     loss = criterion(outputs, labels)    
    26                     
    27                 _, preds = torch.max(outputs, 1)        #返回每一行最大的数和索引,prds的位置是索引的位置,或者preds = outputs.argmax(dim=1)
    28                 
    29                 if phase == "train":
    30                     optimizer.zero_grad()
    31                     loss.backward()
    32                     optimizer.step()
    33                     
    34                 running_loss += loss.item() * inputs.size(0)                                 #交叉熵损失函数是平均过的
    35                 running_corrects += torch.sum(preds.view(-1) == labels.view(-1)).item()      #.view(-1)展开到一维,并自己计算
    36                 
    37             
    38             epoch_loss = running_loss / len(dataloaders[phase].dataset)
    39             epoch_acc = running_corrects / len(dataloaders[phase].dataset)
    40        
    41             print("{} Loss: {} Acc: {}".format(phase, epoch_loss, epoch_acc))
    42             if phase == "val" and epoch_acc > best_acc:
    43                 best_acc = epoch_acc
    44                 best_model_wts = copy.deepcopy(model.state_dict())                #模型变好,就拷贝更新后的模型参数
    45                 
    46             if phase == "val":
    47                 val_acc_history.append(epoch_acc)                                 #记录每个epoch验证集的准确率 
    48             
    49         print()
    50     
    51     time_elapsed = time.time() - since
    52     print("Training compete in {}m {}s".format(time_elapsed // 60, time_elapsed % 60))
    53     print("Best val Acc: {}".format(best_acc))
    54     
    55     model.load_state_dict(best_model_wts)                                         #把最新的参数复制到model中
    56     return model, val_acc_history

    调用一下:

    1 # Train and evaluate
    2 model_ft, ohist = train_model(model_ft, dataloaders_dict, criterion, optimizer_ft, num_epochs=num_epochs)

    执行结果:

     1 Epoch 0/9
     2 ----------
     3 train Loss: 0.6792222046461261 Acc: 0.5491803278688525
     4 val Loss: 0.6042880532788295 Acc: 0.6797385620915033
     5 
     6 Epoch 1/9
     7 ----------
     8 train Loss: 0.5260111435514981 Acc: 0.7254098360655737
     9 val Loss: 0.4606282469493891 Acc: 0.8366013071895425
    10 
    11 Epoch 2/9
    12 ----------
    13 train Loss: 0.3967628830769023 Acc: 0.8811475409836066
    14 val Loss: 0.33848777238060446 Acc: 0.9084967320261438
    15 
    16 Epoch 3/9
    17 ----------
    18 train Loss: 0.3282915304918758 Acc: 0.8852459016393442
    19 val Loss: 0.2889009240795584 Acc: 0.9150326797385621
    20 
    21 Epoch 4/9
    22 ----------
    23 train Loss: 0.2884497346936679 Acc: 0.9139344262295082
    24 val Loss: 0.2592071742793314 Acc: 0.9215686274509803
    25 
    26 Epoch 5/9
    27 ----------
    28 train Loss: 0.26097508507673856 Acc: 0.8975409836065574
    29 val Loss: 0.24648226690448188 Acc: 0.9150326797385621
    30 
    31 Epoch 6/9
    32 ----------
    33 train Loss: 0.2270883551386536 Acc: 0.9385245901639344
    34 val Loss: 0.23724308084039128 Acc: 0.9150326797385621
    35 
    36 Epoch 7/9
    37 ----------
    38 train Loss: 0.20939802268489463 Acc: 0.9467213114754098
    39 val Loss: 0.23119436038864982 Acc: 0.9150326797385621
    40 
    41 Epoch 8/9
    42 ----------
    43 train Loss: 0.21726583628380886 Acc: 0.9180327868852459
    44 val Loss: 0.221941787919967 Acc: 0.9150326797385621
    45 
    46 Epoch 9/9
    47 ----------
    48 train Loss: 0.19981201164057996 Acc: 0.9385245901639344
    49 val Loss: 0.2194489004954793 Acc: 0.9150326797385621
    50 
    51 Training compete in 0.0m 37.531731367111206s
    52 Best val Acc: 0.9215686274509803
    View Code

    不使用预训练模型,所有参数都参加训练

    1 scratch_model,_ = initialize_model(model_name, 
    2                                    num_classes, 
    3                                    feature_extract=False, #所有参数都训练
    4                                    use_pretrained=False)# 不要imagenet的参数
    5 scratch_model = scratch_model.to(device)
    6 scratch_optimizer = optim.SGD(scratch_model.parameters(), lr=0.001, momentum=0.9)
    7 scratch_criterion = nn.CrossEntropyLoss()
    8 _,scratch_hist = train_model(scratch_model, dataloaders_dict, scratch_criterion, scratch_optimizer, num_epochs=num_epochs)

    执行结果:

     1 Epoch 0/9
     2 ----------
     3 train Loss: 0.8219864260954935 Acc: 0.5450819672131147
     4 val Loss: 0.695075081454383 Acc: 0.5424836601307189
     5 
     6 Epoch 1/9
     7 ----------
     8 train Loss: 0.7687111731435432 Acc: 0.5040983606557377
     9 val Loss: 0.7560343270987467 Acc: 0.46405228758169936
    10 
    11 Epoch 2/9
    12 ----------
    13 train Loss: 0.6719165463916591 Acc: 0.5819672131147541
    14 val Loss: 0.6266151779617359 Acc: 0.6013071895424836
    15 
    16 Epoch 3/9
    17 ----------
    18 train Loss: 0.6333085493963273 Acc: 0.6147540983606558
    19 val Loss: 0.6167325887804717 Acc: 0.6601307189542484
    20 
    21 Epoch 4/9
    22 ----------
    23 train Loss: 0.5848636265660896 Acc: 0.6434426229508197
    24 val Loss: 0.5851604537247053 Acc: 0.673202614379085
    25 
    26 Epoch 5/9
    27 ----------
    28 train Loss: 0.5586931158284671 Acc: 0.6844262295081968
    29 val Loss: 0.5588414598913753 Acc: 0.7450980392156863
    30 
    31 Epoch 6/9
    32 ----------
    33 train Loss: 0.5667437266130917 Acc: 0.680327868852459
    34 val Loss: 0.5625949673403322 Acc: 0.6928104575163399
    35 
    36 Epoch 7/9
    37 ----------
    38 train Loss: 0.5877759007156872 Acc: 0.639344262295082
    39 val Loss: 0.6133050057623122 Acc: 0.7254901960784313
    40 
    41 Epoch 8/9
    42 ----------
    43 train Loss: 0.581167609965215 Acc: 0.680327868852459
    44 val Loss: 0.5674625876682257 Acc: 0.7254901960784313
    45 
    46 Epoch 9/9
    47 ----------
    48 train Loss: 0.5575579023752056 Acc: 0.6680327868852459
    49 val Loss: 0.5709076671818503 Acc: 0.6993464052287581
    50 
    51 Training compete in 0.0m 50.611786127090454s
    52 Best val Acc: 0.7450980392156863
    View Code

    演示不同训练模型的性能

    1 plt.title("Validation Accuracy vs. Number of Training Epochs")
    2 plt.xlabel("Training Epochs")
    3 plt.ylabel("Validation Accuracy")
    4 plt.plot(range(1,num_epochs+1),ohist,label="Pretrained")
    5 plt.plot(range(1,num_epochs+1),scratch_hist,label="Scratch")
    6 plt.ylim((0,1.))
    7 plt.xticks(np.arange(1, num_epochs+1, 1.0))
    8 plt.legend()
    9 plt.show()

  • 相关阅读:
    WPF-学习笔记 将控件添加到Grid中的指定行指定列
    WPF 学习笔记-在WPF下创建托盘图标
    WPF-学习笔记 动态修改控件Margin的值
    WPF-学习笔记 按下鼠标拖动窗口
    WPF 学习笔记-判断动画完成的画件
    WPF 学习笔记-跨线程引用控件
    WPF 学习笔记-设置属性使窗口不可改变大小
    C语言博客作业02循环结构
    C语言博客作业03函数
    C语言博客作业01分支、顺序结构
  • 原文地址:https://www.cnblogs.com/cxq1126/p/13697361.html
Copyright © 2011-2022 走看看