【深度學習】使用 Pytorch 進行多類圖像分類

2021-12-28 機器學習初學者

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


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


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



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



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



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

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

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

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

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

結論

未來的工作


讓我們深入研究代碼!


1. 庫

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

import osimport torchimport tarfileimport torchvisionimport torch.nn as nnfrom PIL import Imageimport matplotlib.pyplot as pltimport torch.nn.functional as Ffrom torchvision import transformsfrom torchvision.utils import make_gridfrom torch.utils.data import random_splitfrom torchvision.transforms import ToTensorfrom torchvision.datasets import ImageFolderfrom torch.utils.data import Dataset, DataLoaderfrom torchvision.datasets.utils import download_url


2. 圖片文件夾到數據集

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

transform_train = transforms.Compose([
transforms.Resize((150,150)), #becasue vgg takes 150*150 transforms.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*150 transforms.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=128train_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=128train_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=128train_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 predictions        loss = F.cross_entropy(out, labels) # Calculate lossreturn loss
def validation_step(self, batch): images, labels = batch out = self(images) # Generate predictions loss = F.cross_entropy(out, labels) # Calculate loss acc = accuracy(out, labels) # Calculate accuracyreturn {'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 losses batch_accs = [x['val_acc'] for x in outputs] epoch_acc = torch.stack(batch_accs).mean() # Combine accuraciesreturn {'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 predictions        loss = F.cross_entropy(out, labels) # Calculate lossreturn loss
def validation_step(self, batch): images, labels = batch out = self(images) # Generate predictions loss = F.cross_entropy(out, labels) # Calculate loss acc = accuracy(out, labels) # Calculate accuracyreturn {'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 losses batch_accs = [x['val_acc'] for x in outputs] epoch_acc = torch.stack(batch_accs).mean() # Combine accuraciesreturn {'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 = 10opt_func = torch.optim.Adamlr = 0.00001history = fit(num_epochs, lr, model, train_dl, val_dl, opt_func)Epoch [0], train_loss: 0.8719, val_loss: 0.3769, val_acc: 0.8793Epoch [1], train_loss: 0.4265, val_loss: 0.3104, val_acc: 0.8942Epoch [2], train_loss: 0.3682, val_loss: 0.2884, val_acc: 0.9016Epoch [3], train_loss: 0.3354, val_loss: 0.2819, val_acc: 0.8988Epoch [4], train_loss: 0.3205, val_loss: 0.2704, val_acc: 0.9033Epoch [5], train_loss: 0.2977, val_loss: 0.2722, val_acc: 0.9021Epoch [6], train_loss: 0.2853, val_loss: 0.2629, val_acc: 0.9068Epoch [7], train_loss: 0.2784, val_loss: 0.2625, val_acc: 0.9045Epoch [8], train_loss: 0.2697, val_loss: 0.2623, val_acc: 0.9033Epoch [9], train_loss: 0.2530, val_loss: 0.2629, val_acc: 0.9018

18. 訓練(第二階段)

讓我們訓練更多的曆元並評估該模型。

19. 訓練(第 3 階段)

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

num_epochs = 10opt_func = torch.optim.Adamlr = 0.00001history = fit(num_epochs, lr, model2, train_dl, val_dl, opt_func)Epoch [0], train_loss: 1.6437, val_loss: 1.4135, val_acc: 0.7686Epoch [1], train_loss: 1.2088, val_loss: 0.9185, val_acc: 0.8582Epoch [2], train_loss: 0.8531, val_loss: 0.6467, val_acc: 0.8594Epoch [3], train_loss: 0.6709, val_loss: 0.5129, val_acc: 0.8640Epoch [4], train_loss: 0.5773, val_loss: 0.4416, val_acc: 0.8693Epoch [5], train_loss: 0.5215, val_loss: 0.4002, val_acc: 0.8739Epoch [6], train_loss: 0.4796, val_loss: 0.3725, val_acc: 0.8767Epoch [7], train_loss: 0.4582, val_loss: 0.3559, val_acc: 0.8795Epoch [8], train_loss: 0.4391, val_loss: 0.3430, val_acc: 0.8819Epoch [9], train_loss: 0.4262, val_loss: 0.3299, val_acc: 0.8823

num_epochs = 5opt_func = torch.optim.Adamlr = 0.0001history = fit(num_epochs, lr, model2, train_dl, val_dl, opt_func)Epoch [0], train_loss: 0.4183, val_loss: 0.3225, val_acc: 0.8753Epoch [1], train_loss: 0.3696, val_loss: 0.2960, val_acc: 0.8855Epoch [2], train_loss: 0.3533, val_loss: 0.2977, val_acc: 0.8814Epoch [3], train_loss: 0.3382, val_loss: 0.2970, val_acc: 0.8891Epoch [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 dimension    predictions = 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網絡應用程式。


相關焦點

  • 深度學習黑客競賽神器:基於 PyTorch 圖像特徵工程的深度學習圖像增強
    當我們沒有足夠的數據時,圖像增強是一個非常有效的方法我們可以在任何場合使用圖像增強進行深度學習——黑客競賽、工業項目等等我們還將使用PyTorch建立一個圖像分類模型,以了解圖像增強是如何形成圖片的在深度學習黑客競賽中表現出色的技巧(或者坦率地說,是任何數據科學黑客競賽) 通常歸結為特徵工程。
  • 深度學習黑客競賽神器:基於PyTorch圖像特徵工程的深度學習圖像增強
    當我們沒有足夠的數據時,圖像增強是一個非常有效的方法我們可以在任何場合使用圖像增強進行深度學習——黑客競賽、工業項目等等我們還將使用PyTorch建立一個圖像分類模型,以了解圖像增強是如何形成圖片的在深度學習黑客競賽中表現出色的技巧(或者坦率地說,是任何數據科學黑客競賽) 通常歸結為特徵工程。
  • 使用PyTorch進行表格數據的深度學習
    作者 | Aakanksha NS來源 | Medium編輯 | 代碼醫生團隊使用表格數據進行深度學習的最簡單方法是通過
  • 深度學習框架搭建之PyTorch
    深度學習框架搭建之PyTorchPyTorch 簡介PyTorch 是由 Facebook 推出,目前一款發展與流行勢頭非常強勁的深度學習框架。PyTorch 與 NumPy 非常相似,可以說是它的替代者,支持 GPU 加速運算,用來搭建和訓練深度神經網絡。如果學習過 NumPy 以及常見的深度學習概念(如卷積層,循環層等),非常容易上手PyTorch。目前主流的深度學習框架主要有 TensorFlow,PyTorch,mxnet,caffe和Keras 等。
  • 應用深度學習使用 Tensorflow 對音頻進行分類
    在視覺和語言領域的深度學習方面取得了很多進展,文中一步步說明當我們處理音頻數據時,使用了哪些類型的模型和流程。
  • pytorch+Unet圖像分割:將圖片中的鹽體找出來
    求這個函數有很多方法,但是第一次將深度學習結合起來的是這篇文章全卷積網絡(FCN),利用深度學習求這個函數。在此之前深度學習一般用在分類和檢測問題上。由於用到CNN,所以最後提取的特徵的尺度是變小的。為了讓CNN提取出來的尺度能到原圖大小,FCN網絡利用上採樣和反卷積到原圖像大小。然後做像素級的分類。可以看圖二,輸入原圖,經過VGG16網絡,得到特徵map,然後將特徵map上採樣回去。再將預測結果和ground truth每個像素一一對應分類,做像素級別分類。也就是說將分割問題變成分類問題,而分類問題正好是深度學習的強項。
  • 【深度學習】textCNN論文與原理——短文本分類(基於pytorch)
    前言前文已經介紹了TextCNN的基本原理,如果還不熟悉的建議看看原理:【深度學習】textCNN論文與原理[1]及一個簡單的基於pytorch的圖像分類案例:【深度學習】卷積神經網絡-圖片分類案例(pytorch實現)[2]。
  • 使用PyTorch進行情侶幸福度測試指南
    DeepConnection模型框架計算機視覺--圖像和視頻數據分析是深度學習目前最火的應用領域之一。因此,在學習深度學習的同時嘗試運用某些計算機視覺技術做些有趣的事情會很有意思,也會讓你發現些令人吃驚的事實。
  • 圖像分類:一個更魯棒的場景分類模型
    如何根據圖像的視覺內容為圖像賦予一個語義類別(例如,教室、街道等)是圖像場景分類的目標,也是圖像檢索、圖像內容分析和目標識別等問題的基礎。但由於圖片的尺度、角度、光照等因素的多樣性以及場景定義的複雜性,場景分類一直是計算機視覺中的一個挑戰性問題。本次任務從400萬張網際網路圖片中精選出8萬張圖片,分屬於80個日常場景類別,例如航站樓、足球場等。每個場景類別包含600-1100張圖片。
  • 圖像分類 | 深度學習PK傳統機器學習
    圖像分類的傳統方法是特徵描述及檢測,這類傳統方法可能對於一些簡單的圖像分類是有效的,但由於實際情況非常複雜,傳統的分類方法不堪重負。現在,我們不再試圖用代碼來描述每一個圖像類別,決定轉而使用機器學習的方法處理圖像分類問題。目前,許多研究者使用CNN等深度學習模型進行圖像分類;另外,經典的KNN和SVM算法也取得不錯的結果。
  • 如何用PyTorch訓練圖像分類器
    -99465a1e9bf5如果你剛剛開始使用PyTorch並想學習如何進行基本的圖像分類,那麼你可以參考本教程。它將介紹如何組織訓練數據,使用預訓練神經網絡訓練模型,然後預測其他圖像。為此,我將使用由Google地圖中的地圖圖塊組成的數據集,並根據它們包含的地形特徵對它們進行分類。我會在另一篇文章中介紹如何使用它(簡而言之:為了識別無人機起飛或降落的安全區域)。但是現在,我只想使用一些訓練數據來對這些地圖圖塊進行分類。下面的代碼片段來自Jupyter Notebook。
  • 使用PyTorch進行遷移學習
    概述遷移學習可以改變你建立機器學習和深度學習模型的方式了解如何使用PyTorch進行遷移學習,以及如何將其與使用預訓練的模型聯繫起來我們將使用真實世界的數據集
  • 手把手教你用PyTorch實現圖像分類器(第一部分)
    經過幾個月富有挑戰性但是受益良多的學習,我最近從Udacity的Python Nanodegree program AI編程專業畢業。最後一個項目是用PyTorch創建一個102種不同類型的花的圖像分類器。
  • 【乾貨】史上最全的PyTorch學習資源匯總
    · 開源書籍(https://github.com/zergtant/pytorch-handbook):這是一本開源的書籍,目標是幫助那些希望和使用PyTorch進行深度學習開發和研究的朋友快速入門。但本文檔不是內容不是很全,還在持續更新中。
  • PyTorch官方出品了一本深度學習書,免費提供給開發者
    根據出版商Manning出版社的介紹,這本書的核心,是教你如何使用Python 和 PyTorch 實現深度學習算法。所以出版商介紹稱,想要更好的消化這本書,需要對Python知識和基本線性代數有了解,對深度學習有一些理解更好,但並不需要你具備使用PyTorch或其他深度學習框架的經驗。在多位業內人士看來,這本書的優點是易上手。
  • 新手必備 | 史上最全的PyTorch學習資源匯總
    這是一本開源的書籍,目標是幫助那些希望和使用PyTorch進行深度學習開發和研究的朋友快速入門。但本文檔不是內容不是很全,還在持續更新中。(5)最後,為大家推薦一個簡單易上手的PyTorch中文文檔,非常適合新手學習:https://github.com/fendouai/pytorch1.0-cn。
  • 使用卷積神經網絡進行圖像分類
    卷積神經網絡屬於深度學習的子域。
  • 使用OpenCV深度學習模塊在圖像分類下的應用實踐
    極市導讀:本文來自6月份出版的新書《OpenCV深度學習應用與性能優化實踐》,由Intel與阿里巴巴高級圖形圖像專家聯合撰寫,系統地介紹了OpenCV DNN 推理模塊原理和實踐。極市為大家爭取到5本贈書福利,詳見文末。深度學習理論的廣泛研究促進了其在不同場景的應用。
  • 【學術論文】基於深度學習的圖像分類搜索系統
    深度學習是機器學習研究中的一個新的領域,其動機在於建立、模擬人腦進行分析學習的神經網絡,它模仿人腦的機制來解釋數據,例如圖像、聲音和文本。該系統基於Caffe深度學習框架,首先對數據集進行訓練分析構建深度學習網絡,提取數據集圖像特徵信息,得到數據對應的分類模型,然後以bvlc-imagenet訓練集模型為基礎,對目標圖像進行擴展應用,實現「以圖搜圖」Web應用。
  • PyTorch 完全入門指南!從線性回歸、邏輯回歸到圖像分類
    本文共分3大部分:安裝PyTorch和Jupyter Notebook用PyTorch實現線性回歸使用邏輯回歸實現圖像分類文章超長,秉承用代碼搞定一切的原則,內含大量代碼,建議收藏,並分享給你喜歡的人。同時如果有什麼疑問,也歡迎留言告知我們。Tips:為了方便演示,文中代碼和返回結果是用截圖形式給出。