深度學習 實驗八 自編碼器
一、問題描述
自編碼器是一種數據的壓縮算法,其中數據的壓縮和解壓縮函數有如下幾個特點:
1)數據相關的
2)有損的
3)從樣本中自動學習。
在大部分提到的自動編碼器的場合,壓縮和解壓縮的函數是通過神經網絡實現的。
搭建一個自動編碼器需要完成下面三項工作:搭建編碼器,搭建解碼器,設定一個損失函數,用以衡量由於壓縮而損失掉的信息。本實驗會通過搭建一個簡單的自編碼器觀測數據信息,並再搭建一個卷積自編碼器作爲對比,並學會使用自編碼器進行降噪。
二、設計簡要描述
1. 自編碼器
1.1 自編碼器簡介
1.2 搭建簡單的自編碼器模型
1.3 導入數據集
1.4 擬合模型
1.5 查看重構的輸出與原來的輸出對比
2. 卷積自編碼器
2.1 搭建卷積自編碼器
2.2加載數據並擬合模型
2.3查看重構的輸出與原來的輸出對比
3. 自編碼器的應用
3.1介紹
把訓練樣本用噪聲污染,然後使用解碼器解碼出乾淨的照片,以獲得去噪自動編碼器。
3.2 把原圖片加入高斯噪聲
3.3 構建自編碼器
參考2.1按如下步驟使用Keras函數模型搭建自編碼器並擬合
1)設置input_img參數
2)搭建編碼器,添加Conv2D層,輸入是input_img,輸出維度32,卷積核大小3×3,激活函數’‘relu’,padding設置爲‘same’,返回給x
3)添加Maxpooling2D層,大小是(2,2),padding設置爲‘same’
4)添加Conv2D層,輸出維度32,卷積核大小3×3,激活函數’‘relu’,padding設置爲‘same’
5)添加Maxpooling2D層,大小是(2,2),padding設置爲‘same’,返回給encoded
6)設置解碼器,添加Conv2D層,輸入是encoded,輸出維度32,卷積核大小3×3,激活函數’‘relu’,padding設置爲‘same’,返回給x
7)添加上採樣層,大小是(2,2)
8)添加Conv2D層,輸出維度32,卷積核大小3×3,激活函數’‘relu’,padding設置爲‘same’
9)添加上採樣層,大小是(2,2)
10)添加Conv2D層,輸入是encoded,輸出維度1,卷積核大小3×3,激活函數’‘sigmoid’,padding設置爲‘same’,返回給decoded
11)設置自編碼器,輸入是input_img,decoded
12)編譯自編碼器,參數不變。
13)擬合數據,參數與2.1節一致
3.4查看重構的輸出與原來的輸出對比
參考1.5節查看10張重構後的圖像與原圖像的對比
三、程序清單
# test8_自編碼器
# 1 自編碼器
# 1.1 自編碼器簡介
# 1.2 搭建簡單的自編碼器模型
from keras.layers import Input, Dense
from keras.models import Model
# 編碼器維度
encoding_dim = 32
input_img = Input(shape=(784,))
# "encoded" 是把輸入編碼表示
encoded = Dense(encoding_dim, activation='relu')(input_img)
# "decoded" 是輸入的有損重構
decoded = Dense(784, activation='sigmoid')(encoded)
# 搭建自編碼模型
autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
# 1.3 導入數據集
from keras.datasets import mnist
import numpy as np
(x_train, _), (x_test, _) = mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((len(x_train),np.prod(x_train.shape[1:])))
x_test =x_test.reshape((len(x_test), np.prod(x_test.shape[1:])))
print(x_train.shape)
print(x_test.shape)
# 1.4 擬合模型
# 通過以上數據擬合模型autoencoder
autoencoder.fit(x_train, x_train,
epochs=50,
batch_size=256,
shuffle=True,
validation_data=(x_test, x_test))
# 1.5 查看重構的輸出與原來的輸出對比
# 可以通過以下方式來查看
get_ipython().run_line_magic('matplotlib', 'inline')
# 從測試集選取一些數據來編碼和解碼
# encoded_imgs = autoencoder.predict(x_test)
decoded_imgs = autoencoder.predict(x_test)
import matplotlib.pyplot as plt
n = 10 # 打印的圖片數量
plt.figure(figsize=(20, 4))
for i in range(n):
# 顯示原來圖像
ax = plt.subplot(2, n, i + 1)
plt.imshow(x_test[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
# 顯示重構後的圖像
ax = plt.subplot(2, n, i + 1 + n)
plt.imshow(decoded_imgs[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
# 2 卷積自編碼器
# 2.1 搭建卷積自編碼器
# 創建如下的卷積編碼器和解碼器並編譯
from keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D
from keras.models import Model
from keras import backend as K
input_img = Input(shape=(28, 28, 1)) #輸入圖像形狀
#編碼器
x=Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)
#卷積層
x = MaxPooling2D((2, 2), padding='same')(x)#空域下采樣
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)
#解碼
x = Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = UpSampling2D((2, 2))(x)#上採樣層
x = Conv2D(8, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(16, (3, 3), activation='relu')(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)
autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')#編譯
# 2.2加載數據並擬合模型
# 參考1.3和1.4節加載數據並完成模型擬合
# x_train用reshape重構時參數設置爲x_train = np.reshape(x_train, (len(x_train), 28, 28, 1)) ,x_test類似
# autoencoder中的batch_size設置爲128,其他不變
from keras.datasets import mnist
import numpy as np
(x_train, _), (x_test, _) = mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))
x_test = np.reshape(x_test, (len(x_test), 28, 28, 1))
autoencoder.fit(x_train, x_train,
epochs=50,
batch_size=128,
shuffle=True,
validation_data=(x_test, x_test),)
# 2.3查看重構的輸出與原來的輸出對比
# 參考1.5節查看10張重構後的圖像與原圖像的對比
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
decoded_imgs = autoencoder.predict(x_test)
n = 10
plt.figure(figsize=(20, 4))
for i in range(n):
# 顯示原圖像
ax = plt.subplot(2, n, i+1)
plt.imshow(x_test[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
# 顯示重構後的圖像
ax = plt.subplot(2, n, i + n+1)
plt.imshow(decoded_imgs[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
# 3 自編碼器的應用
# 3.1介紹
# 把訓練樣本用噪聲污染,然後使用解碼器解碼出乾淨的照片,以獲得去噪自動編碼器。
# 3.2 把原圖片加入高斯噪聲
# 通過以下方式來加入噪聲並查看加噪後的圖片
from keras.datasets import mnist
import numpy as np
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
(x_train, _), (x_test, _) = mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))
x_test = np.reshape(x_test, (len(x_test), 28, 28, 1))
noise_factor = 0.5
x_train_noisy = x_train + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_train.shape)
x_test_noisy = x_test + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_test.shape)
x_train_noisy = np.clip(x_train_noisy, 0., 1.)
x_test_noisy = np.clip(x_test_noisy, 0., 1.)
n = 10
plt.figure(figsize=(20, 2))
for i in range(n):
ax = plt.subplot(1, n, i+1)
plt.imshow(x_test_noisy[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
# 3.3 構建自編碼器
# 參考2.1按如下步驟使用Keras函數模型搭建自編碼器並擬合
# 1)設置input_img參數
# 2)搭建編碼器,添加Conv2D層,輸入是input_img,輸出維度32,卷積核大小3×3,激活函數’‘relu’,padding設置爲‘same’,返回給x
# 3)添加Maxpooling2D層,大小是(2,2),padding設置爲‘same’
# 4)添加Conv2D層,輸出維度32,卷積核大小3×3,激活函數’‘relu’,padding設置爲‘same’
# 5)添加Maxpooling2D層,大小是(2,2),padding設置爲‘same’,返回給encoded
# 6)設置解碼器,添加Conv2D層,輸入是encoded,輸出維度32,卷積核大小3×3,激活函數’‘relu’,padding設置爲‘same’,返回給x
# 7)添加上採樣層,大小是(2,2)
# 8)添加Conv2D層,輸出維度32,卷積核大小3×3,激活函數’‘relu’,padding設置爲‘same’
# 9)添加上採樣層,大小是(2,2)
# 10)添加Conv2D層,輸入是encoded,輸出維度1,卷積核大小3×3,激活函數’‘sigmoid’,padding設置爲‘same’,返回給decoded
# 11)設置自編碼器,輸入是input_img,decoded
# 12)編譯自編碼器,參數不變。
# 13)擬合數據,參數與2.1節一致
from keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D
from keras.models import Model
from keras import backend as K
input_img = Input(shape=(28, 28, 1))
x = Conv2D(32, (3, 3), activation='relu', padding='same')(input_img)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)
autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
autoencoder.fit(x_train_noisy, x_train,
epochs=100,
batch_size=128,
shuffle=True,
validation_data=(x_test_noisy, x_test),)
# 3.4查看重構的輸出與原來的輸出對比
# 參考1.5節查看10張重構後的圖像與原圖像的對比
decoded_imgs = autoencoder.predict(x_test)
n = 10
plt.figure(figsize=(20, 4))
for i in range(n):
ax = plt.subplot(2, n, i + 1)
plt.imshow(x_test_noisy[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
ax = plt.subplot(2, n, i + n + 1)
plt.imshow(decoded_imgs[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
.reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
ax = plt.subplot(2, n, i + n + 1)
plt.imshow(decoded_imgs[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()