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}%)]\tLoss: {:.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('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.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("\t",name)
10 else:                                                #否則,所有的參數都會更新
11     for name,param in model_ft.named_parameters():
12         if param.requires_grad == True:
13             print("\t",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()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM