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

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

    具体效果如下:
    在这里插入图片描述

  • 下一步需要考虑如何建立模型,使得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()
    
    • 实验结果截图:
      在这里插入图片描述
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值