<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          輕松學(xué)Pytorch-使用卷積神經(jīng)網(wǎng)絡(luò)實現(xiàn)圖像分類

          共 29094字,需瀏覽 59分鐘

           ·

          2021-05-05 10:23


          點擊上方小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂

          重磅干貨,第一時間送達(dá)

          本文轉(zhuǎn)自|人工智能與算法學(xué)習(xí)

          大家好,本篇教程的貢獻(xiàn)者來自社區(qū)投稿作者【隕星落云】,使用CIFAR-10數(shù)據(jù)集進(jìn)行圖像分類。該數(shù)據(jù)集中的圖像是彩色小圖像,其中被分為了十類。一些示例圖像,如下圖所示:

          測試GPU是否可以使用

          數(shù)據(jù)集中的圖像大小為32x32x3 。在訓(xùn)練的過程中最好使用GPU來加速。

           1import torch
          2import numpy as np
          3
          4# 檢查是否可以利用GPU
          5train_on_gpu = torch.cuda.is_available()
          6
          7if not train_on_gpu:
          8    print('CUDA is not available.')
          9else:
          10    print('CUDA is available!')

          結(jié)果:
          CUDA is available!


          加載數(shù)據(jù)

          數(shù)據(jù)下載可能會比較慢。請耐心等待。加載訓(xùn)練和測試數(shù)據(jù),將訓(xùn)練數(shù)據(jù)分為訓(xùn)練集和驗證集,然后為每個數(shù)據(jù)集創(chuàng)建DataLoader。

           1from torchvision import datasets
          2import torchvision.transforms as transforms
          3from torch.utils.data.sampler import SubsetRandomSampler
          4
          5# number of subprocesses to use for data loading
          6num_workers = 0
          7# 每批加載16張圖片
          8batch_size = 16
          9# percentage of training set to use as validation
          10valid_size = 0.2
          11
          12# 將數(shù)據(jù)轉(zhuǎn)換為torch.FloatTensor,并標(biāo)準(zhǔn)化。
          13transform = transforms.Compose([
          14    transforms.ToTensor(),
          15    transforms.Normalize((0.50.50.5), (0.50.50.5))
          16    ])
          17
          18# 選擇訓(xùn)練集與測試集的數(shù)據(jù)
          19train_data = datasets.CIFAR10('data', train=True,
          20                              download=True, transform=transform)
          21test_data = datasets.CIFAR10('data', train=False,
          22                             download=True, transform=transform)
          23
          24# obtain training indices that will be used for validation
          25num_train = len(train_data)
          26indices = list(range(num_train))
          27np.random.shuffle(indices)
          28split = int(np.floor(valid_size * num_train))
          29train_idx, valid_idx = indices[split:], indices[:split]
          30
          31# define samplers for obtaining training and validation batches
          32train_sampler = SubsetRandomSampler(train_idx)
          33valid_sampler = SubsetRandomSampler(valid_idx)
          34
          35# prepare data loaders (combine dataset and sampler)
          36train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size,
          37    sampler=train_sampler, num_workers=num_workers)
          38valid_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, 
          39    sampler=valid_sampler, num_workers=num_workers)
          40test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, 
          41    num_workers=num_workers)
          42
          43# 圖像分類中10類別
          44classes = ['airplane''automobile''bird''cat''deer',
          45           'dog''frog''horse''ship''truck']



          查看訓(xùn)練集中的一批樣本


           1import matplotlib.pyplot as plt
          2%matplotlib inline
          3
          4# helper function to un-normalize and display an image
          5def imshow(img):
          6    img = img / 2 + 0.5  # unnormalize
          7    plt.imshow(np.transpose(img, (120)))  # convert from Tensor image
          8
          9# 獲取一批樣本
          10dataiter = iter(train_loader)
          11images, labels = dataiter.next()
          12images = images.numpy() # convert images to numpy for display
          13
          14# 顯示圖像,標(biāo)題為類名
          15fig = plt.figure(figsize=(254))
          16# 顯示16張圖片
          17for idx in np.arange(16):
          18    ax = fig.add_subplot(216/2, idx+1, xticks=[], yticks=[])
          19    imshow(images[idx])
          20    ax.set_title(classes[labels[idx]])

          結(jié)果:



          查看一張圖像中的更多細(xì)節(jié)


          在這里,進(jìn)行了歸一化處理。紅色、綠色和藍(lán)色(RGB)顏色通道可以被看作三個單獨的灰度圖像。

           1rgb_img = np.squeeze(images[3])
          2channels = ['red channel''green channel''blue channel']
          3
          4fig = plt.figure(figsize = (3636)) 
          5for idx in np.arange(rgb_img.shape[0]):
          6    ax = fig.add_subplot(13, idx + 1)
          7    img = rgb_img[idx]
          8    ax.imshow(img, cmap='gray')
          9    ax.set_title(channels[idx])
          10    width, height = img.shape
          11    thresh = img.max()/2.5
          12    for x in range(width):
          13        for y in range(height):
          14            val = round(img[x][y],2if img[x][y] !=0 else 0
          15            ax.annotate(str(val), xy=(y,x),
          16                    horizontalalignment='center',
          17                    verticalalignment='center', size=8,
          18                    color='white' if img[x][y]<thresh else 'black')

          結(jié)果:

          定義卷積神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)

          這里,將定義一個CNN的結(jié)構(gòu)。將包括以下內(nèi)容:

          • 卷積層:可以認(rèn)為是利用圖像的多個濾波器(經(jīng)常被稱為卷積操作)進(jìn)行濾波,得到圖像的特征。

          • 通常,我們在 PyTorch 中使用 nn.Conv2d 定義卷積層,并指定以下參數(shù):

            1nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0)
             

            用 3x3 窗口和步長 1 進(jìn)行卷積運算
            • in_channels 是指輸入深度。對于灰階圖像來說,深度 = 1

            • out_channels 是指輸出深度,或你希望獲得的過濾圖像數(shù)量

            • kernel_size 是卷積核的大?。ㄍǔ?3,表示 3x3 核)

            • stride 和 padding 具有默認(rèn)值,但是應(yīng)該根據(jù)你希望輸出在空間維度 x, y 里具有的大小設(shè)置它們的值。

          • 池化層:這里采用的最大池化:對指定大小的窗口里的像素值最大值。

          • 在 2x2 窗口里,取這四個值的最大值。

          • 由于最大池化更適合發(fā)現(xiàn)圖像邊緣等重要特征,適合圖像分類任務(wù)。

          • 最大池化層通常位于卷積層之后,用于縮小輸入的 x-y 維度 。

          • 通常的“線性+dropout”層可避免過擬合,并產(chǎn)生輸出10類別。

          下圖中,可以看到這是一個具有2個卷積層的神經(jīng)網(wǎng)絡(luò)。

          卷積層的輸出大小

          要計算給定卷積層的輸出大小,我們可以執(zhí)行以下計算:

          這里,假設(shè)輸入大小為(H,W),濾波器大小為(FH,FW),輸出大小為 (OH,OW),填充為P,步幅為S。此時,輸出大小可通過下面公式進(jìn)行計算。

          例: 輸入大小為(H=7,W=7),濾波器大小為(FH=3,FW=3),填充為P=0,步幅為S=1, 輸出大小為 (OH=5,OW=5)。如果用 S=2,將得輸出大小為 (OH=3,OW=3)

           1import torch.nn as nn
          2import torch.nn.functional as F
          3
          4# 定義卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)
          5class Net(nn.Module):
          6    def __init__(self):
          7        super(Net, self).__init__()
          8        # 卷積層 (32x32x3的圖像)
          9        self.conv1 = nn.Conv2d(3163, padding=1)
          10        # 卷積層(16x16x16)
          11        self.conv2 = nn.Conv2d(16323, padding=1)
          12        # 卷積層(8x8x32)
          13        self.conv3 = nn.Conv2d(32643, padding=1)
          14        # 最大池化層
          15        self.pool = nn.MaxPool2d(22)
          16        # linear layer (64 * 4 * 4 -> 500)
          17        self.fc1 = nn.Linear(64 * 4 * 4500)
          18        # linear layer (500 -> 10)
          19        self.fc2 = nn.Linear(50010)
          20        # dropout層 (p=0.3)
          21        self.dropout = nn.Dropout(0.3)
          22
          23    def forward(self, x):
          24        # add sequence of convolutional and max pooling layers
          25        x = self.pool(F.relu(self.conv1(x)))
          26        x = self.pool(F.relu(self.conv2(x)))
          27        x = self.pool(F.relu(self.conv3(x)))
          28        # flatten image input
          29        x = x.view(-164 * 4 * 4)
          30        # add dropout layer
          31        x = self.dropout(x)
          32        # add 1st hidden layer, with relu activation function
          33        x = F.relu(self.fc1(x))
          34        # add dropout layer
          35        x = self.dropout(x)
          36        # add 2nd hidden layer, with relu activation function
          37        x = self.fc2(x)
          38        return x
          39
          40# create a complete CNN
          41model = Net()
          42print(model)
          43
          44# 使用GPU
          45if train_on_gpu:
          46    model.cuda()

          結(jié)果:

          1Net(
          2  (conv1): Conv2d(316, kernel_size=(33), stride=(11), padding=(11))
          3  (conv2): Conv2d(1632, kernel_size=(33), stride=(11), padding=(11))
          4  (conv3): Conv2d(3264, kernel_size=(33), stride=(11), padding=(11))
          5  (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
          6  (fc1): Linear(in_features=1024, out_features=500, bias=True)
          7  (fc2): Linear(in_features=500, out_features=10, bias=True)
          8  (dropout): Dropout(p=0.3, inplace=False)
          9)

          選擇損失函數(shù)與優(yōu)化函數(shù)

          1import torch.optim as optim
          2# 使用交叉熵?fù)p失函數(shù)
          3criterion = nn.CrossEntropyLoss()
          4# 使用隨機(jī)梯度下降,學(xué)習(xí)率lr=0.01
          5optimizer = optim.SGD(model.parameters(), lr=0.01)

          訓(xùn)練卷積神經(jīng)網(wǎng)絡(luò)模型

          注意:訓(xùn)練集和驗證集的損失是如何隨著時間的推移而減少的;如果驗證損失不斷增加,則表明可能過擬合現(xiàn)象。(實際上,在下面的例子中,如果n_epochs設(shè)置為40,可以發(fā)現(xiàn)存在過擬合現(xiàn)象?。?/p>

           1# 訓(xùn)練模型的次數(shù)
          2n_epochs = 30
          3
          4valid_loss_min = np.Inf # track change in validation loss
          5
          6for epoch in range(1, n_epochs+1):
          7
          8    # keep track of training and validation loss
          9    train_loss = 0.0
          10    valid_loss = 0.0
          11
          12    ###################
          13    # 訓(xùn)練集的模型 #
          14    ###################
          15    model.train()
          16    for data, target in train_loader:
          17        # move tensors to GPU if CUDA is available
          18        if train_on_gpu:
          19            data, target = data.cuda(), target.cuda()
          20        # clear the gradients of all optimized variables
          21        optimizer.zero_grad()
          22        # forward pass: compute predicted outputs by passing inputs to the model
          23        output = model(data)
          24        # calculate the batch loss
          25        loss = criterion(output, target)
          26        # backward pass: compute gradient of the loss with respect to model parameters
          27        loss.backward()
          28        # perform a single optimization step (parameter update)
          29        optimizer.step()
          30        # update training loss
          31        train_loss += loss.item()*data.size(0)
          32
          33    ######################    
          34    # 驗證集的模型#
          35    ######################
          36    model.eval()
          37    for data, target in valid_loader:
          38        # move tensors to GPU if CUDA is available
          39        if train_on_gpu:
          40            data, target = data.cuda(), target.cuda()
          41        # forward pass: compute predicted outputs by passing inputs to the model
          42        output = model(data)
          43        # calculate the batch loss
          44        loss = criterion(output, target)
          45        # update average validation loss 
          46        valid_loss += loss.item()*data.size(0)
          47
          48    # 計算平均損失
          49    train_loss = train_loss/len(train_loader.sampler)
          50    valid_loss = valid_loss/len(valid_loader.sampler)
          51
          52    # 顯示訓(xùn)練集與驗證集的損失函數(shù) 
          53    print('Epoch: {} \tTraining Loss: {:.6f} \tValidation Loss: {:.6f}'.format(
          54        epoch, train_loss, valid_loss))
          55
          56    # 如果驗證集損失函數(shù)減少,就保存模型。
          57    if valid_loss <= valid_loss_min:
          58        print('Validation loss decreased ({:.6f} --> {:.6f}).  Saving model ...'.format(
          59        valid_loss_min,
          60        valid_loss))
          61        torch.save(model.state_dict(), 'model_cifar.pt')
          62        valid_loss_min = valid_loss

          結(jié)果:

           1Epoch: 1     Training Loss: 2.065666     Validation Loss: 1.706993
          2Validation loss decreased (inf --> 1.706993).  Saving model ...
          3Epoch: 2     Training Loss: 1.609919     Validation Loss: 1.451288
          4Validation loss decreased (1.706993 --> 1.451288).  Saving model ...
          5Epoch: 3     Training Loss: 1.426175     Validation Loss: 1.294594
          6Validation loss decreased (1.451288 --> 1.294594).  Saving model ...
          7Epoch: 4     Training Loss: 1.307891     Validation Loss: 1.182497
          8Validation loss decreased (1.294594 --> 1.182497).  Saving model ...
          9Epoch: 5     Training Loss: 1.200655     Validation Loss: 1.118825
          10Validation loss decreased (1.182497 --> 1.118825).  Saving model ...
          11Epoch: 6     Training Loss: 1.115498     Validation Loss: 1.041203
          12Validation loss decreased (1.118825 --> 1.041203).  Saving model ...
          13Epoch: 7     Training Loss: 1.047874     Validation Loss: 1.020686
          14Validation loss decreased (1.041203 --> 1.020686).  Saving model ...
          15Epoch: 8     Training Loss: 0.991542     Validation Loss: 0.936289
          16Validation loss decreased (1.020686 --> 0.936289).  Saving model ...
          17Epoch: 9     Training Loss: 0.942437     Validation Loss: 0.892730
          18Validation loss decreased (0.936289 --> 0.892730).  Saving model ...
          19Epoch: 10     Training Loss: 0.894279     Validation Loss: 0.875833
          20Validation loss decreased (0.892730 --> 0.875833).  Saving model ...
          21Epoch: 11     Training Loss: 0.859178     Validation Loss: 0.838847
          22Validation loss decreased (0.875833 --> 0.838847).  Saving model ...
          23Epoch: 12     Training Loss: 0.822664     Validation Loss: 0.823634
          24Validation loss decreased (0.838847 --> 0.823634).  Saving model ...
          25Epoch: 13     Training Loss: 0.787049     Validation Loss: 0.802566
          26Validation loss decreased (0.823634 --> 0.802566).  Saving model ...
          27Epoch: 14     Training Loss: 0.749585     Validation Loss: 0.785852
          28Validation loss decreased (0.802566 --> 0.785852).  Saving model ...
          29Epoch: 15     Training Loss: 0.721540     Validation Loss: 0.772729
          30Validation loss decreased (0.785852 --> 0.772729).  Saving model ...
          31Epoch: 16     Training Loss: 0.689508     Validation Loss: 0.768470
          32Validation loss decreased (0.772729 --> 0.768470).  Saving model ...
          33Epoch: 17     Training Loss: 0.662432     Validation Loss: 0.758518
          34Validation loss decreased (0.768470 --> 0.758518).  Saving model ...
          35Epoch: 18     Training Loss: 0.632324     Validation Loss: 0.750859
          36Validation loss decreased (0.758518 --> 0.750859).  Saving model ...
          37Epoch: 19     Training Loss: 0.616094     Validation Loss: 0.729692
          38Validation loss decreased (0.750859 --> 0.729692).  Saving model ...
          39Epoch: 20     Training Loss: 0.588593     Validation Loss: 0.729085
          40Validation loss decreased (0.729692 --> 0.729085).  Saving model ...
          41Epoch: 21     Training Loss: 0.571516     Validation Loss: 0.734009
          42Epoch: 22     Training Loss: 0.545541     Validation Loss: 0.721433
          43Validation loss decreased (0.729085 --> 0.721433).  Saving model ...
          44Epoch: 23     Training Loss: 0.523696     Validation Loss: 0.720512
          45Validation loss decreased (0.721433 --> 0.720512).  Saving model ...
          46Epoch: 24     Training Loss: 0.508577     Validation Loss: 0.728457
          47Epoch: 25     Training Loss: 0.483033     Validation Loss: 0.722556
          48Epoch: 26     Training Loss: 0.469563     Validation Loss: 0.742352
          49Epoch: 27     Training Loss: 0.449316     Validation Loss: 0.726019
          50Epoch: 28     Training Loss: 0.442354     Validation Loss: 0.713364
          51Validation loss decreased (0.720512 --> 0.713364).  Saving model ...
          52Epoch: 29     Training Loss: 0.421807     Validation Loss: 0.718615
          53Epoch: 30     Training Loss: 0.404595     Validation Loss: 0.729914

          加載模型

          1model.load_state_dict(torch.load('model_cifar.pt'))

          結(jié)果:

          1<All keys matched successfully>

          測試訓(xùn)練好的網(wǎng)絡(luò)

          在測試數(shù)據(jù)上測試你的訓(xùn)練模型!一個“好”的結(jié)果將是CNN得到大約70%,這些測試圖像的準(zhǔn)確性。

           1# track test loss
          2test_loss = 0.0
          3class_correct = list(0. for i in range(10))
          4class_total = list(0. for i in range(10))
          5
          6model.eval()
          7# iterate over test data
          8for data, target in test_loader:
          9    # move tensors to GPU if CUDA is available
          10    if train_on_gpu:
          11        data, target = data.cuda(), target.cuda()
          12    # forward pass: compute predicted outputs by passing inputs to the model
          13    output = model(data)
          14    # calculate the batch loss
          15    loss = criterion(output, target)
          16    # update test loss 
          17    test_loss += loss.item()*data.size(0)
          18    # convert output probabilities to predicted class
          19    _, pred = torch.max(output, 1)    
          20    # compare predictions to true label
          21    correct_tensor = pred.eq(target.data.view_as(pred))
          22    correct = np.squeeze(correct_tensor.numpy()) if not train_on_gpu else np.squeeze(correct_tensor.cpu().numpy())
          23    # calculate test accuracy for each object class
          24    for i in range(batch_size):
          25        label = target.data[i]
          26        class_correct[label] += correct[i].item()
          27        class_total[label] += 1
          28
          29# average test loss
          30test_loss = test_loss/len(test_loader.dataset)
          31print('Test Loss: {:.6f}\n'.format(test_loss))
          32
          33for i in range(10):
          34    if class_total[i] > 0:
          35        print('Test Accuracy of %5s: %2d%% (%2d/%2d)' % (
          36            classes[i], 100 * class_correct[i] / class_total[i],
          37            np.sum(class_correct[i]), np.sum(class_total[i])))
          38    else:
          39        print('Test Accuracy of %5s: N/A (no training examples)' % (classes[i]))
          40
          41print('\nTest Accuracy (Overall): %2d%% (%2d/%2d)' % (
          42    100. * np.sum(class_correct) / np.sum(class_total),
          43    np.sum(class_correct), np.sum(class_total)))

          結(jié)果:

           1Test Loss: 0.708721
          2
          3Test Accuracy of airplane: 82% (826/1000)
          4Test Accuracy of automobile: 81% (818/1000)
          5Test Accuracy of  bird: 65% (659/1000)
          6Test Accuracy of   cat: 59% (590/1000)
          7Test Accuracy of  deer: 75% (757/1000)
          8Test Accuracy of   dog: 56% (565/1000)
          9Test Accuracy of  frog: 81% (812/1000)
          10Test Accuracy of horse: 82% (823/1000)
          11Test Accuracy of  ship: 86% (866/1000)
          12Test Accuracy of truck: 84% (848/1000)
          13
          14Test Accuracy (Overall): 75% (7564/10000)

          顯示測試樣本的結(jié)果

           1# obtain one batch of test images
          2dataiter = iter(test_loader)
          3images, labels = dataiter.next()
          4images.numpy()
          5
          6# move model inputs to cuda, if GPU available
          7if train_on_gpu:
          8    images = images.cuda()
          9
          10# get sample outputs
          11output = model(images)
          12# convert output probabilities to predicted class
          13_, preds_tensor = torch.max(output, 1)
          14preds = np.squeeze(preds_tensor.numpy()) if not train_on_gpu else np.squeeze(preds_tensor.cpu().numpy())
          15
          16# plot the images in the batch, along with predicted and true labels
          17fig = plt.figure(figsize=(254))
          18for idx in np.arange(16):
          19    ax = fig.add_subplot(216/2, idx+1, xticks=[], yticks=[])
          20    imshow(images.cpu()[idx])
          21    ax.set_title("{} ({})".format(classes[preds[idx]], classes[labels[idx]]),
          22                 color=("green" if preds[idx]==labels[idx].item() else "red"))

          結(jié)果:


          下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程
          在「小白學(xué)視覺」公眾號后臺回復(fù):擴(kuò)展模塊中文教程即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺、目標(biāo)跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

          下載2:Python視覺實戰(zhàn)項目52講
          小白學(xué)視覺公眾號后臺回復(fù):Python視覺實戰(zhàn)項目,即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計數(shù)、添加眼線、車牌識別、字符識別、情緒檢測、文本內(nèi)容提取、面部識別等31個視覺實戰(zhàn)項目,助力快速學(xué)校計算機(jī)視覺。

          下載3:OpenCV實戰(zhàn)項目20講
          小白學(xué)視覺公眾號后臺回復(fù):OpenCV實戰(zhàn)項目20講,即可下載含有20個基于OpenCV實現(xiàn)20個實戰(zhàn)項目,實現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。

          交流群


          歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN算法競賽等微信群(以后會逐漸細(xì)分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進(jìn)入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~


          瀏覽 56
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产女人18毛片水真多成人如厕 | 在线成人视频网站大香蕉在线网站 | 影音先锋男人站你懂的 | 五月婷婷人妻小说 | 黄色成人电影在线观看 |