自動編碼(AE)器的簡單實現

自動編碼(AE,DAE,CAE,SAE)器的方法介紹與簡單實現(附代碼)

一.目錄

二.自動編碼器的發展簡述

2.1 自動編碼器(Auto-Encoders,AE)

傳統的自動編碼器是一種數據的壓縮算法,其算法包括編碼階段和解碼階段,且擁有對稱的結構。
目前自編碼器的應用主要有兩個方面,第一是數據去噪,第二是爲進行可視化而降維。配合適當的維度和稀疏約束,自編碼器能夠學習到比PCA等技術更有意思的數據投影。編碼

傳統編碼器的編解碼過程描述如圖:url

自動編碼器的訓練過程使用傳統的基於梯度的方式進行訓練。spa

評價:

學界評價:傳統自編碼器的目的是使輸出與輸入儘可能相同,這徹底能夠經過學習兩個恆等函數來完成,可是這樣的變換沒有任何意義,由於咱們真正關心的是隱層表達,而不是實際輸出。所以,針對自編碼器的不少改進方法都是對隱層表達增長必定的約束,迫使隱層表達與輸入不一樣。

2.2 降噪自編碼(Denoising Auto-Encoders, DAE)(2008)

自編碼器真正關心的是隱藏層的特徵表達,一個好的表達可以捕獲輸入信號的穩定結構,以該目的爲出發出現了降噪自動編碼器。降噪自動編碼器,首先對乾淨的輸入信號加入噪聲產生一個受損的信號。而後將受損信號送入傳統的自動編碼器中,使其重建回原來的無損信號。

降噪自編碼器的編解碼過程描述如圖:

降噪自編碼器的目標是最小化損失函數。

降噪自編碼器與傳統的自動編碼器的主要區別在於:

  1. 降噪自編碼器經過人爲的增長噪聲使模型得到魯棒性的特徵表達
  2. 避免使隱層單元學習一個傳統自編碼器中沒有意義的恆等函數

評價:

學界評價:降噪自編碼器經過對輸入信號人爲地進行損壞,主要是爲了達到兩個目的,首先是爲了不使隱層單元學習一個傳統自編碼器中沒有實際意義的恆等函數,其次就是爲了使隱層單元能夠學習到一個更加具備魯棒性的特徵表達。
降噪自編碼器最大的優勢在於,重建信號對輸入中的噪聲具備必定的魯棒性,而最大的缺陷在於每次進行網絡訓練以前,都須要對乾淨輸入信號人爲地添加噪聲,以得到它的損壞信號,這無形中就增長了該模型的處理時間。

2.3 堆疊降燥自動編碼器 (Stacked Denoising Auto-Encoders, SAE)(2008)

參考深度置信網絡的方法,將降噪自編碼器進行堆疊能夠構形成堆疊降噪自編碼器。與自編碼器和降噪自編碼器不一樣,堆疊降噪自編碼器的提出是爲了解決。

降噪自編碼器的編解碼過程描述如圖:

其中,編碼器分別對應的是預先訓練好的降噪自編碼器的編碼函數.

每一個子問題的訓練過程與降噪自編碼器自編碼器相同.

整個堆疊降噪自編碼器的訓練過程以下:

  • 乾淨輸入輸入
  • 加入噪聲,和與對應的解碼器使用降噪自編碼器的方式訓練.
  • 固定,以與步驟2相同的方式訓練到,並在最後一層加入分類器
  • 利用的真實標籤和預測得到的標籤進行有監督學習.對整個網絡參數進行進一步的微調.

其中爲噪聲的分佈, 爲加入噪聲後的輸入, 爲編碼的權重和偏置,爲解碼的權重和偏置。

堆疊降噪自編碼器與降噪自編碼器的區別在於:

  1. 堆疊降噪自編碼器採用了降噪編碼器的編碼器做爲基礎單元,而且使用其訓練方法進行預訓練
  2. 降噪自動編碼器是無監督學習(自監督)的一種方法,而降噪自編碼器是一種有監督方法.

評價:

學界評價:堆疊降噪自編碼器是降噪自編碼器的一個應用方法.

2.4 卷積自動編碼器(Convolution Auto-Encoders, CAE)(2011)

全卷積網絡是一種面向特定應用(圖像語義分割)的卷積神經網絡,其結構圖以下圖所示:

