第七章 遷移學習

2021-10-08 15:53:01 字數 3915 閱讀 7056

簡介:本章將通過搭建卷積神經網路模型對生活中的普通進行分類,並引入遷移學習(transfer learning)方法。為了驗證遷移學習方法的方便性和高效性,我們先使用自定義結構的卷積神經網路模型解決的分類問題,然後通過使用遷移學習方法得到的模型來解決同樣的問題,以此來看看在效果上是傳統的方法更出色,還是遷移學習方法更出色。

(因為本章**使用cpu執行時間高達5個小時,所以暫時沒有進行實踐。)

1.遷移學習入門

使用遷移模型解決同一類問題,由於這種方法的出現,我們通過對乙個訓練好的模型進行細微調整,就能將其應用到相似的問題中,最後還能取得很好的效果;另外,對於原始資料較少的問題,我們也能夠通過採用遷移模型進行有效解決,所以,如果能夠選取合適的遷移學習方法,則會對解決我們所面臨的問題有很大的幫助。

使用遷移模型時,要對遷移的模型進行重新訓練,這是因為最後分類的物件發生了變化。

需要注意的是,在使用遷移學習的過程中有時會導致遷移模型出現負遷移,我們可以將其理解為模型的泛化能力惡化。假如我們將遷移學習用於解決兩個毫不相關的問題,則極有可能使得最後遷移得到的模型出現負遷移。

2.資料集處理

本章使用的資料集來自kaggle**上的「dogs vs. cats」競賽專案。在這個資料集中乙個有25000張貓和狗的,其中包含12500張貓的和12500張狗的在測試資料集中又12500張,不過其中的貓狗是無序混雜的,而且沒有對應的標籤。這些資料集將被用於對模型進行訓練和對引數進行優化,以及在最後對模型的泛化能力進行驗證。

(1)驗證資料集和測試資料集

為了防止過擬合,模型缺少泛化能力,我們會把測試資料集從模型的訓練和優化過程中隔離出來,只在每輪訓練結束後使用。如果模型對驗證資料集(從訓練資料集中劃分出來的)和測試資料集的**同時具備高準確率和低損失值,就基本說明模型的引數優化是成功的,模型將具備極強的泛化能力。

在本章實踐中我們分別從訓練資料集的貓和狗的中各抽出2500張組成乙個具有5000張的驗證資料集。

本章不使用測試資料集,進行的只是模型對驗證資料集的準確性的橫向比較。

(2)資料預覽

在劃分好資料集之後,就可以先進行資料預覽了。我們通過資料預覽可以掌握資料的基本資訊,從而更好的決定如何使用這些資料。

import torch

import torchvision

from torchvision import datasets,transforms

import os

import matplotlib.pyplot as plt

import time

%matplotlib inline

在以上**中先導入了必要的包,和之前不同的是新增加了os包和time包,os包整合了一些對檔案路徑和目錄進行操作的類,time包主要是一些和時間相關的方法。

在獲取全部資料集之後,我們就可以對這些資料進行簡單的分類了。新建乙個名為dogsvscats的資料夾,在該資料夾下面新建乙個名為train和乙個名為valid的子資料夾。在子資料夾下面再分別新建乙個名為cat的資料夾和乙個名為dog的資料夾,最後將資料集對應部分的資料放到對應名字的資料夾中,之後就可以進行資料的載入了。

在進行資料的載入時我們使用torch.transforms中的scale類將原始的大小統一縮放至64×64。在以上**中對資料的變換和匯入都使用了字典形式,因為我們需要分別對訓練資料集和驗證資料集的資料載入方法進行簡單定義,所以使用字典可以簡化**,也方便之後進行相應的呼叫和操作。

os.path.join就是來自之前提到的os包的方法,它的作用是將輸入引數中的兩個名字拼接成乙個完整的檔案路徑。

其他常用的os.path類方法如下:

os.path.dirname:用於返回乙個目錄的目錄名,輸入引數為檔案的目錄。

os.path.exists:用於測試輸入引數指定的檔案是否存在。

os.path.isdir:用於測試輸入引數是否是目錄名。

os.path.isfile:用於測試輸入引數是否是乙個檔案。

os.path.samefile:用於測試兩個輸入的路徑引數是否指向同乙個檔案。

os.path.split:用於對輸入引數中的目錄名進行分割,返回乙個元組,該元組由目錄名和檔名組成。

下面獲取乙個批次的資料並進行資料預覽和分析。

以上**通過next和iter迭代操作獲取乙個批次的裝載資料,不過因為受到我們之前定義的bath_size值的影響,這一批次的資料只有16張,所以x_example和y_example的長度也全部是16。

