何爲自編碼器
以下是來自TensorFlow實戰-黃文堅這本書。
這裏有一個自編碼器的思想來源,就是說雖然圖片,音頻,視頻千千萬,但是往往“表達”他們的基本機構是少數的一些基本固定的結構。稱爲特徵的稀疏表達。
這裏來解釋一下,自編碼器就是輸入的圖片不知道自己的基本結構是什麼的。需要不斷的訓練來近似得到基本結構。怎麼得到呢?就是把輸出也設置爲輸入的原圖像。使之不斷的優化以得到最佳的基本結構。一般自編碼器都是中間小,兩頭大的一個網絡結構。因爲中間的每一層表達的是“基本結構”。
如何實現
具體的實現形式有很多,比如簡單的三層網絡,深層網絡,卷積網絡等。
還可以把它應用到圖像去噪上面去。這時把輸入設置爲加噪的圖片,輸出設置爲未加燥的圖片,自編碼器依然要不斷的學習以獲得最佳的適合輸出的基本結構。這是前面說的升級版了。
下面是自編碼器應用於圖像去噪的例子:(CNN)
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
# 加載數據集
minst = tf.keras.datasets.mnist
(x_train, _), (x_test, _) = minst.load_data()
# 設置數據格式
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train = x_train/255
x_test = x_test/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 = 20
plt.figure(figsize=(60, 12)) # 指定寬爲20,高爲4
for i in range(1, 10):
ax = plt.subplot(2, n/2, i) # 表示將設置爲2行,n/2列,當前位置在i。
plt.imshow(x_train[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
ax = plt.subplot(2, n/2, 10+i)
plt.imshow(x_train_noisy[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
# 模型建立
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(filters=16, kernel_size=(3, 3), padding="same", activation=tf.nn.relu, input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"),
tf.keras.layers.Conv2D(filters=8, kernel_size=(3, 3), padding="same", activation=tf.nn.relu),
tf.keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"),
tf.keras.layers.Conv2D(filters=8, kernel_size=(3, 3), padding="same", activation=tf.nn.relu),
tf.keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"),
# encode 4,4,8
# let us decode
# 中間縮小到很小。。表達的是基本結構。
# 然後下面再給他還原回去。
tf.keras.layers.Conv2D(8, (3, 3), activation="relu", padding="same"),
tf.keras.layers.UpSampling2D((2, 2)),
tf.keras.layers.Conv2D(8, (3, 3), activation="relu", padding="same"),
tf.keras.layers.UpSampling2D((2, 2)),
tf.keras.layers.Conv2D(16, (3, 3), activation="relu"),
tf.keras.layers.UpSampling2D((2, 2)),
tf.keras.layers.Conv2D(1, (3, 3), activation="sigmoid", padding="same"),
])
learning_rate = 0.001
# 優化器
adam_optimizer = tf.keras.optimizers.Adam(learning_rate)
model.compile(optimizer=adam_optimizer, loss=tf.keras.losses.binary_crossentropy)
model.fit(x_train_noisy, x_train,
epochs=50, batch_size=128,
shuffle=True,
validation_data=(x_test_noisy, x_test),
)
decoded_imgs = model.predict(x_test_noisy)
n = 10
plt.figure(figsize=(20, 4))
for i in range(1, n):
# display original
ax = plt.subplot(2, n, i)
plt.imshow(x_test_noisy[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
# display reconstruction
ax = plt.subplot(2, n, i + 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()
效果:50輪,loss爲0.12左右。