與經典的CNN在卷積層以後使用全鏈接層獲得固定長度的特徵向量進行分類(全聯接層+softmax輸出)不一樣,FCN能夠接受任意尺寸的輸入圖像,採用反捲積層對最後一個卷積層的feature map進行上採樣, 使它恢復到輸入圖像相同的尺寸,從而能夠對每一個像素都產生了一個預測, 同時保留了原始輸入圖像中的空間信息, 最後在上採樣的特徵圖上進行逐像素分類。

與全卷積網絡相似的一種無監督方法稱爲卷機自動編碼器.

因爲卷積神經網絡所取得的各類優異表現,直接推進了卷積自編碼器的產生.卷積自編碼器屬於傳統自編碼器的一個特例.它使用卷積層和池化層替代了原來的全鏈接層.卷積
自編碼器能很好的保留二維信號的空間信息.

學界評價:其主要差異在於卷積自編碼器採用卷積方式對輸入信號進行線性變換,而且其權重是共享的,這點與卷積神經網絡同樣。所以,重建過程就是基於隱藏編碼的基本圖像塊的線性組合。

我實現後的感覺:

2.5 變分自動編碼器(Variational Auto-Encoders, VAE)(Kingma, 2014)

變分自編碼器是一種主要用於數據生成的自編碼器的變體.看成爲生成模型時,首先利用數據訓練變分自編碼器,而後只使用變分自編碼器的解碼部分,自動生成與訓練數據相似的輸出.

其結構圖如圖所示:

整個結構能夠分紅三個部分,分別是編碼部分,解碼部分和生成部分.編碼部分和解碼部分同時進行訓練,目標函數是從KL散度的概念中推倒獲得的.

其中表明瞭輸入數據,表明了隱變量(latent varibles)(一個相似隱層輸出的機率描述),
變分編碼器的目標能夠描述爲最大化生成的機率

其中  爲模型的參數,也是優化的對象.通常選取

loss函數的推導過程:

首先咱們但願編碼器部分生成的隨機變量與理想的儘可能接近,所以使用KL散度的概念對兩個隨機變量的類似性進行描述.

其中,爲散度符號.利用貝葉斯公式將上述公式展開獲得:

通過變換能夠獲得:

該公式正好是變分自編碼器的目標函數.目標函數能夠分紅兩個部分,分別約束了中間的隱變量受到一個標準分佈的約束和輸出圖像儘可能與原圖相同.

2.5 幾種算法的改進點表格

編碼器名稱 提出時間 改進點 目的
傳統自編碼器 1986
降噪自編碼器 2008 將帶有噪聲的損壞信息做爲輸入信號 使重建信號魯棒性更強
堆疊自編碼器 2008 將多層結構和棧式訓練引入自編碼器 使自編碼器能夠訓練更高層數
卷積自編碼器 2011 將卷積層引入自編碼器 更好的處理圖片數據,獲得更好的效果
變分自編碼器 2014 至關於在傳統自編碼器的隱層表達上增長一個對隱變量的約束,提出了一種將機率模型和神經網絡結構的方法 使編碼器產生的隱層表達知足正態分佈,可以更好的生成圖像模型

三. 實驗

3.1 傳統的自動編碼器實驗結果

模型結構與實現代碼

傳統的自動編碼器分爲編碼器部分和解碼器部分,總體模型結構如圖所示:

模型分爲三個子模塊,由上至下分別爲輸入層,編碼器層和解碼器層,編碼器將輸入維度爲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. 編碼器可視化的類別間的界限不明顯

3.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. 將深度玻爾茲曼姬的思想遷移到自動編碼器中

3.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的主要區別在於局部卷積鏈接,而不全部層都是全鏈接。對圖像和某些其餘數據影響在空間局部的問題,比全鏈接更合適.所以效果更加優秀.

於降噪自動編碼器相同,首先對圖片增長噪聲:

而後對增長噪聲的圖片進行去噪:

去噪結果比較優秀,與上文中全部的結果相比是最優秀的.

3.4 變分自編碼器

模型結構與實現代碼

變分自動編碼器的結構最爲複雜,而且在模型中引入了隱變量,和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方法將機率方法引入神經網絡的計算體系中,經過網絡完成對機率分佈的映射,使用散度的概念構造損失函數,對其餘研究有些啓發.

原文連接 本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索