乐趣区

关于人工智能:用深度卷积自编码器在10分钟内降低图像噪声

作者 |Orhan Gazi Yalçınv
编译 |VK
起源 |Towards Datas Science

你可能对不同的神经网络构造有点相熟。你可能据说过前馈神经网络,CNNs,RNNs,这些神经网络对于解决诸如回归和分类之类的监督学习工作十分有用。

然而,在无监督学习畛域,咱们面临着大量的问题,如降维、特征提取、异样检测、数据生成、加强以及噪声克制等。对于这些工作,咱们须要非凡的神经网络的帮忙,这些神经网络是专门为无监督学习工作而开发的。

因而,他们必须可能在不须要监督的状况下训练进去。其中一种非凡的神经网络构造是自编码器。

自编码器

什么是自编码器?

自编码器是一种神经网络构造,它由两个子网络组成,即编码和解码网络,它们之间通过一个潜在空间相互连接。

自编码器最早由杰弗里·辛顿(Geoffrey Hinton)和 PDP 小组在 20 世纪 80 年代开发。Hinton 和 PDP 小组的指标是解决“没有老师的反向流传”问题,即无监督学习,将输出作为老师。换句话说,他们只是简略地将特色数据用作特色数据和标签数据。让咱们认真看看自编码器是如何工作的!

自编码器体系结构

自编码器由一个编码器网络组成,该网络接管特色数据并对其进行编码以适应潜在空间。解码器应用该编码数据(即代码)将其转换回特色数据。在编码器中,模型学习的是如何无效地编码数据,以便解码器可能将其转换回原始数据。因而,自编码器训练的要害是生成一个优化的潜在空间。

当初,要晓得在大多数状况下,潜在空间中的神经元数量要比输出层和输入层小得多,但不肯定要这样。有不同类型的自编码器,如欠齐备、过齐备、稠密、去噪、压缩和变分自编码器。在本教程中,咱们只关注用于去噪的欠齐备自编码器。

自编码器中的层

构建自编码器时的规范做法是设计一个编码器并创立该网络的反向版本作为该自编码器的解码器。因而,只有编码器和解码器网络之间存在反向关系,你就能够自在地向这些子网络增加任何层。例如,如果你解决的是图像数据,你必定须要卷积和池层。另一方面,如果要解决序列数据,则可能须要 LSTM、GRU 或 RNN 单元。这里重要的一点是,你能够自在地构建任何你想要的货色。

当初,你曾经有了能够构建图像降噪的自编码器的想法,咱们能够持续学习教程,开始为图像降噪模型编写代码。在本教程中,咱们抉择应用 TensorFlow 的官网教程之一《Autoencoders 简介》[1],咱们将应用 AI 社区成员中十分风行的数据集:Fashion MNIST。

下载 Fashion MNIST 数据集

Fashion MNIST 由德国柏林的欧洲电子商务公司 Zalando 设计和保护。Fashion MNIST 由 60000 个图像的训练集和 10000 个图像的测试集组成。每个例子是一个 28×28 的灰度图像,与来自 10 个类的标签相关联。

Fashion MNIST 蕴含服装的图像(如图所示),被设计为 MNIST 数据集的代替数据集,MNIST 数据集蕴含手写数字。咱们抉择 Fashion MNIST 仅仅是因为 MNIST 在许多教程中曾经被适度应用。

上面的行导入 TensorFlow 和 load Fashion MNIST:

import tensorflow as tf
from tensorflow.keras.datasets import fashion_mnist
# 咱们不须要 y_train 和 y_test
(x_train, _), (x_test, _) = fashion_mnist.load_data()
print('Max value in the x_train is', x_train[0].max())
print('Min value in the x_train is', x_train[0].min())

当初,让咱们应用数据集中的示例生成一个网格,其中蕴含以下行:

import matplotlib.pyplot as plt

fig, axs = plt.subplots(5, 10) 
fig.tight_layout(pad=-1)
plt.gray()
a = 0 
for i in range(5): 
  for j in range(10): 
    axs[i, j].imshow(tf.squeeze(x_test[a])) 
    axs[i, j].xaxis.set_visible(False) 
    axs[i, j].yaxis.set_visible(False) 
    a = a + 1 

咱们的输入显示了测试数据集的前 50 个样本:

