使用 TensorFlow 和 Keras 编写自动编码器

自动编码器是一种神经网络架构,通常与无监督学习,降维和数据压缩相关联。自动编码器通过使用隐藏层中较少数量的神经元来学习产生与输入层相同的输出。这允许隐藏层以较少数量的参数学习输入的特征。使用较少数量的神经元来学习输入数据的特征的这个过程反过来减少了输入数据集的维度。

自动编码器架构有两个阶段:编码器和解码器。在编码器阶段,模型学习如何将输入表示为具有较小维度的压缩矢量;在解码器阶段,模型学习如何将压缩了的矢量表示为输出矢量。损失则定义为为输出和输入之间的熵距离,因此通过最小化损失,我们学习的是将输入编码成能够重放输入本身的表示的参数,以及另一组学习参数。

在本文中,您将学习如何使用TensorFlow和Keras在以下主题中创建自动编码器体系结构:

  • 自动编码器类型
  • TensorFlow 和 Keras 中的堆叠自动编码器
  • TensorFlow 和 Keras 中的去噪声自动编码器
  • TensorFlow 和 Keras 中的变分自动编码器

自动编码器类型

自动编码器架构可以在各种配置中找到,例如简单自动编码器,稀疏自动编码器,去噪自动编码器和卷积自动编码器。

  • 简单自动编码器:在简单自动编码器中,与输入相比,隐藏层具有较少数量的节点或神经元。例如,在MNIST数据集中,784个特征的输入可以连接到512个节点或256个节点的隐藏层,这个隐藏层又连接到784个特征的输出层。因此,在训练期间,可能仅由256个节点学习784个特征。简单的自动编码器也称为欠完全(undercomplete)自动编码器。
    简单的自动编码器可以是单层或多层。通常,单层自动编码器在生产中表现不佳。 多层自动编码器具有多个隐藏层,分为编码器和解码器分组。编码器层将大量特征编码为较少数量的神经元,然后解码器层将学习的压缩特征解码回原始特征或减少数量的特征。多层自动编码器称为堆叠自动编码器。
  • 稀疏自动编码器:在稀疏自动编码器中,添加正则化项作为惩罚,因此,与简单自动编码器相比,表示变得更稀疏。
  • 去噪自动编码器:在去噪自动编码器架构中,输入引入了随机噪声。去噪自动编码器重新创建输入并尝试消除噪音。去噪自动编码器中的退出函数将去噪重建输出与原始未损坏输入进行比较。
  • 卷积自动编码器:之前讨论的自动编码器使用完全连接的层,这种模式类似于多层感知器模型。我们也可以使用卷积层而不是完全连接或稠密层。当我们使用卷积层来创建自动编码器时,它被称为卷积自动编码器。例如,我们可以为卷积自动编码器提供以下层:
    输入->卷积->池化->卷积->池化->输出
    第一组卷积和池化层充当编码器,将高维输入特征空间减少到低维特征空间。第二组卷积和池化层充当解码器,将其转换回高维特征空间。
  • 变分自动编码器:变分自动编码器架构是自动编码器领域的最新发展。变分自动编码器是一种生成模型,即它产生概率分布的参数,从中可以生成原始数据或与原始数据非常相似的数据。
    在变分自动编码器中,编码器将输入样本转换为潜在空间中的参数,使用该参数对潜在点进行采样。然后解码器使用潜点重新生成原始输入数据。 因此,在变分自动编码器中学习的重点转移到最大化输入数据的概率,而不是试图从输入重建输出。

现在让我们在接下来的章节中使用TensorFlow和Keras构建自动编码器。我们将使用MNIST数据集来构建自动编码器。自动编码器将学习使用较少数量的神经元或特征表示MNIST数据集中的手写数字。

您可以按照Jupyter笔记本ch-10_AutoEncoders_TF_and_Keras中的代码进行操作。

像往常一样,我们首先使用以下代码读取MNIST数据集:

我们从训练和测试数据集中提取四个不同的图像集及其各自的标签:

现在让我们看看使用MNIST数据集构建自动编码器的代码。

您可以按照Jupyter笔记本ch-10_AutoEncoders_TF_and_Keras中的代码进行操作。

TensorFlow 中的堆叠自动编码器