其中x_example是tensor資料型別的變數,因為做了大小的縮放變換,所以現在的大小全部是64×64了,那麼x_example的維度就是(16,3,64,64),16代表在這個批次中有16張;3代表色彩通道數,因為原始是彩色的,所以使用了r、g、b這三個通道;64代表的寬度值和高度值。

y_example也是tensor資料型別的變數,不過其中的元素全部是0和1。這是因為在進行資料裝載時已經對dog資料夾和cat資料夾下的內容進行了獨熱編碼(one-hot encoding),所以這時的0和1不僅是每張的標籤,還分別對應貓的和狗的。

貓的標籤和狗的標籤被獨熱編碼後分別被數位化了,相較於使用文字作為的標籤而言,使用0和1也可以讓之後的計算方便很多。

不過,為了增加之後繪製的影象標籤的可識別性,我們還需要通過image_datasets[「train」].classes將原始標籤的結果儲存在名為example_classes的變數中。

example_classes變數其實是乙個列表,而且在這個列表中只有兩個元素,分別是dog和cat。我們使用matplotlib對乙個批次的進行繪製。

3.模型搭建和引數優化

其基本思路是凍結卷積神經網路中全連線層之前的全部網路層次,讓這些被凍結的網路層次中的引數在模型的訓練過程中不進行梯度更新,能夠被優化的引數僅僅是沒有被凍結的全連線層的全部引數。

首先,遷移過來的vgg16架構模型在最後輸出的結果是1000個,在我們的問題中只需要兩個輸出結果,所以全連線層必須進行調整。

首先,對原模型中的引數進行遍歷操作,將引數中的parma.requires_grad全部設定為false,這樣對應的引數將不計算梯度,當然也不會進行梯度更新了,這就是之前說到的凍結操作;然後,定義新的全連線層結構並重新賦值給model.classifier。在完成了新的全連線層定義後,全連線層中的parma.requires_grad引數會被預設重置為true,所以不需要再次遍歷引數來進行解凍操作。損失函式的loss值依然使用交叉熵進行計算,但是在優化函式中負責優化的引數變成了全連線層中的所有引數,即對model.classifier.parameters這部分引數進行優化。

通過應用遷移學習,最後的結果在準確率上提公升非常多,而且僅僅通過5次訓練就達到了這個效果,所以遷移學習是一種提公升模型泛化能力的非常有效的方法。

(3)遷移resnet50

在掌握了遷移學習方法之後,下面來看強大的resnet架構的卷積神經網路模型的遷移學習。在下面例項中會將resnet架構中的resnet50模型進行遷移,進行模型遷移的**為model=models.resnet50(pretrained=true)。

和遷移vgg16模型類似,在**中使用resnet50對vgg16進行替換就完成了對應模型的遷移。

因為resnet50中的全連線層只有一層,所以對**的調整非常簡單。

同樣,僅僅是最後一部分全連線層有差異,對遷移得到的模型進行5次訓練,可以看到,準確率同樣非常理想,和之前遷移學習得到的vgg16模型相比在模型**的準確率上相差不大。

**總結:**通過本章學習發現,gpus在深度學習的計算優化過程中效率明顯高於cpu;遷移學習非常強大,能快速解決同類問題,對於類似的問題不用再從頭到尾對模型的全部引數進行優化。我們對於複雜模型的引數優化可能需要數週,採用遷移學習的思路能大大節約時間成本。當然,如果模型的訓練結果不很理想,則還可以訓練更多的模型層次,優化更多的模型引數,而不是盲目的從頭訓練。

第七章學習小結

第七章的內容是查詢。查詢可以分為3種。分別是線性表查詢 樹表查詢 雜湊表查詢。1 線性表查詢 線性表查詢主要介紹了順序查詢和折半查詢這兩種方法。1 順序查詢區別於上學期學的方法,設定了哨兵,採用從後往前開始查詢的方法,將時間複雜度縮短了一倍。asl n 1 2 2 折半查詢,其實也叫二分查詢,原理是...

第七章學習小結

查詢的基本概念 查詢表 同一型別的資料元素 記錄 構成的集合。靜態查詢表 對查詢表只進行查詢操作。動態查詢表 不僅進行查詢操作,而且在查詢過程中還伴隨著插入 查詢的資料元素不在表中時 刪除某個資料元素的操作。關鍵字 key 是資料元素 或記錄 的某個資料項的值,用它可標識 識別 乙個資料元素 或記錄...

python第七章 python教程(第七章)

字典和集合 字典是python中唯一,乙個對映型別 如何建立乙個字典,如下 dict dict 滲透 網路安全 怎麼理解字典呢?現實生活中的字典可以通過首字母進行查詢要查詢的漢子,python也可以這樣理解,通過 前的元素查詢到冒號後的元素。為什麼說字典是唯一乙個對映型別呢?看圖。對映型別區別與序列...