准备

用到的数据是MNIST,手写数字识别数据集,Keras中自带

训练集5W条,测试集1W条,都是 28 X 28 的灰度图

这里我们用jupyter notebook写代码,因为有些地方需要交互地进行展示

拖到最底下看最终效果


In [1]:
from keras.datasets import mnist
import numpy as np
import keras
import sys

import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logging.info(str("本次运行使用的包版本为:keras.__version__" + keras.__version__ + "np.__version__" + np.__version__ + "Python 版本为" + sys.version))


Using TensorFlow backend.
2018-10-24 15:21:44,173 - root - INFO - 本次运行使用的包版本为:keras.__version__2.2.4np.__version__1.15.3Python 版本为3.6.7 (v3.6.7:6ec5cf24b7, Oct 20 2018, 00:28:22) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]

In [2]:
logging.info('# 加载MNIST数据,不需要对应的标签,将像素值归一化到0至1,即张量,1表示颜色通道,即灰度图')

(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))


2018-10-24 15:21:44,187 - root - INFO - # 加载MNIST数据,不需要对应的标签,将像素值归一化到0至1,即张量,1表示颜色通道,即灰度图

In [3]:
logging.info('# 添加随机白噪声,并限制加噪后像素值仍处于0至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.)


2018-10-24 15:21:44,741 - root - INFO - # 添加随机白噪声,并限制加噪后像素值仍处于0至1之间

In [4]:
logging.info('# 看一下加噪后的效果')

import matplotlib.pyplot as plt
%matplotlib inline

n = 20
plt.figure(figsize=(20, 2))
for i in range(n):
    ax = plt.subplot(1, n, i + 1)
    plt.imshow(x_test_noisy[i*5+17].reshape(28, 28))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()


2018-10-24 15:21:48,699 - root - INFO - # 看一下加噪后的效果
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/matplotlib/font_manager.py:229: UserWarning: Matplotlib is building the font cache using fc-list. This may take a moment.
  'Matplotlib is building the font cache using fc-list. '
2018-10-24 15:22:00,443 - matplotlib.font_manager - INFO - Could not open font file /Library/Fonts/NISC18030.ttf

In [5]:
logging.info('# 定义模型的输入')

from keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D
from keras.models import Model, load_model

input_img = Input(shape=(28, 28, 1,))
logging.info('# 实现encoder部分,由两个 3 X 3 X 32 的卷积和两个 2 X 2 的最大池化组成')

x = Conv2D(32, (3, 3), padding='same', activation='relu')(input_img)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(32, (3, 3), padding='same', activation='relu')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)
logging.info('# 实现decoder部分,由两个 3 X 3 X 32 的卷积和两个 2 X 2 的上采样组成')

