详解自动编码器(AE)
自動編碼器(AE,DAE,CAE,SAE)的方法介紹與簡單實現(附代碼)
自動編碼器的發展簡述
自動編碼器(Auto-Encoders,AE)
傳統的自動編碼器是一種數據的壓縮算法
其算法包括編碼階段和解碼階段,且擁有對稱的結構。
目前自編碼器的應用主要有兩個方面,第一是數據去噪,第二是為進行可視化而降維。配合適當的維度和稀疏約束,自編碼器可以學習到比PCA等技術更有意思的數據投影。
傳統編碼器的編解碼過程描述如圖:
評價:
傳統自編碼器的目的是使輸出與輸入盡量相同,這完全可以通過學習兩個恒等函數來完成,但是這樣的變換沒有任何意義,因為我們真正關心的是隱層表達,而不是實際輸出。因此,針對自編碼器的很多改進方法都是對隱層表達增加一定的約束,迫使隱層表達與輸入不同。
降噪自編碼(Denoising Auto-Encoders, DAE)(2008)
自編碼器真正關心的是隱藏層的特征表達,一個好的表達能夠捕獲輸入信號的穩定結構,以該目的為出發出現了降噪自動編碼器。
降噪自動編碼器,首先對干凈的輸入信號加入噪聲產生一個受損的信號。然后將受損信號送入傳統的自動編碼器中,使其重建回原來的無損信號。
降噪自編碼器的編解碼過程描述如圖:
降噪自編碼器與傳統的自動編碼器的主要區別在于:
1.降噪自編碼器通過人為的增加噪聲使模型獲得魯棒性的特征表達
2.避免使隱層單元學習一個傳統自編碼器中沒有意義的恒等函數
評價:
降噪自編碼器通過對輸入信號人為地進行損壞,主要是為了達到兩個目的,首先是為了避免使隱層單元學習一個傳統自編碼器中沒有實際意義的恒等函數,其次就是為了使隱層單元可以學習到一個更加具有魯棒性的特征表達。
降噪自編碼器最大的優點在于,重建信號對輸入中的噪聲具有一定的魯棒性,而最大的缺陷在于每次進行網絡訓練之前,都需要對干凈輸入信號人為地添加噪聲,以獲得它的損壞信號,這無形中就增加了該模型的處理時間。
堆疊降燥自動編碼器 (Stacked Denoising Auto-Encoders, SAE)(2008)
降噪自編碼器的編解碼過程描述如圖:
堆疊降噪自編碼器與降噪自編碼器的區別在于:
1.堆疊降噪自編碼器采用了降噪編碼器的編碼器作為基礎單元,并且使用其訓練方法進行預訓練
2.降噪自動編碼器是無監督學習(自監督)的一種方法,而降噪自編碼器是一種有監督方法.
評價:
堆疊降噪自編碼器是降噪自編碼器的一個應用方法.
卷積自動編碼器(Convolution Auto-Encoders, CAE)(2011)
全卷積網絡是一種面向特定應用(圖像語義分割)的卷積神經網絡,其結構圖如下圖所示:
與經典的CNN在卷積層之后使用全連接層得到固定長度的特征向量進行分類(全聯接層+softmax輸出)不同,FCN可以接受任意尺寸的輸入圖像,采用反卷積層對最后一個卷積層的feature map進行上采樣, 使它恢復到輸入圖像相同的尺寸,從而可以對每個像素都產生了一個預測, 同時保留了原始輸入圖像中的空間信息, 最后在上采樣的特征圖上進行逐像素分類。
與全卷積網絡類似的一種無監督方法稱為卷機自動編碼器。
由于卷積神經網絡所取得的各種優異表現,直接推動了卷積自編碼器的產生。
卷積自編碼器屬于傳統自編碼器的一個特例,它使用卷積層和池化層替代了原來的全連接層,卷積自編碼器能很好的保留二維信號的空間信息。
評價:
其主要差別在于卷積自編碼器采用卷積方式對輸入信號進行線性變換,并且其權重是共享的,這點與卷積神經網絡一樣。因此,重建過程就是基于隱藏編碼的基本圖像塊的線性組合。
變分自動編碼器(Variational Auto-Encoders, VAE)(Kingma, 2014)
變分自編碼器是一種主要用于數據生成的自編碼器的變體.當作為生成模型時,首先利用數據訓練變分自編碼器,然后只使用變分自編碼器的解碼部分,自動生成與訓練數據類似的輸出.
其結構圖如圖所示:
整個結構可以分成三個部分,分別是編碼部分,解碼部分和生成部分.編碼部分和解碼部分同時進行訓練,目標函數是從KL散度的概念中推倒得到的.
loss函數的推導過程:
幾種算法的改進點表格
| 編碼器名稱 | 提出時間 | 改進點 | 目的 |
|---|---|---|---|
| 傳統自編碼器 | 1986 | 無 | 無 |
| 降噪自編碼器 | 2008 | 將帶有噪聲的損壞信息作為輸入信號 | 使重建信號魯棒性更強 |
| 堆疊自編碼器 | 2008 | 將多層結構和棧式訓練引入自編碼器 | 使自編碼器可以訓練更高層數 |
| 卷積自編碼器 | 2011 | 將卷積層引入自編碼器 | 更好的處理圖片數據,得到更好的效果 |
| 變分自編碼器 | 2014 | 相當于在傳統自編碼器的隱層表達上增加一個對隱變量的約束,提出了一種將概率模型和神經網絡結構的方法 | 使編碼器產生的隱層表達滿足正態分布,能夠更好的生成圖像模型 |
實現與Python實現
傳統的自動編碼器實驗結果
模型結構與實現代碼
傳統的自動編碼器分為編碼器部分和解碼器部分,整體模型結構如圖所示:
模型分為三個子模塊,由上至下分別為輸入層,編碼器層和解碼器層,編碼器將輸入維度為784(28 28)的mnint灰度值轉化為一個維度為2的值.編碼器將維度為2的值解碼回維度為784(28 28)的mnint灰度值.
python-keras代碼實現關鍵代碼如下
def __init__(self, ENCODING_DIM_INPUT=784, ENCODING_DIM_OUTPUT=2, Name = "ae"):
input_image = Input(shape=(ENCODING_DIM_INPUT, ))
# encoding layer
hidden_layer = Dense(ENCODING_DIM_OUTPUT, activation='relu')(input_image)
# decoding layer
decode_output = Dense(ENCODING_DIM_INPUT, activation='relu')(hidden_layer)
# build autoencoder, encoder, decoder
autoencoder = Model(inputs=input_image, outputs=decode_output)
encoder = Model(inputs=input_image, outputs=hidden_layer)
# compile autoencoder
autoencoder.compile(optimizer='adam', loss='mse', metrics=['accuracy'])
self.autoencoder = autoencoder
self.encoder = encoder
訓練過程
本實驗討論使用relu和tanh兩種激活函數的自監督訓練的情況.訓練的loss函數選擇為方均根誤差.
訓練過程的loss變化圖像如下.
使用tanh作為激活函數時,loss變化情況如下:
可以觀察到,loss收斂到0.0685,效果較好.使用relu作為激活函數同樣能夠有效收斂,不過誤差數值相對較大.由于篇幅原因不將圖片在此進行展示.
編碼器輸出的可視化結果
本節將從重建圖像和編碼器輸出層的二維可視化圖像兩部分進行展示,分別展示使用tanh和relu兩種損失函數的訓練結果.
訓練好的自動編碼器重建圖像(使用relu激活函數)如下圖:
訓練好的自動編碼器重建圖像(使用tanh激活函數)如下圖:
兩者對比可以發現relu函數訓練出的模型存在一些像素顆粒,這也驗證了上一節loss函數較大的實驗結果.為了解釋該問題,展示編碼器輸出層的二維可視化圖片.
訓練好的編碼器輸出圖像(使用relu激活函數)如下圖:
訓練好的編碼器輸出圖像(使用tanh激活函數)如下圖:
以上兩張圖片是 編碼器-解碼器 結構中編碼器部分的輸出繪制成的二維可視化圖片,不同的顏色代表了不同的數字,對應的數字在右邊的圖例中進行了顯示.從以上兩張圖片中可以得到:
1.由于relu函數對負數的截斷性質,使用relu激活函數訓練的模型中有一部分點被限制在x=0,y=0兩條邊緣線上,這也是上文中提到的訓練誤差較大和出現像素顆粒的原因.
2.自動編碼器雖然能夠對mnist數據集進行編碼和解碼,但是效果并沒有其改進的其他方法理想,這一觀點可以從解碼圖片較為模糊和編碼器可視化后各個類別的分類相重合得到驗證.
說明與討論
傳統自編碼器有很大的改進空間,改進空間的可以從幾個方面闡述:
1.解碼器輸出較為模糊
2.編碼器可視化的類別間的界限不明顯
堆疊降噪自編碼器
模型結構與實現代碼
傳統的自動編碼器分為編碼器部分和解碼器部分,整體模型結構如圖所示:
模型分為三個子模塊,由上至下分別為輸入層,多層編碼器層和多層解碼器層,編碼器將輸入維度為784(28 28)的mnint灰度值轉化為一個維度為2的值.編碼器將維度為2的值解碼回維度為784(28 28)的mnint灰度值
python-keras代碼實現關鍵代碼如下
class DAE(ae.AE):
def __init__(
self, ENCODING_DIM_INPUT=784, ENCODING_DIM_LAYER1=128,
ENCODING_DIM_LAYER2=64, ENCODING_DIM_LAYER3=10,
ENCODING_DIM_OUTPUT=2,Name="dae" ):
# input placeholder
input_image = Input(shape=(ENCODING_DIM_INPUT, ))
# encoding layer
encode_layer1 = Dense(ENCODING_DIM_LAYER1,
activation='relu')(input_image)
encode_layer2 = Dense(ENCODING_DIM_LAYER2,
activation='relu')(encode_layer1)
encode_layer3 = Dense(ENCODING_DIM_LAYER3,
activation='relu')(encode_layer2)
encode_output = Dense(ENCODING_DIM_OUTPUT)(encode_layer3)
# decoding layer
decode_layer1 = Dense(ENCODING_DIM_LAYER3,
activation='relu')(encode_output)
decode_layer2 = Dense(ENCODING_DIM_LAYER2,
activation='relu')(decode_layer1)
decode_layer3 = Dense(ENCODING_DIM_LAYER1,
activation='relu')(decode_layer2)
decode_output = Dense(ENCODING_DIM_INPUT,
activation='tanh')(decode_layer3)
# build surprised learning model
SL_output = Dense(10, activation='softmax')(encode_output)
# build autoencoder, encoder
autoencoder = Model(inputs=input_image, outputs=decode_output)
encoder = Model(inputs=input_image, outputs=encode_output)
SL_model = Model(inputs=input_image, outputs=SL_output)
# compile autoencoder
autoencoder.compile(optimizer='adam', loss='mse', metrics=['accuracy'])
SL_model.compile(optimizer='adam', loss='mse', metrics=['accuracy'])
代碼定義了三個模型,分別是用于自監督訓練的 autoencoder, 用于二維化的編碼器 encoder 和用于進行有監督訓練的 SL_model.
訓練過程
堆疊降噪自動編碼器分為無監督的預訓練過程和有監督的訓練過程兩部分.
本部分分別進行說明.
自監督的預訓練過程loss變化情況如下.
無監督的訓練過程正確率acc變化情況如下.
可以看到,在兩個訓練階段,方法可以有效的達到收斂.
以下幾點需要指出:
1.多層編碼器的訓練沒有使用棧式編碼器的訓練方式.
2.預訓練次數20epoch,并不足夠模型充分收斂,但是作為預訓練部分,已經充分.
3.預訓練部分的誤差與傳統自編碼器相比較大,是因為在初始層加入了噪聲的原因.
4.訓練時間與傳統編碼器相比更長,是其3倍左右.
5.在有監督學習的開始階段,分類的正確率并不高,這也印證了上一部分二位可視化的結果,很多點的界限不清晰.
編碼器輸出的可視化結果
本節將從重建圖像和編碼器輸出層的二維可視化圖像兩部分進行展示
預訓練部分
重建圖像
下圖展示了添加噪聲的效果(第一行原圖,第二行增加噪聲的圖).
下圖展示了,對添加噪聲的圖片進行重構的結果(第一行增加噪聲的圖,第二行重構圖)
編碼器輸出層的二維可視化圖像
下圖展示了添加噪聲的效果(第一行原圖,第二行增加噪聲的圖).
以下幾點需要指出:
1.本方法可以有效的對隨機噪聲進行去除
2.恢復圖與原圖相比雖然能夠識別但是效果更模糊
3.與傳統自動編碼器相比,本方法得到的二維圖的界限更加清晰
有監督訓練部分
經過有監督的訓練
重建圖像(因為不是目標,所以必然走樣)
下圖展示了,對添加噪聲的圖片進行重構的結果(第一行增加噪聲的圖,第二行重構圖)
編碼器輸出層的二維可視化圖像
經過有監督學習,二維可視化圖中各個組的界限更加清晰.
說明與討論
堆疊降噪自編碼器的改進有以下啟發:
1.使用自監督預訓練與有監督訓練方式相結合的形式獲得更加優秀的效果
2.使用增加噪聲的形式迫使模型學習更加有效的特征
3.將深度玻爾茲曼姬的思想遷移到自動編碼器中
卷積自編碼器
模型結構與實現代碼
卷積自編碼器自動編碼器分為編碼器部分和解碼器部分,整體模型結構如圖所示:
python-keras代碼實現關鍵代碼如下:
def __init__(self,CHANNEL_1 = 16,CHANNEL_2 = 8,CHANNEL_OUTPUT = 1, Name="cae"):
# input placeholder
input_image = Input(shape=(28, 28, 1))
# encoding layer
x = Conv2D(CHANNEL_1, (3, 3), activation='relu', padding="same")(input_image)
x = MaxPool2D((2, 2), padding='same')(x)
x = Conv2D(CHANNEL_2, (3, 3), activation='relu', padding='same')(x)
encode_output = MaxPool2D((2, 2), padding='same')(x)
# decoding layer
x = Conv2D(CHANNEL_2, (3, 3), activation='relu', padding='same')(encode_output)
x = UpSampling2D((2, 2))(x)
x = Conv2D(CHANNEL_1, (3, 3),activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
decode_output = Conv2D(CHANNEL_OUTPUT, (3, 3), activation='sigmoid', padding='same')(x)
# build surprised learning model
encode_output_flatten = Flatten()(decode_output)
SL_output = Dense(10, activation='softmax')(encode_output_flatten)
# build autoencoder, encoder
autoencoder = Model(inputs=input_image, outputs=decode_output)
encoder = Model(inputs=input_image, outputs=encode_output)
SL_model = Model(inputs=input_image, outputs=SL_output)
# compile autoencoder
autoencoder.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
SL_model.compile(optimizer='adam', loss='mse', metrics=['accuracy'])
訓練過程
堆疊降噪自動編碼器分為無監督的預訓練過程和有監督的訓練過程兩部分.
本部分分別進行說明.
在自監督的預訓練過程loss變化情況如下:
圖像顯示,自監督的訓練loss收斂于0.07左右,該誤差比降噪自編碼器的0.09要小.與傳統自編碼器的訓練誤差相差不多.但是從下文可知其訓練效果明顯優于傳統自動編碼器.
在有監督的訓練過程正確率acc變化情況如下:
圖像顯示,有監督訓練過程的正確率上升到0.99,比降噪自動編碼器的正確(0.95)率更高.
因此在mnist數據集中的重建任務和分類任務中,卷積自動編碼器有一定優勢.
不過以下幾點需要指出:
1.與sDAE相比,CAE有更高的準確率和更低的損失
2.更好的效果除了卷積單元能夠更好的處理圖像數據外,可能與CAE方法的復雜度更高和其瓶頸處通道更寬有關
編碼器輸出的可視化結果
可以看到和stacked AE的主要區別在于局部卷積連接,而不所有層都是全連接。對圖像和某些其他數據影響在空間局部的問題,比全連接更合適.因此效果更加優秀.
于降噪自動編碼器相同,首先對圖片增加噪聲:
然后對增加噪聲的圖片進行去噪:
去噪結果比較優秀,與上文中所有的結果相比是最優秀的.
變分自編碼器
模型結構與實現代碼
變分自動編碼器的結構最為復雜,并且在模型中引入了隱變量,和KL散度等概率論概念.對模型的實現造成了一定的影響.
自動編碼器分為編碼器部分和解碼器部分,整體模型結構如圖所示:
上圖中并沒有展開編碼器和解碼器的結構,編碼器(encoder) 與 解碼器(decoder)的形式分別如下:
encoder:
decoder:
python-keras代碼實現關鍵代碼如下:
class VAE(ae.AE):
def __init__(
self,
ENCODING_DIM_INPUT = 784,
intermediate_dim = 512,
batch_size = 128,
latent_dim = 2,
mse_loss = True,
Name="vae"
):
self.name = Name
# input placeholder
input_image = Input(shape=(ENCODING_DIM_INPUT,), name='encoder_input')
# VAE model = encoder + decoder
# encoding layer
x = Dense(intermediate_dim, activation='relu')(input_image)
z_mean = Dense(latent_dim, name='z_mean')(x)
z_log_var = Dense(latent_dim, name='z_log_var')(x)
z = Lambda(sampling, output_shape=(latent_dim,), name='z')([z_mean, z_log_var])
# build decoder model
latent_inputs = Input(shape=(latent_dim,), name='z_sampling')
x = Dense(intermediate_dim, activation='relu')(latent_inputs)
outputs = Dense(ENCODING_DIM_INPUT, activation='sigmoid')(x)
# # build surprised learning model
# SL_output = Dense(10, activation='softmax')()
# build autoencoder, encoder
encoder = Model(input_image, [z_mean, z_log_var, z], name='encoder')
decoder = Model(latent_inputs, outputs, name='decoder')
# SL_model = Model(inputs=input_image, outputs=SL_output)
outputs = decoder(encoder(input_image)[2])
autoencoder = Model(input_image, outputs, name='vae_mlp')
# compile autoencoder
# VAE loss = mse_loss or xent_loss + kl_loss
if mse_loss:
reconstruction_loss = mse(input_image, outputs)
else:
reconstruction_loss = binary_crossentropy(input_image,outputs)
reconstruction_loss *= ENCODING_DIM_INPUT
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)
autoencoder.add_loss(vae_loss)
autoencoder.compile(optimizer='adam')
autoencoder.summary()
# SL_model.compile(optimizer='adam', loss='mse', metrics=['accuracy'])
self.autoencoder = autoencoder
self.encoder = encoder
self.decoder = decoder
訓練過程
由于,變分自動編碼器主要應用于圖像生成,而并非是提取與分類,因此變分降噪自動編碼器只有自監督的訓練過程…
在自監督的訓練過程,使用 KL散度+交叉熵 作為loss函數,loss變化情況如下.
可以看散度可以收斂到145的情況,能夠有效進行收斂.
在自監督的訓練過程,使用 KL散度+方均根 作為loss函數,loss變化情況如下.
對于兩種損失函數效果的討論在下文中進行.
自編碼器輸出的可視化結果
使用 KL散度+交叉熵 作為損失函數
基于kl散度的loss訓練結果二維可視化如下
使用生成器對圖像進行生成可以得到如下結果.
使用 KL散度+方均根 作為損失函數
基于kl散度的loss訓練結果二維可視化如下
使用生成器對圖像進行生成可以得到如下結果.
由于方均根與交叉熵的區別在于 解碼器重現誤差上面的區別,在編碼器部分同樣使用kl散度作為loss,因此兩者的可視化結果類似.
以下幾點需要指出:
1.二維可視化的結果中各個類別的界限較為明顯,且其分布十分集中方便生成模型的圖像生成.
2.KL散度作為一種新的損失函數無法與其他方法的誤差進行對比.
討論
1.自動編碼器可能的應用有特征提取,圖像分類,圖像去燥,圖像生成等
2.在特征提取領域和圖像分類領域使用SAE有較優秀的效果
3.在圖像去噪領域可以使用cae方法,CAE方法對二維圖片的去燥效果十分優秀,但是由于中間部分是比較復雜的卷機核結構,無法進行有效的可視化
4.VAE方法在圖像生成領域有出色的表現,將中間的隱變量約束為正太分布的形式,十分方便的通過生成器完成圖像生成.
5.在研究角度,VAE方法將概率方法引入神經網絡的計算體系中,通過網絡完成對概率分布的映射,使用散度的概念構造損失函數,對其他研究有些啟發.
完成代碼
https://github.com/zangzelin/Auto-encoder-AE-SAE-DAE-CAE-DAE-with-keras-in-Mnist-and-report
總結
以上是生活随笔為你收集整理的详解自动编码器(AE)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何找到Fiori Launchpad
- 下一篇: 数仓分层理论_多元分层理论