Deep Learning(深度学习)实验二:自编码器图像降噪

一、前期准备

  • 自编码器: 自编码器是神经网络的一种,经过训练后能够将输入复制到输出。该网络可以看到由两部分组成:一个由函数h=f(x)表示的编码器和一个生成重构的解码器r=g(h)。
  • 实现方法: 用CNN实现自编码器,通过学习从原始图片到加噪图片的映射,完成图像去噪任务。
  • 使用的数据集: MNIST(手写数字识别数据集)
  • 需要的包: Keras,数据集MNIST在Keras这个包里,而且这个包好像有点大,install用了一些时间。
  • np.clip: np.clip是一个截取函数,用于截取数组中小于或者大于某值的部分,并使得被截取部分等于固定值。np.clip(a, a_min, a_max, out=None) a:输入矩阵;
    a_min:被限定的最小值,所有比a_min小的数都会强制变为a_min;
    a_max:被限定的最大值,所有比a_max大的数都会强制变为a_max;
    out:可以指定输出矩阵的对象,shape与a相同
  • Feature Map: Feature Map是卷积核卷出来的,你用各种情况下的卷积核去乘以原图,会得到各种各样的feature map。你可以理解为你从多个角度去分析图片。而不同的特征提取(核)会提取不同的feature,模型想要达成的目的是解一个最优化,来找到能解释现象的最佳的一组卷积核。

二、具体实验过程

  • 导入需要用到的包:
from keras.datasets import mnist
import numpy as np
import matplotlib.pyplot as plt

这个降噪实验是基于mnist这个数据集来做的所有需要首先导入这个数据集。from keras.datasets import mnist

  • 加载MNIST数据,不需要对应的标签,所以只需要x不需要y,y表示图片上的数字具体是几
(x_train, _), (x_test, _) =mnist.load_data()
  • 将像素值归一化到0-1,因为像素值原本是0-255,所以除以255归一
x_train = x_train.astype('float32') / 255
x_test = x_test.astype('float32') / 255
  • 进行reshape,将其变成重塑为N128*28的四维tensor,x_train是原始数据 len(x_train)表示图片的个数 28表示高度 28表示宽度 1表示深度
x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))
x_test = np.reshape(x_test, (len(x_test), 28, 28, 1))
  • 添加白噪声,使得添加噪声后图片的像素值仍处在0~1之间,noise_factor = 0.5表示添加的噪声比例
noise_factor = 0.5
  • 噪声=原始数据+噪声比例*随机normal,loc=0.0均值是零,scale=1.0方差是1,size=x_train.reshape()数组大小和原始数据一样
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)
  • 通过clip函数保证数据范围是0~1,不能有负数
x_train_noisy = np.clip(x_train_noisy, 0., 1.)
x_test_noisy = np.clip(x_test_noisy, 0., 1.)
  • 用matplotlib来展示加噪后的效果
n = 10      # 图片个数为10
plt.figure(figsize=(20, 2))     # 图片size是20*2
for i in range(n):
    ax = plt.subplot(1, n, i+1)     # 1行 10列 获取第i+1个子图
    plt.imshow(x_test_noisy[i].reshape(28, 28))
    plt.gray()
    # 隐藏图片的x轴y轴
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()

具体效果如下:

AWGN 降噪 神经网络 matlab 神经网络降噪工具_数据集

  • 下一步需要考虑如何建立模型,使得x_train映射到x_train_noisy,x_test映射到x_test_noisy
  • 导入新的所需的包
    Input是输入层,Dense是全连接层,Conv2D是二维卷积,MaxPooling2D是二维池化,UpSampling2D是二维上采样
from keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D

load_model用于保存加载模型

from keras.models import Model, load_model
  • 在keras中,数据是以张量的形式表示的,张量的形状称之为shape,表示从最外层向量逐步到达最底层向量的降维解包过程。“维”的也叫“阶”,形状指的是维度数和每维的大小。比如,一个一阶的张量[1,2,3]的shape是(3,);一个二阶的张量[[1,2,3],[4,5,6]]的shape是(2,3);一个三阶的张量[[[1],[2],[3]],[[4],[5],[6]]]的shape是(2,3,1),input_shape就是指输入张量的shape。
  • (28, 28, 1,)表示(高度,宽度,深度,空出来的是不确定的数据个数)
input_img = Input(shape=(28, 28, 1,))
  • encoder部分:
  • Conv2D表示是二维的卷积,32表示tensor数组深度,(3, 3)表示卷积盒的大小,padding='same’表示卷积后图像尺寸不变,activation='relu’表示激活函数是relu,(input_img)表示输入
x = Conv2D(32, (3, 3), padding='same', activation='relu')(input_img)    # 图片规格:28*28*32
  • MaxPooling2D表示二维的最大池化,size为(2, 2),输入为(x)
x = MaxPooling2D((2, 2), padding='same')(x)     # 图片规格: 14*14*32
  • 二次卷积
x = Conv2D(32, (3, 3), padding='same', activation='relu')(x)        # 图片规格: 14*14*32
  • 最大池化赋值给encoded
encoded = MaxPooling2D((2, 2), padding='same')(x)       # 图片规格: 7*7*32
  • decoder部分:
  • 上面的图片规格传下来是:7732
x = Conv2D(32, (3, 3), padding='same', activation='relu')(encoded)       # 图片规格: 7*7*32
  • UpSampling2D表示上采样,与MaxPooling2D是相反的作用
x = UpSampling2D((2, 2))(x)        # 图片规格: 14*14*32
x = Conv2D(32, (3, 3), padding='same', activation='relu')(x)        # 图片规格: 14*14*32
x = UpSampling2D((2, 2))(x)          # 图片规格:28*28*32
decoded = Conv2D(1, (3, 3), padding='same', activation='sigmoid')(x)          # 图片规格:28*28*1
  • 将输入和输出连接,构成自编码器并compile
    input_img是整个模型的input,decoded是整个模型的output
autoencoder = Model(input_img, decoded)
  • optimizer:优化函数,loss:损失函数
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
  • # 用x_train作为输入和输出进行训练,用x_test进行校验
    x_train_noisy:输入,x_train:输出,epochs=100训练一百轮迭代,shuffle=True:训练后随机打乱
autoencoder.fit(x_train_noisy, x_train,
                epochs=100,
                batch_size=128,
                shuffle=True,
                validation_data=(x_test_noisy, x_test))
  • 将训练后的模型保存下来
autoencoder.save('autoencoder1.h5')
autoencoder = load_model('autoencoder1.h5')
decoded_imgs = autoencoder.predict(x_test_noisy)
  • 图片展示
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+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()
  • 实验结果截图:

AWGN 降噪 神经网络 matlab 神经网络降噪工具_AWGN 降噪 神经网络 matlab_02