在TensorFlow中构建堆叠自动编码器模型的步骤如下:

  1. 首先,定义超参数如下:
  1. 定义输入(即特征)和输出(即目标)的数量。输出数量与输入数量相同:
  1. 定义输入和输出图像的占位符:
  1. 将编码器和解码器层的神经元数量添加为[512, 256, 256, 512]:
  1. 定义 wb 参数:
  1. 构建网络并为每个层使用sigmoid激活函数:
  1. 使用mean_squared_error定义损失函数,使用AdamOptimizer定义优化器:
  1. 训练模型并预测训练集以及测试集:
  1. 从以下输出中我们可以看到,在20次循环后损失明显下降:
  1. 现在模型已经过训练,让我们显示训练模型中的预测图像。我们写了一个辅助函数display_images来帮助我们显示图像:

使用此功能,我们首先显示训练集中的四个图像和自动编码器预测的图像。

第一行表示实际图像,第二行表示生成的图像:

生成的图像有一点点噪音,可以通过更多训练和超参数调整来消除。现在预测训练集图像并不神奇,因为我们在这些图像上训练了自动编码器,之后自动编码器就能理解图片了。让我们看一下预测测试集图像的结果。第一行表示实际图像,第二行表示生成的图像:

哇!经过训练的自动编码器能够生成相同的数字,而这一切只需要根据从768个特征中学到的256个特征。生成的图像中的噪声可以通过超参数调整和更多训练来改善。

Keras 中的自动编码器

现在让我们在Keras中构建相同的自动编码器。

我们使用以下命令清除笔记本中的图形,以便我们可以构建一个新图形,该图形不会占用上一个会话或图形中的任何内存:

tf.reset_default_graph()
keras.backend.clear_session()

  1. 首先,我们导入keras库并定义超参数和层:
  1. 接下来,我们构建一个顺序模型并为其添加密集层。至于更改,我们对隐藏图层使用relu激活,对最终图层使用线性激活:
  1. 现在让我们显示模型摘要以查看模型的外观:

该模型在五个密集层中共有1,132,816个参数:

层(类型)输出形状参数 #
dense_1 (Dense)(None, 512)401920
dense_2 (Dense)(None, 256)131328
dense_3 (Dense)(None, 256)65792
dense_4 (Dense)(None, 512)131584
dense_5 (Dense)(None, 784)402192
  1. 让我们用上一个例子中的均方损失编译模型:

在20次迭代后,我们能够获得0.0046的损失,相比之前我们得到的0.078550要的得多:

现在让我们预测并显示模型生成的训练和测试图像。第一行表示实际图像,第二行表示生成的图像。以下是训练集图像:

以下是测试集图像:

我们能够仅根据256个特征生成图片已经是非常好的精确度了。

TensorFlow 中的去噪自动编码器

正如您在本文的第一部分中所了解的那样,可以使用去噪自动编码器来训练模型,以便它们能够从输入到训练模型的图像中去除噪声:

  1. 为了达到本示例的目的,我们编写以下辅助函数来帮助我们为图像添加噪声:
  1. 然后我们添加噪声来测试图像并将其存储在单独的列表中:

我们将使用这些测试图像来测试我们的去噪模型示例的输出。

  1. 我们按照前面的例子构建和训练去噪自动编码器,但有一点不同:在训练时,我们将噪声图像输入到输入层,我们用非噪声图像检查重建和去噪误差,如下面的代码所示:

笔记本ch-10_AutoEncoders_TF_and_Keras中提供了去噪自动编码器的完整代码。

现在让我们首先显示从去噪自动编码器模型生成的测试图像;第一行表示原始的非噪声测试图像,第二行表示生成的测试图像:

上述代码的结果如下:

接下来,当我们输入噪声测试图像时,我们显示生成的图像:

上述代码的结果如下:

那太酷了!! 该模型学习了图像并生成了几乎正确的图像,即使是非常嘈杂的图像。通过适当的超参数调整可以进一步提高再生质量。

Keras 中的去噪自动编码器

现在让我们在Keras中构建相同的去噪自动编码器。

由于Keras负责按批量大小送入训练集,我们创建了一个带有噪声的训练集作为我们模型的输入:

笔记本ch-10_AutoEncoders_TF_and_Keras中提供了Keras中DAE的完整代码。

去噪自动编码器的Keras模型如下所示:

层(类型)输出形状参数 #
dense_1 (Dense)(None, 512)401920
dense_2 (Dense) (None, 256) 131328
dense_3 (Dense) (None, 256) 65792
dense_4 (Dense) (None, 512) 131584
dense_5 (Dense) (None, 784) 402192

