自動編碼(AE)器的簡單實現python
傳統的自動編碼器是一種數據的壓縮算法,其算法包括編碼階段和解碼階段,且擁有對稱的結構。
目前自編碼器的應用主要有兩個方面,第一是數據去噪,第二是爲進行可視化而降維。配合適當的維度和稀疏約束,自編碼器能夠學習到比PCA等技術更有意思的數據投影。編碼
傳統編碼器的編解碼過程描述如圖:url
自動編碼器的訓練過程使用傳統的基於梯度的方式進行訓練。spa
評價:
學界評價:傳統自編碼器的目的是使輸出與輸入儘可能相同,這徹底能夠經過學習兩個恆等函數來完成,可是這樣的變換沒有任何意義,由於咱們真正關心的是隱層表達,而不是實際輸出。所以,針對自編碼器的不少改進方法都是對隱層表達增長必定的約束,迫使隱層表達與輸入不一樣。
自編碼器真正關心的是隱藏層的特徵表達,一個好的表達可以捕獲輸入信號的穩定結構,以該目的爲出發出現了降噪自動編碼器。降噪自動編碼器,首先對乾淨的輸入信號加入噪聲產生一個受損的信號。而後將受損信號送入傳統的自動編碼器中,使其重建回原來的無損信號。
降噪自編碼器的編解碼過程描述如圖:
降噪自編碼器的目標是最小化損失函數。
降噪自編碼器與傳統的自動編碼器的主要區別在於:
評價:
學界評價:降噪自編碼器經過對輸入信號人爲地進行損壞,主要是爲了達到兩個目的,首先是爲了不使隱層單元學習一個傳統自編碼器中沒有實際意義的恆等函數,其次就是爲了使隱層單元能夠學習到一個更加具備魯棒性的特徵表達。
降噪自編碼器最大的優勢在於,重建信號對輸入中的噪聲具備必定的魯棒性,而最大的缺陷在於每次進行網絡訓練以前,都須要對乾淨輸入信號人爲地添加噪聲,以得到它的損壞信號,這無形中就增長了該模型的處理時間。
參考深度置信網絡的方法,將降噪自編碼器進行堆疊能夠構形成堆疊降噪自編碼器。與自編碼器和降噪自編碼器不一樣,堆疊降噪自編碼器的提出是爲了解決。
降噪自編碼器的編解碼過程描述如圖:
其中,編碼器分別對應的是預先訓練好的降噪自編碼器的編碼函數.
每一個子問題的訓練過程與降噪自編碼器自編碼器相同.
整個堆疊降噪自編碼器的訓練過程以下:
其中爲噪聲的分佈, 爲加入噪聲後的輸入, 爲編碼的權重和偏置,爲解碼的權重和偏置。
堆疊降噪自編碼器與降噪自編碼器的區別在於:
評價:
學界評價:堆疊降噪自編碼器是降噪自編碼器的一個應用方法.
全卷積網絡是一種面向特定應用(圖像語義分割)的卷積神經網絡,其結構圖以下圖所示:
與經典的CNN在卷積層以後使用全鏈接層獲得固定長度的特徵向量進行分類(全聯接層+softmax輸出)不一樣,FCN能夠接受任意尺寸的輸入圖像,採用反捲積層對最後一個卷積層的feature map進行上採樣, 使它恢復到輸入圖像相同的尺寸,從而能夠對每一個像素都產生了一個預測, 同時保留了原始輸入圖像中的空間信息, 最後在上採樣的特徵圖上進行逐像素分類。
與全卷積網絡相似的一種無監督方法稱爲卷機自動編碼器.
因爲卷積神經網絡所取得的各類優異表現,直接推進了卷積自編碼器的產生.卷積自編碼器屬於傳統自編碼器的一個特例.它使用卷積層和池化層替代了原來的全鏈接層.卷積
自編碼器能很好的保留二維信號的空間信息.
學界評價:其主要差異在於卷積自編碼器採用卷積方式對輸入信號進行線性變換,而且其權重是共享的,這點與卷積神經網絡同樣。所以,重建過程就是基於隱藏編碼的基本圖像塊的線性組合。
我實現後的感覺:
變分自編碼器是一種主要用於數據生成的自編碼器的變體.看成爲生成模型時,首先利用數據訓練變分自編碼器,而後只使用變分自編碼器的解碼部分,自動生成與訓練數據相似的輸出.
其結構圖如圖所示:
整個結構能夠分紅三個部分,分別是編碼部分,解碼部分和生成部分.編碼部分和解碼部分同時進行訓練,目標函數是從KL散度的概念中推倒獲得的.
其中表明瞭輸入數據,表明了隱變量(latent varibles)(一個相似隱層輸出的機率描述),
變分編碼器的目標能夠描述爲最大化生成的機率
其中 爲模型的參數,也是優化的對象.通常選取
loss函數的推導過程:
首先咱們但願編碼器部分生成的隨機變量與理想的儘可能接近,所以使用KL散度的概念對兩個隨機變量的類似性進行描述.
其中,爲散度符號.利用貝葉斯公式將上述公式展開獲得:
通過變換能夠獲得:
該公式正好是變分自編碼器的目標函數.目標函數能夠分紅兩個部分,分別約束了中間的隱變量受到一個標準分佈的約束和輸出圖像儘可能與原圖相同.
編碼器名稱 | 提出時間 | 改進點 | 目的 |
---|---|---|---|
傳統自編碼器 | 1986 | 無 | 無 |
降噪自編碼器 | 2008 | 將帶有噪聲的損壞信息做爲輸入信號 | 使重建信號魯棒性更強 |
堆疊自編碼器 | 2008 | 將多層結構和棧式訓練引入自編碼器 | 使自編碼器能夠訓練更高層數 |
卷積自編碼器 | 2011 | 將卷積層引入自編碼器 | 更好的處理圖片數據,獲得更好的效果 |
變分自編碼器 | 2014 | 至關於在傳統自編碼器的隱層表達上增長一個對隱變量的約束,提出了一種將機率模型和神經網絡結構的方法 | 使編碼器產生的隱層表達知足正態分佈,可以更好的生成圖像模型 |
傳統的自動編碼器分爲編碼器部分和解碼器部分,總體模型結構如圖所示:
模型分爲三個子模塊,由上至下分別爲輸入層,編碼器層和解碼器層,編碼器將輸入維度爲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激活函數)以下圖:
以上兩張圖片是 編碼器-解碼器 結構中編碼器部分的輸出繪製成的二維可視化圖片,不一樣的顏色表明了不一樣的數字,對應的數字在右邊的圖例中進行了顯示.從以上兩張圖片中能夠獲得:
傳統自編碼器有很大的改進空間,改進空間的能夠從幾個方面闡述:
傳統的自動編碼器分爲編碼器部分和解碼器部分,總體模型結構如圖所示:
模型分爲三個子模塊,由上至下分別爲輸入層,多層編碼器層和多層解碼器層,編碼器將輸入維度爲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變化狀況以下.
能夠看到,在兩個訓練階段,方法能夠有效的達到收斂.
如下幾點須要指出:
本節將從重建圖像和編碼器輸出層的二維可視化圖像兩部分進行展現
預訓練部分
重建圖像
下圖展現了添加噪聲的效果(第一行原圖,第二行增長噪聲的圖).
下圖展現了,對添加噪聲的圖片進行重構的結果(第一行增長噪聲的圖,第二行重構圖)
編碼器輸出層的二維可視化圖像
下圖展現了添加噪聲的效果(第一行原圖,第二行增長噪聲的圖).
如下幾點須要指出:
有監督訓練部分
通過有監督的訓練
重建圖像(由於不是目標,因此必然走樣)
下圖展現了,對添加噪聲的圖片進行重構的結果(第一行增長噪聲的圖,第二行重構圖)
編碼器輸出層的二維可視化圖像
通過有監督學習,二維可視化圖中各個組的界限更加清晰.
堆疊降噪自編碼器的改進有如下啓發:
卷積自編碼器自動編碼器分爲編碼器部分和解碼器部分,總體模型結構如圖所示:
使用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數據集中的重建任務和分類任務中,卷積自動編碼器有必定優點.
不過如下幾點須要指出:
能夠看到和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,所以二者的可視化結果相似.
如下幾點須要指出:
原文連接 本文爲雲棲社區原創內容,未經容許不得轉載。