解决 Fashion MNIST 数据

为了进步计算效率和模型可靠性,咱们必须对图像数据利用 Minmax 规范化,将值范畴限度在 0 到 1 之间。因为咱们的数据是 RGB 格局的,所以最小值为 0,最大值为 255,咱们能够应用以下代码进行最小最大规格化操作:

x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.

咱们还必须扭转 NumPy 数组维度,因为数据集的以后形态是(60000,28,28)和(10000,28,28)。咱们只须要增加一个繁多值的第四个维度(例如,从(60000,28,28)到(60000,28,28,1))。

第四维简直能够证实咱们的数据是灰度格局的。如果咱们有彩色图像,那么咱们须要在第四维中有三个值。然而咱们只须要一个蕴含繁多值的第四维度,因为咱们应用灰度图像。以下几行代码能够做到这一点:

x_train = x_train[…, tf.newaxis]
x_test = x_test[…, tf.newaxis]

让咱们通过以下几行来看看 NumPy 数组的形态:

print(x_train.shape)
print(x_test.shape)

输入 :(60000,28,1)和(10000,28,28,1)

给图像增加噪声

记住咱们的指标是建设一个模型,它可能对图像进行降噪解决。为了做到这一点,咱们将应用现有的图像数据并将它们增加到随机噪声中。

而后,咱们将原始图像作为输出,噪声图像作为输入。咱们的自编码器将学习洁净的图像和有噪声的图像之间的关系,以及如何革除有噪声的图像。

因而,让咱们创立一个有噪声的版本。

对于这个工作,咱们应用 tf.random.normal 办法。而后,咱们用一个噪声系数乘以随机值,你能够随便应用它。以下代码为图像增加噪声:

noise_factor = 0.4
x_train_noisy = x_train + noise_factor * tf.random.normal(shape=x_train.shape) 
x_test_noisy = x_test + noise_factor * tf.random.normal(shape=x_test.shape)

咱们还须要确保数组项的值在 0 到 1 的范畴内。为此,咱们能够应用 tf.clip_by_value 办法。clip_by_value 是一种 TensorFlow 办法,它将“最小值 - 最大值”范畴之外的值剪裁并替换为指定的“最小值”或“最大值”。以下代码剪辑超出范围的值:

x_train_noisy = tf.clip_by_value(x_train_noisy, clip_value_min=0., clip_value_max=1.) 
x_test_noisy = tf.clip_by_value(x_test_noisy, clip_value_min=0., clip_value_max=1.)

当初,咱们曾经创立了数据集的规则化和噪声版本,咱们能够查看它的外观:

n = 5
plt.figure(figsize=(20, 8))
plt.gray()
for i in range(n):
  ax = plt.subplot(2, n, i + 1) 
  plt.title("original", size=20) 
  plt.imshow(tf.squeeze(x_test[i])) 
  plt.gray() 
  bx = plt.subplot(2, n, n+ i + 1) 
  plt.title("original + noise", size=20) 
  plt.imshow(tf.squeeze(x_test_noisy[i])) 
plt.show()

正如你所见,在嘈杂的图像中简直不可能了解咱们所看到的。然而,咱们的自编码器将神奇地学会清洁它。

建设咱们的模型

在 TensorFlow 中,除了程序 API 和函数 API 之外,还有第三种办法来构建模型:模型子类化。在模型子类化中,咱们能够自在地从零开始实现所有。

模型子类化是齐全可定制的,使咱们可能实现本人的定制模型。这是一个十分弱小的办法,因为咱们能够建设任何类型的模型。然而,它须要根本的面向对象编程常识。咱们的自定义类是 tf.keras.Model 对象。它还须要申明几个变量和函数。

另外请留神,因为咱们解决的是图像数据,因而构建一个卷积式自编码器更为无效,如下所示:

要构建模型,咱们只需实现以下工作:

  • 创立一个扩大 keras.Model 的对象
  • 创立一个函数来申明两个用程序 API 构建的独立模型。在它们中,咱们须要申明互相颠倒的层。一个 Conv2D 层用于编码器模型,而一个 Conv2DTranspose 层用于解码器模型。
  • 应用 __init__ 办法创立一个 call 函数,通知模型如何应用初始化的变量来解决输出
  • 咱们须要调用以图像为输出的初始化编码器模型
  • 咱们还须要调用以编码器模型(encoded)的输入作为输出的初始化解码器模型
  • 返回解码器的输入

