优达学城《DeepLearning》2-4:自编码器(无监督学习算法)
本次包含3個部分:
- 簡單的自編碼器
- 卷積自編碼器
- 去噪自編碼器
?
目錄
1 簡單的自編碼器
壓表示法縮
可視化數據
線性自編碼器
訓練
檢查結果
2 卷積自編碼器
Encoder
Decoder
解碼器:轉置卷積
訓練
檢查結果
(額外)解碼器:上采樣層 + 卷積層
3 去噪自編碼器
去噪
訓練
檢查去噪效果
?
1 簡單的自編碼器
首先,我們將構建一個簡單的自動編碼器來壓縮MNIST數據集。使用自動編碼器,我們通過編碼器傳遞輸入數據,該編碼器對輸入數據進行了壓縮表示。然后,這個表示通過一個解碼器來重建輸入數據。通常,編碼器和解碼器將結合神經網絡一同使用,然后訓練示例數據。
壓表示法縮
壓縮表示非常適合以比存儲原始數據更高效的方式保存和共享任何類型的數據。在實踐中,壓縮表示通常保存有關輸入圖像的關鍵信息,我們可以用它去噪圖像或其他類型的重建和變換!
在本筆記本中,我們將為編碼器和解碼器構建一個簡單的網絡架構。讓我們開始導入庫并獲取數據集。
可視化數據
線性自編碼器
我們將用這些圖像訓練一個自動編碼器,將它們拉平成784長度的向量。來自該數據集的圖像已經標準化,其值在0到1之間。讓我們從構建一個簡單的自動編碼器開始。編碼器和解碼器應由一個線性層構成。連接編碼器和解碼器的單元將是壓縮表示(compressed representation)。
由于圖像是在0到1之間標準化的,我們需要在輸出層上使用sigmoid激活來獲得與輸入值范圍匹配的值。
待辦事項:在下面的單元格中為自動編碼器構建圖表。
- 輸入的圖像將被拉平為784長度的向量。目標與輸入是相同的。編碼器和解碼器將由兩層線性層組成。深度維度應更改如下:784 inputs > encoding_dim > 784 outputs。所有層都將應用ReLu激活,除了最終輸出層,它有一個sigmoid激活。
compressed representation應該是一個維度為 encoding_dim=32 的向量。
訓練
在這里,我將編寫一些代碼來訓練網絡。我在這里對驗證不太感興趣,所以我會在之后監控訓練損失和測試損失。
在本例中,我們不關心標簽,只關心圖像,我們可以從train_loader中獲得圖像。因為我們正在比較輸入和輸出圖像中的像素值,所以最好使用用于回歸任務的損失函數。回歸是關于比較數量而不是概率值。在本例中,我將使用MSELoss。并將輸出圖像和輸入圖像進行如下比較:
另外,這是非常簡單的PyTorch訓練。我們將圖像拉平,將其輸入自動編碼器,并記錄下訓練過程中的損失。
檢查結果
下面我繪制了一些測試圖像及其重建圖。在大多數情況下,這些看起來很好,除了一些模糊的部分。
下一節內容
我們這里處理的是圖像,所以我們(通常)可以使用卷積層獲得更好的性能。所以,接下來我們將使用卷積層構建一個更好的自動編碼器。
2 卷積自編碼器
繼續使用MNIST數據集,讓我們使用卷積層來改進自動編碼器的性能。我們將建立一個卷積自動編碼器來壓縮MNIST數據集。
編碼器部分將由卷積和池化層組成,解碼器將由學習“上采樣”壓縮表示的轉置卷積層組成。
Encoder
網絡的編碼器部分將是一個典型的卷積金字塔。每個卷積層后面都有一個最大池化層,以降低層的維數。
Decoder
不過這個解碼器對你來說可能是新的。解碼器需要從窄表示轉換為寬的、重建的圖像。例如,表示可以是一個7x7x4的max-pool層。這是編碼器的輸出,也是解碼器的輸入。我們想從解碼器中得到一個28x28x1的圖像,所以我們需要從壓縮的表示返回。網絡的原理圖如下所示。
這里我們最終的編碼器層的大小是7x7x4 = 196。原始圖像的大小是28x28 = 784,所以編碼后的向量是原始圖像大小的25%。這些只是每一層的建議尺寸。你可以隨意改變深度和大小,事實上,我們鼓勵你添加額外的層來讓這個表現更小!記住,我們這里的目標是找到輸入數據的一個小表示。
解碼器:轉置卷積
該解碼器使用轉置卷積層來增加輸入層的寬度和高度。它們的工作原理與卷積層幾乎完全相同,只是方式相反。輸入層的步幅導致轉置卷積層的步幅。例如,如果你有一個3x3的內核,那么輸入層中的一個3x3 patch就會被簡化為一個卷積層中的一個單元。相比較而言,輸入層中的一個單元將擴展為轉置卷積層中的3x3 patch。PyTorch為我們提供了一種創建圖層的簡單方法nn.ConvTranspose2d。
值得注意的是,轉置卷積層可能導致最終圖像中的偽影,比如棋盤圖案。這是由于內核中的重疊,可以通過設置步幅和內核大小相等來避免重疊。在Augustus Odena等人的這篇Distill文章中,作者指出,通過使用最近鄰或雙線性插值(上采樣)然后使用卷積層來調整圖層大小,可以避免這些棋盤效應。
- 我們將在另一個筆記本中展示這種方法,以便您可以試驗它并看到區別。
待辦事項:建立如上所示的網絡。
- 用一系列卷積層和池化層構建編碼器。在構建解碼器時,記得轉置卷積層可以使用stride和kernel_size=2來對輸入進行向上采樣。
訓練
# specify loss function
criterion = nn.MSELoss()# specify loss function
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# number of epochs to train the model
n_epochs = 30for epoch in range(1, n_epochs+1):# monitor training losstrain_loss = 0.0#################### train the model ####################for data in train_loader:# _ stands in for labels, here# no need to flatten imagesimages, _ = data# clear the gradients of all optimized variablesoptimizer.zero_grad()# forward pass: compute predicted outputs by passing inputs to the modeloutputs = model(images)# calculate the lossloss = criterion(outputs, images)# backward pass: compute gradient of the loss with respect to model parametersloss.backward()# perform a single optimization step (parameter update)optimizer.step()# update running training losstrain_loss += loss.item()*images.size(0)# print avg training statistics train_loss = train_loss/len(train_loader)print('Epoch: {} \tTraining Loss: {:.6f}'.format(epoch, train_loss))
結果:
Epoch: 1 Training Loss: 0.536067
Epoch: 2 Training Loss: 0.296300
Epoch: 3 Training Loss: 0.271992
Epoch: 4 Training Loss: 0.257491
Epoch: 5 Training Loss: 0.248846
Epoch: 6 Training Loss: 0.242581
Epoch: 7 Training Loss: 0.238418
Epoch: 8 Training Loss: 0.235051
Epoch: 9 Training Loss: 0.232203
Epoch: 10 Training Loss: 0.230150
Epoch: 11 Training Loss: 0.228493
Epoch: 12 Training Loss: 0.226843
Epoch: 13 Training Loss: 0.225579
Epoch: 14 Training Loss: 0.224565
Epoch: 15 Training Loss: 0.223704
Epoch: 16 Training Loss: 0.222844
Epoch: 17 Training Loss: 0.221671
Epoch: 18 Training Loss: 0.220569
Epoch: 19 Training Loss: 0.219486
Epoch: 20 Training Loss: 0.218675
Epoch: 21 Training Loss: 0.218025
Epoch: 22 Training Loss: 0.217432
Epoch: 23 Training Loss: 0.216864
Epoch: 24 Training Loss: 0.216343
Epoch: 25 Training Loss: 0.215857
Epoch: 26 Training Loss: 0.215377
Epoch: 27 Training Loss: 0.214942
Epoch: 28 Training Loss: 0.214570
Epoch: 29 Training Loss: 0.214245
Epoch: 30 Training Loss: 0.213977
檢查結果
下面我繪制了一些測試圖像及其重建圖。這些看起來有點粗糙的邊緣,可能是由于我們上面提到的棋盤效應,往往發生在轉置層。
訓練結果:
Epoch: 1 Training Loss: 0.323222
Epoch: 2 Training Loss: 0.167930
Epoch: 3 Training Loss: 0.150233
Epoch: 4 Training Loss: 0.141811
Epoch: 5 Training Loss: 0.136143
Epoch: 6 Training Loss: 0.131509
Epoch: 7 Training Loss: 0.126820
Epoch: 8 Training Loss: 0.122914
Epoch: 9 Training Loss: 0.119928
Epoch: 10 Training Loss: 0.117524
Epoch: 11 Training Loss: 0.115594
Epoch: 12 Training Loss: 0.114085
Epoch: 13 Training Loss: 0.112878
Epoch: 14 Training Loss: 0.111946
Epoch: 15 Training Loss: 0.111153
Epoch: 16 Training Loss: 0.110411
Epoch: 17 Training Loss: 0.109753
Epoch: 18 Training Loss: 0.109152
Epoch: 19 Training Loss: 0.108625
Epoch: 20 Training Loss: 0.108119
Epoch: 21 Training Loss: 0.107637
Epoch: 22 Training Loss: 0.107156
Epoch: 23 Training Loss: 0.106703
Epoch: 24 Training Loss: 0.106221
Epoch: 25 Training Loss: 0.105719
Epoch: 26 Training Loss: 0.105286
Epoch: 27 Training Loss: 0.104917
Epoch: 28 Training Loss: 0.104582
Epoch: 29 Training Loss: 0.104284
Epoch: 30 Training Loss: 0.104016
編解碼效果:
(額外)解碼器:上采樣層 + 卷積層
該解碼器使用最近鄰上采樣層和正常卷積層的組合來增加輸入層的寬度和厚度。
待辦事項:建立如下所示的網絡。
- 用一系列卷積層和池化層構建編碼器。在構建解碼器時,使用上采樣和正常卷積層的組合。
3 去噪自編碼器
繼續使用MNIST數據集,讓我們給數據添加噪聲,看看我們是否可以定義和訓練一個自動編碼器去噪。
讓我們開始導入庫并獲取數據集。
去噪
正如我之前提到的,像您目前所構建的自動編碼器在實踐中并不是太有用。然而,只要在有噪聲的圖像上訓練網絡,就可以很成功地用于圖像去噪。我們可以通過在訓練圖像中添加高斯噪聲來創建噪聲圖像,然后將其裁剪到0到1之間。
- 我們將使用噪聲圖像作為輸入,原始的、干凈的圖像作為標簽。
下面是我生成的一些噪聲圖像和相關的去噪圖像的例子。
因為這對網絡來說是一個更難的問題,所以我們想在這里使用更深的卷積層;層與更多的功能地圖。您也可以考慮添加額外的層。我建議將編碼器中的卷積層的深度設為32,并將相同的深度倒推到解碼器中。
TODO:構建去噪自編碼器的網絡。與上面的模型相比,添加更深的和/或更多的層。
訓練
我們只關心可以從train_loader中獲得的訓練圖像。
在本例中,我們實際上給這些圖像添加了一些噪聲,并將這些噪聲y_imgs提供給我們的模型。該模型將產生基于噪聲輸入的重建圖像。但是,我們希望它產生正常的無噪聲圖像,所以,當我們計算損失時,我們仍然會將重建的輸出與原始圖像進行比較!
因為我們正在比較輸入和輸出圖像中的像素值,所以最好使用用于回歸任務的損失函數。在本例中,我將使用MSELoss。并將輸出圖像和輸入圖像進行如下比較:
檢查去噪效果
總結
以上是生活随笔為你收集整理的优达学城《DeepLearning》2-4:自编码器(无监督学习算法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 优达学城《DeepLearning》2-
- 下一篇: AI视频行为分析系统项目复盘——技术篇1