日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

【深度学习】使用 Pytorch 进行多类图像分类

發布時間:2025/3/12 pytorch 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【深度学习】使用 Pytorch 进行多类图像分类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

關于數據集

此數據包含大小為150x150、分布在6個類別下的約25k圖像。


{'建筑物':0,'森林':1,'冰川':2,'山':3,'海':4,'街道':5}

訓練、測試和預測數據在每個 zip 文件中分開。訓練中有大約 14k 圖像,測試中有 3k,預測中有 7k。

挑戰

這是一個多類圖像分類問題,目標是將這些圖像以更高的精度分類到正確的類別中。

先決條件

基本理解python、pytorch和分類問題。

方法

  • 做一些探索性數據分析 (EDA) 來分析和可視化數據,以便更好地理解。

  • 定義一些實用函數來執行各種任務,從而可以保持代碼的模塊化。

  • 加載各種預先訓練的模型并根據我們的問題對它們進行微調。

  • 為每個模型嘗試各種超參數。

  • 保存模型的權重并記錄指標。

  • 結論

  • 未來的工作

  • 讓我們深入研究代碼!

    1. 庫

    首先,導入所有重要的庫。

    import os import torch import tarfile import torchvision import torch.nn as nn from PIL import Image import matplotlib.pyplot as plt import torch.nn.functional as F from torchvision import transforms from torchvision.utils import make_grid from torch.utils.data import random_split from torchvision.transforms import ToTensor from torchvision.datasets import ImageFolder from torch.utils.data import Dataset, DataLoader from torchvision.datasets.utils import download_url

    2. 圖片文件夾到數據集

    由于我們的數據存在于文件夾中,因此讓我們將它們轉換為數據集。

    transform_train = transforms.Compose([transforms.Resize((150,150)), #becasue vgg takes 150*150transforms.RandomHorizontalFlip(),transforms.RandomVerticalFlip(),transforms.ToTensor(),transforms.Normalize((.5, .5, .5), (.5, .5, .5))])#Augmentation is not done for test/validation data. transform_test = transforms.Compose([transforms.Resize((150,150)), #becasue vgg takes 150*150transforms.ToTensor(),transforms.Normalize((.5, .5, .5), (.5, .5, .5))])train_ds = ImageFolder('../input/intel-image-classification/seg_train/seg_train', transform=transform_train) test_ds = ImageFolder('../input/intel-image-classification/seg_test/seg_test', transform=transform_test) pred_ds = ImageFolder('/kaggle/input/intel-image-classification/seg_pred/', transform=transform_test)

    3. 探索性數據分析 (EDA)

    作為 EDA 的一部分,讓我們在這里回答一些問題,但這里并未廣泛涵蓋 EDA。

    讓我們繼續回答一些問題。

    a) 數據集中有多少張圖片?

    回答 :

    這意味著有 14034 張圖像用于訓練,3000 張圖像用于測試/驗證,7301 張圖像用于預測。

    b) 你能告訴我圖像的大小嗎?

    回答:

    這意味著圖像的大小為 150 * 150,具有三個通道,其標簽為 0。

    c) 你能打印一批訓練圖像嗎?

    回答:此問題的答案將在創建數據加載器后給出,因此請等待并繼續下面給出的下一個標題。

    4. 創建數據加載器

    為將批量加載數據的所有數據集創建一個數據加載器。

    batch_size=128 train_dl = DataLoader(train_ds, batch_size, shuffle=True, num_workers=4, pin_memory=True) val_dl = DataLoader(test_ds, batch_size, num_workers=4, pin_memory=True) pred_dl = DataLoadebatch_size=128 train_dl = DataLoader(train_ds, batch_size, shuffle=True, num_workers=4, pin_memory=True) val_dl = DataLoader(test_ds, batch_size, num_workers=4, pin_memory=True) pred_dl = DataLoader(pred_ds, batch_size, num_workers=4, pin_memory=True)r(pred_ds, batch_size, num_workers=4, pin_memory=True)

    接下來,創建一個數據加載器,可用于打印上述問題中要求的一批圖像。

    batch_size=128 train_dl = DataLoader(train_ds, batch_size, shuffle=True, num_workers=4, pin_memory=True) val_dl = DataLoader(test_ds, batch_size, num_workers=4, pin_memory=True) pred_dl = DataLoader(pred_ds, batch_size, num_workers=4, pin_memory=True)

    5. 生成類名

    雖然可以通過查看文件夾名稱手動列出類名稱,但作為一個好習慣,我們應該為此編寫代碼。

    6. 創建精度函數

    定義一個函數來計算我們模型的準確性。

    7. 下載預訓練模型

    下載我們選擇的任何預訓練模型,可以根據需要自由選擇任何模型,這里我選擇了兩個模型 VGG 和 ResNet50 來做實驗。讓我們下載模型。

    8. 凍結所有圖層

    下載模型后,可以根據需要訓練整個架構。一種可能的策略是我們可以訓練預訓練模型的某些層,而一些層則不能。在這里,我選擇了這樣一種策略,即在新輸入的模型訓練期間不必訓練任何現有層,因此通過將模型的每個參數的 requires_grad 設置為 False 來保持所有層凍結。

    如果 requires_grad 為 True 則意味著更新可以計算導數的參數。

    9. 添加我們自己的分類器層

    現在要將下載的預訓練模型用作我們自己的分類器,我們必須對其進行一些更改,因為我們要預測的類數可能與模型已訓練的類數不同。另一個原因是有可能(幾乎在所有情況下)模型已經過訓練以檢測某些特定類型的事物,但我們想使用該模型檢測不同的事物。

    所以模型的一些變化是可以有我們自己的分類層,它會根據我們的要求進行分類。因此,我們想在預訓練模型中添加什么架構完全取決于我們自己。在這里,我選擇了人們遵循的最常見的策略,即用我們自己的分類層替換模型的最后一層。

    另一個策略是我們可以從最后一個圖層刪除一些層,例如我們刪除了最后三層并添加了我們自己的分類層,為了更好地理解,請參見下文。

    預訓練的VGG 模型:

    上圖中顯示了 VGG 模型的最后兩層(avgpool 和 classsifer)。我們可以看到這個預訓練模型是為對1000個類進行分類而設計的,但是我們只需要 6 類分類,所以稍微改變一下這個模型。

    替換最后一層后的新模型:

    我已經用我自己的分類器層替換了分類器層,因為我們可以看到有 6 個 out_features,這意味著 6 個輸出,但在預訓練模型中還有一些其他的數字,因為模型經過訓練,可以對這些數量的類進行分類。

    小伙伴們可能會問為什么分類器層內部的一些 in-features 和 out_features 發生了變化?

    所以讓我們回答這個。我們可以為這些選擇任何數字,但請記住,第一個線性層內的 in_features 必須相同,即 25088,因為它是不得更改的輸出層數。


    與 ResNet50 相同:

    預訓練模型(最后兩層)

    替換最后一層后的新模型

    請注意,第一個線性層 層中的 in_features 與 2048 相同,而最后一個 線性層層中的 out_features 為 6。除了上面提到的,其他任何 in_features 和 out_features 都可以根據我們的選擇進行更改。

    10.創建基類

    創建一個基類,其中將包含將來要使用的所有有用函數,這樣做只是為了確保 DRY的概念,因為這兩個模型都需要該類中的函數,如果不在這里實現,我們必須分別為每個模型定義這些函數,這將違反DRY概念。

    class ImageClassificationBase(nn.Module): def training_step(self, batch):images, labels = batch out = self(images) # Generate predictionsloss = F.cross_entropy(out, labels) # Calculate loss return lossdef validation_step(self, batch):images, labels = batch out = self(images) # Generate predictionsloss = F.cross_entropy(out, labels) # Calculate lossacc = accuracy(out, labels) # Calculate accuracy return {'val_loss': loss.detach(), 'val_acc': acc}def validation_epoch_end(self, outputs):batch_losses = [x['val_loss'] for x in outputs]epoch_loss = torch.stack(batch_losses).mean() # Combine lossesbatch_accs = [x['val_acc'] for x in outputs]epoch_acc = torch.stack(batch_accs).mean() # Combine accuracies return {'val_loss': epoch_loss.item(), 'val_acc': epoch_acc.item()}def epoch_end(self, epoch, result):print("Epoch [{}], train_loss: {:.4f}, val_loss: {:.4f}, val_acc: {:.4f}".format(epoch, result['train_loss'], result['val_loss'], result['val_acc']))

    11.繼承基類

    通過繼承基類為每個模型創建一個類,該類具有任何模型訓練期間所需的所有有用函數。

    12.創建繼承類的對象

    實例化該類

    13. 檢查設備

    創建一個函數來檢查當前存在哪個設備。如果存在 GPU,則選擇它,否則選擇 CPU 作為工作設備。

    在這里,我使用 GPU,因此它將設備類型顯示為 CUDA。

    14. 移動到設備

    創建一個可以將張量和模型移動到特定設備的函數。

    15. 設備數據加載器

    創建DeviceDataLoader類,該類包裝DataLoader以將數據移動到特定設備,然后可以從該設備生成一批數據。

    在這里我們可以看到張量和兩個模型都已發送到當前存在的適當設備。

    16.評估和擬合函數

    讓我們定義一個評估函數,用于評估模型在不可見數據上的性能,并定義一個擬合函數,該函數可用于模型的訓練。

    class ImageClassificationBase(nn.Module): def training_step(self, batch):images, labels = batch out = self(images) # Generate predictionsloss = F.cross_entropy(out, labels) # Calculate loss return lossdef validation_step(self, batch):images, labels = batch out = self(images) # Generate predictionsloss = F.cross_entropy(out, labels) # Calculate lossacc = accuracy(out, labels) # Calculate accuracy return {'val_loss': loss.detach(), 'val_acc': acc}def validation_epoch_end(self, outputs):batch_losses = [x['val_loss'] for x in outputs]epoch_loss = torch.stack(batch_losses).mean() # Combine lossesbatch_accs = [x['val_acc'] for x in outputs]epoch_acc = torch.stack(batch_accs).mean() # Combine accuracies return {'val_loss': epoch_loss.item(), 'val_acc': epoch_acc.item()}def epoch_end(self, epoch, result):print("Epoch [{}], train_loss: {:.4f}, val_loss: {:.4f}, val_acc: {:.4f}".format(epoch, result['train_loss'], result['val_loss'], result['val_acc']))

    17. 訓練(第一階段)

    讓我們訓練我們的模型,即 VGG 。

    num_epochs = 10 opt_func = torch.optim.Adam lr = 0.00001 history = fit(num_epochs, lr, model, train_dl, val_dl, opt_func) Epoch [0], train_loss: 0.8719, val_loss: 0.3769, val_acc: 0.8793 Epoch [1], train_loss: 0.4265, val_loss: 0.3104, val_acc: 0.8942 Epoch [2], train_loss: 0.3682, val_loss: 0.2884, val_acc: 0.9016 Epoch [3], train_loss: 0.3354, val_loss: 0.2819, val_acc: 0.8988 Epoch [4], train_loss: 0.3205, val_loss: 0.2704, val_acc: 0.9033 Epoch [5], train_loss: 0.2977, val_loss: 0.2722, val_acc: 0.9021 Epoch [6], train_loss: 0.2853, val_loss: 0.2629, val_acc: 0.9068 Epoch [7], train_loss: 0.2784, val_loss: 0.2625, val_acc: 0.9045 Epoch [8], train_loss: 0.2697, val_loss: 0.2623, val_acc: 0.9033 Epoch [9], train_loss: 0.2530, val_loss: 0.2629, val_acc: 0.9018

    18. 訓練(第二階段)

    讓我們訓練更多的歷元并評估該模型。

    19. 訓練(第 3 階段)

    讓我們訓練我們的模型 2 ,即 ResNet50 。

    num_epochs = 10 opt_func = torch.optim.Adam lr = 0.00001 history = fit(num_epochs, lr, model2, train_dl, val_dl, opt_func) Epoch [0], train_loss: 1.6437, val_loss: 1.4135, val_acc: 0.7686 Epoch [1], train_loss: 1.2088, val_loss: 0.9185, val_acc: 0.8582 Epoch [2], train_loss: 0.8531, val_loss: 0.6467, val_acc: 0.8594 Epoch [3], train_loss: 0.6709, val_loss: 0.5129, val_acc: 0.8640 Epoch [4], train_loss: 0.5773, val_loss: 0.4416, val_acc: 0.8693 Epoch [5], train_loss: 0.5215, val_loss: 0.4002, val_acc: 0.8739 Epoch [6], train_loss: 0.4796, val_loss: 0.3725, val_acc: 0.8767 Epoch [7], train_loss: 0.4582, val_loss: 0.3559, val_acc: 0.8795 Epoch [8], train_loss: 0.4391, val_loss: 0.3430, val_acc: 0.8819 Epoch [9], train_loss: 0.4262, val_loss: 0.3299, val_acc: 0.8823num_epochs = 5 opt_func = torch.optim.Adam lr = 0.0001 history = fit(num_epochs, lr, model2, train_dl, val_dl, opt_func) Epoch [0], train_loss: 0.4183, val_loss: 0.3225, val_acc: 0.8753 Epoch [1], train_loss: 0.3696, val_loss: 0.2960, val_acc: 0.8855 Epoch [2], train_loss: 0.3533, val_loss: 0.2977, val_acc: 0.8814 Epoch [3], train_loss: 0.3382, val_loss: 0.2970, val_acc: 0.8891 Epoch [4], train_loss: 0.3289, val_loss: 0.2849, val_acc: 0.8933

    20. 訓練(第 4 階段)

    讓我們訓練更多的歷元并評估該模型。

    21. 預測單個圖像

    定義一個函數,該函數可由模型用于預測單個圖像。

    def predict_single(input,label, model):input = to_device(input,device)inputs = input.unsqueeze(0) # unsqueeze the input i.e. add an additonal dimensionpredictions = model(inputs)prediction = predictions[0].detach().cpu()print(f"Prediction is {np.argmax(prediction)} of Model whereas given label is {label}")

    22.預測

    讓我們預測一下

    可以看出,目前 VGG 給出了錯誤的預測,盡管它具有良好的驗證精度?(val_acc),而 ResNet 給出了正確的預測,但我們不能說它會在每張圖像上預測正確。

    因此,讓我們針對更多的歷元訓練這兩個模型,以便將誤差最小化,即 val_loss 可以盡可能地減少,并且兩個模型都可以更準確地執行。

    現在,輪到小伙伴們預測整個 pred 文件夾/數據集了。

    提示:使用 pred_dl 作為數據加載器批量加載 pred 數據進行預測。練習它,并嘗試使用集成預測的概念來獲得更正確的預測數量。

    23.保存模型

    在很好地訓練模型后,讓我們保存它,以便我們可以將其用作下一個標題中給出的未來工作。

    24. 未來工作

    使用我們保存的模型集成兩個模型的預測,進行最終預測并將此項目轉換為flask/stream-lit網絡應用程序。

    往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯黃海廣老師《機器學習課程》視頻課

    本站qq群851320808,加入微信群請掃碼:

    總結

    以上是生活随笔為你收集整理的【深度学习】使用 Pytorch 进行多类图像分类的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。