版權聲明:本文爲原創文章,未經博主允許不得用於商業用途。
1. Auto-Encoder
1.1 原理
最基本的AutoEncode是由三層網絡組成的,即輸入層,輸出層和編碼層,這裏拓展爲深度模型則將Encoder和Decoder都變爲一個深度網絡,如下圖:
優化目標爲使得輸入和輸出儘可能相似,而中間的Code即爲降維後的結果。
相比於PCA或者LDA,DAE的多層網絡結構使得其爲非線性模型,因此可以更好的還原輸入。
1.2 數據集
數據集使用了李宏毅老師提供的寶可夢數據集,鏈接如下:
原始圖片
編碼後數組
colormap
共包含792種寶可夢的彩色圖片,每張圖片大小爲20*20,已經經過預處理將顏色空間從256*256*256映射到常用的167種顏色並重新按需編碼儲存。
本來這樣應該可以降低輸入的維度從而減少網絡的複雜程度,但是在真正訓練時發現由於167種顏色之間沒有線性關係,因此如果直接將數據集作爲輸入則很容易出現小的偏差造成輸出圖片上的巨大差異,如輸出從7.3到7.6,則在繪圖時會從7號顏色(如白色)變爲8號顏色(如黑色),因此只能將每一個像素映射爲167維的01向量,將原來的線性預測模型變爲20*20個分類器,輸入維度變爲20*20*167。
由於我目前在用新筆記本,沒有獨顯,只能用CPU跑,所以在訓練時只選擇了其中的110個寶可夢作爲數據集。
1.3 構建網絡
我直接使用了五個全連接層作爲encoder和decoder,最後使用Sigmoid映射到0,1,代碼如下:
class ATE(nn.Module):
def __init__(self):
super(ATE,self).__init__()
self.encoder = nn.Sequential(
nn.Linear(400*167,400),
nn.Linear(400,128),
nn.Linear(128,64),
nn.Linear(64,12),
nn.Linear(12,5),
)
self.decoder = nn.Sequential(
nn.Linear(5,12),
nn.Linear(12,64),
nn.Linear(64,128),
nn.Linear(128,400),
nn.Linear(400,400*167),
nn.Sigmoid(),
)
def forward(self,x):
x=self.encoder(x)
x=self.decoder(x)
return x
1.4 訓練結果
編碼-解碼
訓練時採用BCE誤差,Adam優化器,效果如下:
其中左側爲輸入數據,右側爲經過DAE編碼-解碼後的輸出,從顏色和形狀來看很好的還原了原來的特徵。
生成
我嘗試使用DAE產生一些中間圖片。
之前聽說過DAE無法很好的產生新的數據,這是由於訓練時無法保證編碼空間裏樣本點周圍的點都可以有效解碼,且和樣本相關聯。
我選擇了比較相似的寶可夢之間的向量作爲生成碼,具體即將兩個樣本之間的高維空間線段等分後進行解碼。
上方是從皮丘進化到皮卡丘的過程,可以看到中間幾張圖都完全看不出形象並且失去了原來的顏色。下方是從鬼斯進化到鬼斯通,信息保留比較好,不過中間的都不像是新的寶可夢。
源碼見github