重磅乾貨,第一時間送達
深度學習是基於人工神經網絡(ANN)的機器學習方法大家庭的一部分。深度學習是當今普遍存在的一種學習方式,它被廣泛應用於從圖像分類到語音識別的各個領域。在這篇文章中,我將向你展示如何構建一個簡單的神經網絡,用PyTorch從視網膜光學相干斷層掃描圖像中檢測不同的眼部疾病。
數據集
OCT 是一種成像技術,用於捕捉活體患者視網膜的高解析度橫截面。每年大約要進行3000萬次 OCT 掃描,這些圖像的分析和解釋需要大量的時間。
這個數據集來自 kaggle,它被分成3個文件夾(train,test,val) ,每個圖像類別包含子文件夾: 脈絡膜新血管生成(CNV) ,糖尿病性黃斑水腫(DME) ,早期 AMD (DRUSEN)中出現的多個視網膜,以及保留中心凹輪廓的正常視網膜,沒有任何視網膜液體/水腫(NORMAL)。
加載和預處理圖像
首先,我們要加載所有的庫,並指定函數,我們將用來加載我們的數據和模型在 GPU 上。
cuda
然後我們將解析 train 文件夾中的所有圖像,以創建包含訓練圖像的每個通道的平均值和標準差的兩個矢量。我們要利用這些數據對圖像進行normalize操作。
現在我們使用 pytorch 加載數據。每幅圖像都是中心像素,大小為490x490像素(為了在每幅圖像之間保持統一大小) ,然後轉換為張量,再進行規範化。
可視化數據
現在我們已經加載並預處理了數據,我們可以進行一些數據探索。
在左邊我們可以看到原始圖像,在右邊我們看到經過預處理的圖像。標準化將所有通道的平均值都集中在零點附近,這種操作有助於網絡更快地學習,因為梯度對每個通道的作用是一致的,並有助於在圖像中產生有意義的特徵。
我們繪製訓練集標籤、驗證集標籤以及測試集標籤的分布圖便於檢查標籤不平衡。我們可以看到,驗證集和測試集中的標籤分布是均勻的,而訓練集中的標籤分布是不平衡的。有不同的方法來處理不平衡的數據集,這裡我們嘗試了抽樣處理。
加載數據
這裡我們使用自定義加載器在 GPU 上加載數據。由於 GPU 的內存不足以容納數以千計的圖像,因此需要批量大小將數據以較小的批量輸入模型。訓練數據集並不是整體加載的,我們使用了一個自定義的採樣器來對數據進行子採樣(為了使每個標籤的分布更加均勻) ,並將訓練數據總數減少到4000個圖像,以加快計算時間的速度。
模型
部分結果
最後我們創建了我們的模型,給出了我們相對較小的樣本量(並且為了加快訓練時間) ,我們使用了遷移學習和 ResNet 的預訓練模型,並刪除了最終的全連接層,並添加了兩個線性層和一個 ReLu 激活函數。因為我們正在做一個分類任務,我們的損失函數將是交叉熵損失。
訓練模型
一個經過訓練的模型是有用的,因為它的層已經被訓練來提取特徵(比如特定的形狀或線條,等等)。因此,在訓練過程中,網絡卷積部分的權重和偏差不會發生很大變化。另一方面,我們創建的全連接層是用隨機權重初始化的。解決這個問題的一個方法是凍結網絡中所有預先訓練的部分,只訓練最後的全連接層,然後解凍所有的網絡,以較低的學習率訓練它。我們採用了另一種技術:我們對網絡的每個部分使用不同的學習速度。更深的網絡層使用更低的學習率。通過這種方法,我們訓練了分類器,並對預訓練的網絡進行了微調,而無需對其進行兩次訓練。
作為一個例子,我們使用 Adam 優化器對這個網絡進行了15個 epoch 的訓練,學習率為0.004,並使用了一個學習率調度器。
計劃學習率是非常有用的,因為高學習速率有助於網絡學習更快,但他們有可能錯過最小的損失函數。另一方面,低學習率可能太慢了。
我們使用了一個調度器,降低了學習率一旦它停止,以減少損失函數。我們繪製每個 epoch 的損失函數、學習速度和不同的分類指標:
所有的指標在短短幾個時期內就達到了0.9,在訓練結束時驗證的準確率達到了93.75% ,對於一個簡單的網絡來說,這已經不錯了!
測試模型
最後,我們使用測試集來測試模型。首先讓我們看看相關矩陣:
這幾乎是完美的!該模型能夠正確地對幾乎所有的標籤進行分類,其中11% 的DRUSEN 圖像混淆為 CNV。現在讓我們來看看測試集的度量:
最後,測試集上的所有度量值都是0.97,甚至高於驗證集!
這個網絡表現很好,但是它還可以改進:
更多的 epoch :由於時間限制,我們只訓練了15個 epoch,使用更多的 epoch 可以極大地提高準確性;
早期停止:使用更多的時期,我們可以避免數據過擬合的風險和增加泛化誤差,早期停止訓練,避免為了過度擬合測試集引起的驗證集的loss爆炸;
改變參數:學習速度,權重衰減等。所有的參數均可以調整,以提高準確性;
使用數據增強:增加隨機旋轉、裁剪等等可以幫助模型更好地泛化。