做者|Orhan Gazi Yalçınv
编译|VK
来源|Towards Datas Sciencepython
你可能对不一样的神经网络结构有点熟悉。你可能据说过前馈神经网络,CNNs,RNNs,这些神经网络对于解决诸如回归和分类之类的监督学习任务很是有用。编程
可是,在无监督学习领域,咱们面临着大量的问题,如降维、特征提取、异常检测、数据生成、加强以及噪声抑制等。对于这些任务,咱们须要特殊的神经网络的帮助,这些神经网络是专门为无监督学习任务而开发的。数组
所以,他们必须可以在不须要监督的状况下训练出来。其中一种特殊的神经网络结构是自编码器。网络
自编码器是一种神经网络结构,它由两个子网络组成,即编码和解码网络,它们之间经过一个潜在空间相互链接。dom
自编码器最先由杰弗里·辛顿(Geoffrey Hinton)和PDP小组在20世纪80年代开发。Hinton和PDP小组的目标是解决“没有教师的反向传播”问题,即无监督学习,将输入做为教师。换句话说,他们只是简单地将特征数据用做特征数据和标签数据。让咱们仔细看看自编码器是如何工做的!机器学习
自编码器由一个编码器网络组成,该网络接收特征数据并对其进行编码以适应潜在空间。解码器使用该编码数据(即代码)将其转换回特征数据。在编码器中,模型学习的是如何有效地编码数据,以便解码器可以将其转换回原始数据。所以,自编码器训练的关键是生成一个优化的潜在空间。ide
如今,要知道在大多数状况下,潜在空间中的神经元数量要比输入层和输出层小得多,但不必定要这样。有不一样类型的自编码器,如欠完备、过完备、稀疏、去噪、压缩和变分自编码器。在本教程中,咱们只关注用于去噪的欠完备自编码器。函数
构建自编码器时的标准作法是设计一个编码器并建立该网络的反向版本做为该自编码器的解码器。所以,只要编码器和解码器网络之间存在反向关系,你就能够自由地向这些子网络添加任何层。例如,若是你处理的是图像数据,你确定须要卷积和池层。另外一方面,若是要处理序列数据,则可能须要LSTM、GRU或RNN单元。这里重要的一点是,你能够自由地构建任何你想要的东西。学习
如今,你已经有了能够构建图像降噪的自编码器的想法,咱们能够继续学习教程,开始为图像降噪模型编写代码。在本教程中,咱们选择使用TensorFlow的官方教程之一《Autoencoders简介》[1],咱们将使用AI社区成员中很是流行的数据集: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个样本:
为了提升计算效率和模型可靠性,咱们必须对图像数据应用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对象。它还须要声明几个变量和函数。
另外请注意,因为咱们处理的是图像数据,所以构建一个卷积式自编码器更为有效,以下所示:
要构建模型,咱们只需完成如下任务:
咱们能够经过如下代码实现全部这些目标:
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/