由于去噪自动编码器模型很复杂,为了演示,我们不得不将时期数增加到100来训练模型:

打印生成的图像:

第一行是原始测试图像,第二行是生成的测试图像:

第一行是噪声测试图像,第二行是生成的测试图像:

正如我们所看到的,去噪自动编码器可以很好地从噪声版本的图像中生成图像。

TensorFlow 中的变分自动编码器

变分自动编码器是自动编码器的现代生成版本。让我们为前面提到的相同的问题构建一个变分自动编码器。我们将通过提供来自原始和嘈杂测试集的图像来测试自动编码器。

我们将使用不同的编码风格来构建此自动编码器,以便使用TensorFlow演示不同的编码风格:

  1. 首先定义超参数:
  1. 接下来,定义参数字典以保存权重和偏置参数:
  1. 定义每个编码器和解码器中隐藏层的数量:
  1. 变分编码器中的新增加变量是我们新定义的潜在变量z的维数:
  1. 我们使用激活函数 tanh:
  1. 定义输入和输出占位符:
  1. 定义输入层:
  1. 定义编码器网络的偏置和权重并添加图层。变分自动编码器的编码器网络也称为识别网络或推理网络或概率编码器网络:
  1. 接下来,添加潜在变量的均值和方差的图层:
  1. 接下来,定义表示与保持z方差的变量相同形状的噪声分布的epsilon变量:
  1. 根据均值,对数方差和噪声定义后验分布:
  1. 接下来,定义解码器网络的权重和偏置,并添加解码器层。 变分自动编码器中的解码器网络也称为概率解码器或发生器网络。
  1. 最后,定义输出层:
  1. 在变分自动编码器中,我们有重建损失和正则化损失。将损失函数定义为重建损失和正则化损失的总和:
  1. 基于AdapOptimizer定义优化器函数:
  1. 现在让我们训练模型并从非噪声和噪声测试图像生成图像:

我们得到以下输出:

现在让我们显示图像:

结果如下:

结果如下:

同样,可以通过超参数调整和增加学习量来改善结果。

Keras 中的变分自动编码器

在Keras中,构建变分自动编码器更容易,并且代码行更少。Keras变分自动编码器最好使用函数式构建。到目前为止,我们已经使用了在Keras中构建模型的顺序样式,现在在这个例子中,我们将看到在Keras中构建变分自动编码器模型的函数风格。在Keras建立变分自动编码器的步骤如下:

  1. 定义隐藏层和潜在变量层中的超参数和神经元数量:
  1. 构建输入层:
  1. 构建编码器层,以及潜在变量的均值和方差层:
  1. 创建噪声和后验分布:
  1. 添加解码层:
  1. 定义最终输出层:
  1. 最后,从输入层和输出层定义模型并显示模型摘要:

我们看到以下摘要:

层(类型)输出形状参数 #连接到
输入(输入层)(None, 784)0
enc_0 (Dense)(None, 512)401920input[0][0]
enc_1 (Dense)(None, 256)131328enc_0[0][0]
z_mean (Dense)(None, 128)32896enc_1[0][0]
z_log_v (Dense)(None, 128)32896enc_1[0][0]
z (Lambda)(None, 128)0z_mean[0][0]
z_log_v[0][0]
dec_1 (Dense)(None, 256)33024z[0][0]
dec_0 (Dense)(None, 512)131584dec_1[0][0]
output (Dense)(None, 784)402192dec[0][0]
  1. 定义一个计算重建和正则化损失之和的函数:
  1. 使用此损失函数来编译模型:
  1. 让我们训练50次迭代的模型并预测图像,正如我们在前面的部分中所做的那样:

让我们显示结果图像:

我们得到如下结果:

我们得到如下结果:

这很棒!! 生成的图像更清晰、更锐利。

总结

自动编码器是无人监督数据学习的绝佳工具。它们通常用于降低维数,因此数据可以用较少数量的特征来表示。在本章中,您了解了各种类型的自动编码器。我们使用TensorFlow和Keras练习构建三种类型的自动编码器:堆叠自动编码器,去噪自动编码器和变分自动编码器。我们使用MNIST数据集作为示例。

在后面的几篇文章中,您会学习到如何使用TensorFlow和Keras构建各种机器学习和深度学习模型,例如回归,分类,MLP,CNN,RNN和自动编码器。在下一篇文章中,您将了解TensorFlow和Keras的高级功能,这些功能允许我们将模型投入生产。

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据