1.前言
自編碼,簡單來說就是把輸入數據進行一個壓縮和解壓縮的過程。 原來有很多 Feature,壓縮成幾個來代表原來的數據,解壓之後恢復成原來的維度,再和原數據進行比較。
它是一種非監督算法,只需要輸入數據,解壓縮之後的結果與原數據本身進行比較。
今天要做的事情是把 datasets.mnist 數據的 28×28=784 維的數據,壓縮成 2 維的數據,然後在一個二維空間中可視化出分類的效果
2.用Keras搭建自編碼神經網絡
2.1.導入必要模塊
import numpy as np
from keras.datasets import mnist
from keras.models import Model
from keras.layers import Dense, Input
import matplotlib.pyplot as plt
np.random.seed(42)
2.2.數據預處理
x_train = x_train.astype('float')/255. - 0.5 #歸一化
x_test = x_test.astype('float')/255. - 0.5
x_train = x_train.reshape((x_train.shape[0],-1))
x_test = x_test.reshape((x_test.shape[0]),-1)
print(x_train.shape)
print(x_test.shape)
2.3.搭建模型
encoding_dim,要壓縮成的維度。
接下來是建立 encoded 和 decoded ,再用 autoencoder 把二者組建在一起。訓練時用 autoencoder。
encoded 用4層 Dense 全聯接層,激活函數用 relu,輸入的維度就是前一步定義的 input_img。
接下來定義下一層,它的輸出維度是64,輸入是上一層的輸出結果。
在最後一層,我們定義它的輸出維度就是想要的 encoding_dim=2。
解壓的環節,它的過程和壓縮的過程是正好相反的。相對應層的激活函數也是一樣的,不過在解壓的最後一層用到的激活函數是 tanh。 因爲輸入值是由 -0.5 到 0.5 這個範圍,在最後一層用這個激活函數的時候,它的輸出是 -1 到 1,可以是作爲一個很好的對應。
encoding_dim = 2
#自編碼器
input_img = Input(shape=(784,)) #返回一個張量
encoded = Dense(128,activation='relu')(input_img)
encoded = Dense(64,activation='relu')(encoded)
encoded = Dense(10,activation='relu')(encoded)
encoder_output = Dense(encoding_dim)(encoded)
decoded = Dense(10,activation='relu')(encoder_output)
decoded = Dense(64,activation='relu')(decoded)
decoded = Dense(128,activation='relu')(decoded)
decoded = Dense(784,activation='tanh')(decoded)
2.4.實例化並激活模型
接下來直接用 Model 這個模塊來組建模型,輸入就是圖片,輸出是解壓的最後的結果。
當我們想要看由 784 壓縮到 2維後,這個結果是什麼樣的時候,也可以只單獨組建壓縮的板塊,此時它的輸入是圖片,輸出是壓縮環節的最後結果。
接下來是編譯自編碼這個模型,優化器用的是 adam,損失函數用的是 mse。
autoencoder = Model(input = input_img, output=decoded) #實例化
encoder = Model(input=input_img, output=encoder_output)
autoencoder.compile(
optimizer = 'adam',
loss = 'mse'
)
2.5.訓練
接下來訓練自編碼模型,注意它的輸入和輸出是一樣的,都是訓練集的 X。
autoencoder.fit(x_train,x_train,
epochs = 20,
batch_size = 256,
shuffle = True)
2.6.可視化
最後看到可視化的結果,自編碼模型可以把這幾個數字給區分開來,我們可以用自編碼這個過程來作爲一個特徵壓縮的方法,和PCA的功能一樣,效果要比它好一些,因爲它是非線性的結構。
encoded_imgs = encoder.predict(x_test)
plt.scatter(encoded_imgs[:,0],encoded_imgs[:,1],c=y_test)
plt.colorbar()
plt.show()