# 7 * 7 * 32
x = Conv2D(32, (3, 3), padding='same', activation='relu')(encoded)
x = UpSampling2D((2, 2))(x)
x = Conv2D(32, (3, 3), padding='same', activation='relu')(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(1, (3, 3), padding='same', activation='sigmoid')(x)
logging.info('# 将输入和输出连接,构成自编码器并compile')

autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
logging.info('# 使用x_train作为输入和输出进行训练,使用x_test进行校验')
logging.info('# 先训练5次看效果')

autoencoder.fit(x_train_noisy, x_train,
                epochs=5,
                batch_size=512,
                shuffle=True,
                validation_data=(x_test_noisy, x_test))
decoded_imgs = autoencoder.predict(x_test_noisy)

n = 20
plt.figure(figsize=(20, 4))
for i in range(n):
    # display original
    ax = plt.subplot(2, n, i + 1)
    plt.imshow(x_test_noisy[i*5+17].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 + 1 + n)
    plt.imshow(decoded_imgs[i*5+17].reshape(28, 28))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()


2018-10-24 15:22:04,261 - root - INFO - # 定义模型的输入
2018-10-24 15:22:04,315 - root - INFO - # 实现encoder部分,由两个 3 X 3 X 32 的卷积和两个 2 X 2 的最大池化组成
2018-10-24 15:22:04,409 - root - INFO - # 实现decoder部分,由两个 3 X 3 X 32 的卷积和两个 2 X 2 的上采样组成
2018-10-24 15:22:04,522 - root - INFO - # 将输入和输出连接,构成自编码器并compile
2018-10-24 15:22:04,591 - root - INFO - # 使用x_train作为输入和输出进行训练,使用x_test进行校验
2018-10-24 15:22:04,593 - root - INFO - # 先训练5次看效果
Train on 60000 samples, validate on 10000 samples
Epoch 1/5
60000/60000 [==============================] - 227s 4ms/step - loss: 0.2906 - val_loss: 0.1705
Epoch 2/5
60000/60000 [==============================] - 221s 4ms/step - loss: 0.1556 - val_loss: 0.1492
Epoch 3/5
60000/60000 [==============================] - 194s 3ms/step - loss: 0.1379 - val_loss: 0.1356
Epoch 4/5
60000/60000 [==============================] - 168s 3ms/step - loss: 0.1288 - val_loss: 0.1215
Epoch 5/5
60000/60000 [==============================] - 194s 3ms/step - loss: 0.1234 - val_loss: 0.1205

In [6]:
autoencoder.save('autoencoder.h5')

logging.info('''
# autoencoder.save('autoencoder.h5')
# 在CPU上训练比较慢,有条件的话可以用GPU,速度快上几十倍

# 这里将训练后的模型保存下来,之后或在其他地方都可以直接加载使用

# 使用自编码器对x_test_noisy预测,绘制预测结果,和原始加噪图像进行对比,便可以得到一开始的对比效果图

# autoencoder = load_model('autoencoder.h5')
''')
autoencoder = load_model('autoencoder.h5')


2018-10-24 15:39:03,399 - root - INFO - 
# autoencoder.save('autoencoder.h5')
# 在CPU上训练比较慢,有条件的话可以用GPU,速度快上几十倍

# 这里将训练后的模型保存下来,之后或在其他地方都可以直接加载使用

# 使用自编码器对x_test_noisy预测,绘制预测结果,和原始加噪图像进行对比,便可以得到一开始的对比效果图

# autoencoder = load_model('autoencoder.h5')


In [7]:
logging.info('# 再训练20次看效果')

autoencoder.fit(x_train_noisy, x_train,
                epochs=20,
                batch_size=512,
                shuffle=True,
                validation_data=(x_test_noisy, x_test))
decoded_imgs = autoencoder.predict(x_test_noisy)

n = 20
plt.figure(figsize=(20, 4))
for i in range(n):
    # display original
    ax = plt.subplot(2, n, i + 1)
    plt.imshow(x_test_noisy[i*5+17].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 + 1 + n)
    plt.imshow(decoded_imgs[i*5+17].reshape(28, 28))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()


2018-10-24 15:39:05,761 - root - INFO - # 再训练20次看效果
Train on 60000 samples, validate on 10000 samples
Epoch 1/20
60000/60000 [==============================] - 199s 3ms/step - loss: 0.1196 - val_loss: 0.1205
Epoch 2/20
60000/60000 [==============================] - 206s 3ms/step - loss: 0.1171 - val_loss: 0.1171
Epoch 3/20
60000/60000 [==============================] - 179s 3ms/step - loss: 0.1151 - val_loss: 0.1129
Epoch 4/20
60000/60000 [==============================] - 181s 3ms/step - loss: 0.1134 - val_loss: 0.1115
Epoch 5/20
60000/60000 [==============================] - 190s 3ms/step - loss: 0.1120 - val_loss: 0.1102
Epoch 6/20
60000/60000 [==============================] - 200s 3ms/step - loss: 0.1107 - val_loss: 0.1098
Epoch 7/20
60000/60000 [==============================] - 177s 3ms/step - loss: 0.1098 - val_loss: 0.1092
Epoch 8/20
60000/60000 [==============================] - 198s 3ms/step - loss: 0.1087 - val_loss: 0.1112
Epoch 9/20
60000/60000 [==============================] - 224s 4ms/step - loss: 0.1081 - val_loss: 0.1064
Epoch 10/20
60000/60000 [==============================] - 207s 3ms/step - loss: 0.1075 - val_loss: 0.1069
Epoch 11/20
60000/60000 [==============================] - 209s 3ms/step - loss: 0.1068 - val_loss: 0.1047
Epoch 12/20
60000/60000 [==============================] - 197s 3ms/step - loss: 0.1062 - val_loss: 0.1060
Epoch 13/20
60000/60000 [==============================] - 201s 3ms/step - loss: 0.1058 - val_loss: 0.1056
Epoch 14/20
60000/60000 [==============================] - 199s 3ms/step - loss: 0.1054 - val_loss: 0.1054
Epoch 15/20
60000/60000 [==============================] - 192s 3ms/step - loss: 0.1049 - val_loss: 0.1042
Epoch 16/20
60000/60000 [==============================] - 176s 3ms/step - loss: 0.1046 - val_loss: 0.1052
Epoch 17/20
60000/60000 [==============================] - 191s 3ms/step - loss: 0.1043 - val_loss: 0.1046
Epoch 18/20
60000/60000 [==============================] - 206s 3ms/step - loss: 0.1039 - val_loss: 0.1029
Epoch 19/20
60000/60000 [==============================] - 186s 3ms/step - loss: 0.1037 - val_loss: 0.1040
Epoch 20/20
60000/60000 [==============================] - 212s 4ms/step - loss: 0.1033 - val_loss: 0.1030