這篇是我對嗶哩嗶哩up主 @霹靂吧啦Wz 的視頻的文字版學習筆記 感謝他對知識的分享
有關我們數據讀取預訓練
以及如何將它打包成一個一個batch輸入我們的網絡的
首先我們來看一下之前我們在講resnet網絡時所使用的源碼
我們去使用了官方實現的image?folder去讀取我們的圖像數據
然后再使用官方提供的data?loader去對我們讀取的數據進行一個打包
大家有沒有想過這個image?folder它的內部到底實現了哪些功能呢
那么我們今天為什么要講這個dataset呢
因為在之前我們講分類網絡時
有很多小伙伴私信問我
如果我的圖片不是rgb圖像
是灰度圖像或者是雷達圖像
深度圖像等等
就是非rgb的圖像時
我該如何去載入并預處理我的圖像
那么如果你直接通過官方提供的這個方法呢
其實它是有一定的局限性的
而且比如如果你想去設計一個比較獨特的網絡
比如說你設計的網絡
它有多個輸入
那么這種情況呢官方所提供的這些方法都是無法滿足你的需求的
所以本節課我們來講一下如何去實現我們自己的一個data?set
以及進一步去講解我們的data?loader是如何利用我們data?set所生成的數據
打包成一批一批的數據輸入網絡的
那么本節課所講的一個代碼呢
我已經提前上傳到我的github上了
在pytourh?classification模塊下的custom?dataset這個文件夾當中
然后這三個文件呢就是我們今天主要要講的內容了
那么這個內容呢也是我們在后面講利用多gpu訓練時
所使用到的一個數據讀取
以及預處理的部分
那么我們接下來就進入到我們的代碼當中
首先呢我們看一下我們的main這個腳本
首先呢我們這里所使用的數據集
還是我之前所說的劃分類數據集
之前也有小伙伴在問我數據在哪下載呀
我該如何去劃分訓練集以及驗證集
那么今天呢我在這里就詳細地將整個流程仔細的講一遍
并且呢我這里寫了一個新的關于劃分數據集的一個腳本
相比原來那個腳本呢使用起來會更加的方便
不需要再將訓練集以及驗證集單獨劃分到不同的文件夾當中了
首先呢如果你想使用之前我們所說的花分類數據集
那么大家可以自己去在這個鏈接當中去下載
下載完之后呢
你會得到一個點tgz的一個壓縮文件
然后解壓之后呢
我們可以看到都有個flower?photos
在這個文件夾下呢主要有這五個子文件夾
每個文件夾呢它對應的一種花的類型
比如說我們看這個daisy
這個daisy呢它對應的就是雛菊
也就是說在這個文件夾下面的所有圖片都是關于雛菊這個類別
那么我們下載完之后呢
我們這里的root這個變量就指向我們的flower?photos
那么我這里就已經設置好了
就保存在我所給定的這個路徑下
然后呢我們就進入到我們這個main函數
接下來呢我們就使用我們的read?split?data
這個方法來劃分我們的訓練集一驗證集
那么這個方法呢我們只需要傳入一個root這個參數就可以了
然后我們來仔細的看一下這個方法
進入這個方法之后呢
我們可以看到有兩個參數
第一個是root
就是我們剛剛所說指向我們解壓后的文件夾的路徑
然后這個rate它是我們劃分驗證集所占所有樣本的一個比例
我們這里將我們引入的random這個隨機的這個包
設置一個隨機種子設置為零
這里為什么要設計隨機種子呢
就在于能夠保證隨機結果是可以復現的
也就是說只要我們將這個random的種子設置為零之后
無論是在你的電腦上
我的電腦上還是其他人電腦上
我們待會兒通過隨機函數所隨機劃分的數據都是一模一樣的
也就是都是可復現的
這樣呢就能夠保證大家劃分的數據集都是一模一樣的
然后接下來呢我們來判斷一下我們所傳入的這個路徑
它是否存在
如果不存在
我們就會報出一個錯誤
接下來我們再通過os庫的例子
第二來便利我們所給的那個路徑下的所有的文件
那么它它變的文件呢可能就包含有文件夾以及我們普通的文件
然后這里呢我們就通過一個for循環來遍歷它所編輯得到的
每一個文件夾或文件
接下來我們再判斷
如果我們的這個路徑它所對應的是個文件夾的話
那么我們就將它進行保存
如果不是文件夾的話
那我們就將它丟棄
那么這樣我們得到的flower?class就應該有五個值
初始化幾個空列表
那么這里呢我再多說一句
我們這里為什么要使用PIL的image這個庫
而不去使用open?cv
因為在touch它所提供的這一系列預處理方法
其實它主要還是針對pl庫所讀入的images
比如我們隨機看一個預處理方法
那么在他預處理方法的計劃當中呢
他寫的就是針對一個PIL的image進行一個處理的
然后這里我再多說一句
就是有時候我們在調試過程當中可能會遇到這種情況
就是我想看一下變量的一個信息
但是我設置斷點之后
我們在debug這個信息當中呢
看到每個變量一直在顯示正在載入數據
然后一直看不到
那么這個問題要怎么解決呢
那么這里呢大家可以點擊這個file
然后在設置當中
然后在我們的build?execution?deployment
然后在這個地方呢大家可以勾選一下這個
然后再點ok
這樣的話你在調試過程當中
每一個變量它的參數值就會很快的載入進來了
那么通過stack方法之后呢
它會增加一個新的維度
那么這個新維度是在dimension等于零的位置上
那么拼接之后我們可以來看一下我們所得到的shape
那接下來我們再將我們的labels也轉化成tensor形式
因為剛在我們item的方法當中呢
我們通過transform方法將我們的image已經轉換成tensor格式了
但我們label它并不是tender格式
所以這里我們要通過touch?as?tensor這個方法
我們label也轉換成tensor
然后我們所得到的labels呢
它就是一個tensor變量了
然后我們再通過return
就可以將我們打包好的圖片以及標簽信息進行一個返回
那么接下來我們再停止我們的一個調試過程
我們再回到我們的main函數當中
那么這里我們講了這么多
我說的這些到底是不是對的呢
我們接下來再通過我們所得到的這個train?data?loader
應該讀取它的圖片以及標簽信息
看是否是正確的
那么這里我又實現了個plot?data?loader?image這個方法
那我們來看一下這個方法
這個方法當中呢
首先我們獲取一下我們這個data?load的batchsize
然后我們這個json?pass就指向我們剛剛生成的這個json文件
然后我們這里判斷一下存存在
如果不存在就報錯
然后我們再打開這個計算文件
然后載入它就得到了我們的一個字典
然后通過transport方法來調整它的一個通道順序
原來通道順序是channel
高度寬度
那么通過transpose之后
我們就還原成了高度寬度以及channel
然后在我們剛剛預處理過程當中呢
首先我們這個Totensor會將我們的數據范圍從0~255
縮放到0~1之間
然后呢通過這個normalize這個方法
將我們數據rgb?個通道的數值分別減去這三個均值
然后再除以這三個標準差
得到我們標準化之后的數據
那么現在我們讀入的數據就是標準化之后的數據
如果我們要繪制它呢
我們就需要將它轉化回去
所以呢我們這里就對我們的rgb?通道首先乘以這三個數值
然后再加上這三個數值
然后再乘以255
我們就可以還原回原來的一個圖像了
那么我們這里繪制的一個圖像當中一共有1個行,plot?number個列
我們這里呢由于我們剛剛進行了一系列操作之后呢
它是一個float類型
我們這里將它轉化成一個int?類型然后再show