咱们能够通过以下代码实现所有这些指标:

from tensorflow.keras.layers import Conv2DTranspose, Conv2D, Input

class NoiseReducer(tf.keras.Model): 
  def __init__(self):

    super(NoiseReducer, self).__init__() 

    self.encoder = tf.keras.Sequential([Input(shape=(28, 28, 1)), 
      Conv2D(16, (3,3), activation='relu', padding='same', strides=2), 
      Conv2D(8, (3,3), activation='relu', padding='same', strides=2)]) 
    
    self.decoder = tf.keras.Sequential([Conv2DTranspose(8, kernel_size=3, strides=2, activation='relu', padding='same'), 
      Conv2DTranspose(16, kernel_size=3, strides=2, activation='relu', padding='same'), 
      Conv2D(1, kernel_size=(3,3), activation='sigmoid', padding='same')]) 
  
  def call(self, x): 
    encoded = self.encoder(x) 
    decoded = self.decoder(encoded) 
    return decoded

让咱们用一个对象调用来创立模型:

autoencoder = NoiseReducer()

配置咱们的模型

对于这个工作,咱们将应用 Adam 优化器和模型的均方误差。咱们能够很容易地应用 compile 函数来配置咱们的自编码器,如下所示:

autoencoder.compile(optimizer='adam', loss='mse')

最初,咱们能够在 10 个 epoch 下通过输出噪声和洁净的图像运行咱们的模型,这将须要大概 1 分钟的训练。咱们还应用测试数据集进行验证。以下代码用于训练模型:

autoencoder.fit(x_train_noisy, 
                x_train, 
                epochs=10, 
                shuffle=True, 
                validation_data=(x_test_noisy, x_test))

用咱们训练过的自编码器升高图像噪声

咱们当初就能够开始清理乐音图像了。留神,咱们能够拜访编码器和解码器网络,因为咱们在 NoiseReducer 对象下定义了它们。

所以,首先,咱们将应用一个编码器来编码咱们的噪声测试数据集(x_test_noise)。而后,咱们将编码后的输入输出到解码器,以取得洁净的图像。以下代码实现这些工作:

encoded_imgs=autoencoder.encoder(x_test_noisy).numpy()
decoded_imgs=autoencoder.decoder(encoded_imgs)

让咱们绘制前 10 个样本,进行并排比拟:

n = 10 
plt.figure(figsize=(20, 7))
plt.gray()
for i in range(n): 
  # 显示原始 + 噪声
  bx = plt.subplot(3, n, i + 1) 
  plt.title("original + noise") 
  plt.imshow(tf.squeeze(x_test_noisy[i])) 
  ax.get_xaxis().set_visible(False) 
  ax.get_yaxis().set_visible(False) 
  
  # 显示重建
  cx = plt.subplot(3, n, i + n + 1) 
  plt.title("reconstructed") 
  plt.imshow(tf.squeeze(decoded_imgs[i])) 
  bx.get_xaxis().set_visible(False) 
  bx.get_yaxis().set_visible(False) 
  
  # 显示原始
  ax = plt.subplot(3, n, i + 2*n + 1) 
  plt.title("original") 
  plt.imshow(tf.squeeze(x_test[i])) 
  ax.get_xaxis().set_visible(False) 
  ax.get_yaxis().set_visible(False) 

plt.show()

第一行用于噪声图像,第二行用于清理(重建)图像,最初,第三行用于原始图像。查看清理后的图像与原始图像的相似性:

结尾

你曾经构建了一个自编码器模型,它能够胜利地革除十分嘈杂的图像,这是它以前从未见过的(咱们应用测试数据集)。

显然有一些未复原的变形,例如右起第二张图片中短少拖鞋的底部。然而,如果思考到噪声图像的变形水平,咱们能够说咱们的模型在复原失真图像方面是相当胜利的。

在我的脑子里,你能够比如说——思考扩大这个自编码器,并将其嵌入照片加强应用程序中,这样能够进步照片的清晰度和清晰度。

参考

[1] Intro to Autoencoders, TensorFlow, available on https://www.tensorflow.org/tu…

原文链接:https://towardsdatascience.co…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

退出移动版