提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
@TOC
前言
在本文中,我们将研究自动编码器。本文介绍了自动编码器的数学和基本概念。我们将讨论它们是什么,限制是什么,典型用例,并将查看一些示例。我们将从对自动编码器的一般介绍开始,我们将讨论激活函数在输出层和损失函数的作用。然后我们将讨论什么是重构误差。最后,我们将研究典型的应用,如降维、分类、去噪和异常检测。
1、介绍
在深度学习中,自动编码器是一种 无监督 的 神经网络 模型,它可以学习到输入数据的隐含特征,这称为编码(coding),同时用学习到的新特征可以重构出原始输入数据,称之为解码(decoding)。在1986年,由鲁梅尔哈特、辛顿和威廉姆斯首次提出了自动编码器其目的是学习怎么以尽可能低的误差重建输入观测。为什么要学习重建输入的观察结果?想象一下有一个由图像组成的数据集。
图片一:自动编码器的一般构造
为了更好地理解自动编码器,我们需要参考它们的典型架构,如图1所示。自动编码器的主要组件有三个:编码器、潜在特征表示和解码器,编码器和解码器都是简单的函数。一般来说,我们希望自动编码器能够很好地重构输入。不过,与此同时,它应该创建一个有用且有意义的潜在表示(图1中编码器部分的输出)。在大多数典型的体系结构中,编码器和解码器都是神经网络(这是我们将在本文中详细讨论的情况),因为它们可以很容易地使用现有的软件库进行训练,如带有反向传播的TensorFlow或PyTorch。 编码器可以写成一个依赖于某些参数的函数g 其中为编码器(encoder)块的输出且,解码器(decoder)可以写成具有潜在特征的第二个函数(我们将用来表示网络的输出) 且 训练一个自动编码器即意味着找到函数**和**能够满足 其中自编码器的输入和输出的差异,表示所有观测结果的平均值。同时在设计自动编码器时,很有可能找到和可以让自动编码器完美的重建输出,从而变成恒等函数(与原来的函数相同的恒等函数),但是在学习的过程中我们得到的均方误差有可能会变得特别小,这样的话就会导致过拟合的现象,这就不是我们想要得到的目的。为了避免这种情况,可以使用两种策略:创建瓶颈和添加某种形式的正则化。
1.1 自动编码器中的正则化
在自动编码器中添加正则化项其目的是在潜在特征输出中加强稀疏性,实现这一目的最简单的方法是在损失函数中添加或正则化项。其中加入正则化项如下所示 在公式中是函数和中的参数(你可以想象在函数是神经网络的情况下,参数将是权重)。另一个值得一提的技巧是将编码器的权值与解码器的权值捆绑在一起(换句话说,使它们相等)。这些操作基本上具有相同的效果:为潜在特征表示增加稀疏性。
2.前馈自动编码器
前馈自动编码器(FFA)是由具有特定架构的密集层组成的神经网络,如图2所示。
图二:前馈自动编码器的典型结构
典型的FF A体系结构(尽管它不是强制性的要求)具有奇数层,并且相对于中间层是对称的。通常,第一层的神经元数量为n1 = n(输入观察数据的大小xi),当我们向网络的中心移动时,每一层的神经元数量都在某种程度上下降。中间层(记住我们有奇数层)通常有最小数量的神经元。这一层的神经元数量小于输入的大小,这是我们前面提到的瓶颈。在几乎所有的实际应用中,中间层之后的层是中间层之前的层的镜像版本。例如,一个有3层的自动编码器可以有以下数量的神经元:n1 = 10, n2 = 5,然后n3 = n1 = 10(假设我们正在处理一个输入维数为n = 10的问题)。从中间层开始并包括中间层在内的所有层构成所谓的编码器,从中间层开始并包括中间层(直到输出层)的所有层构成所谓的解码器,如图(25.2)所示。如果FF A训练是成功的,结果将是输入的一个很好的近似,换句话说,。需要注意的是,解码器可以通过使用比输入观测值初始值(n)小得多的特征数(q)来重建输入。
2.1 输出层的激活函数
在基于神经网络的自动编码器中,输出层的激活函数起着特别重要的作用,最常用的函数是ReLU和sigmoid。
2.1.1 ReLU
ReLU激活函数可以假设在范围内的所有值。其公式如下: 当输入的观察值假设一个大范围的正值时,这种选择是好的。如果输入可以假设为负值,那么ReLU当然是一个糟糕的选择。
2.1.2 Sigmoid
Sigmoid函数可以假设在范围内的所有值,它的公式是: 这个激活函数只能在输入的观察都在的范围内,或者你已经将它们规范化到这个范围内时使用。以MNIST数据集为例。输入观察xi(一张图像)的每一个值都是像素的灰度值,可以假设从0到255的任何值。通过将像素值除以255进行归一化处理,将使每个观察结果(每张图像)只有0到1之间的像素值。在这种情况下,对于输出层的激活函数,sigmoid是一个很好的选择。
2.2 损失函数
与任何神经网络模型一样,我们需要一个损失函数来衡量误差,即是用来测量和之间的差异。如同上文所示,可以写为: 其中和就是我们通过FFA(前馈自动编码器)学习得到的函数,而且自动编码器的目标是学习恒等函数的近似值,所以我们希望根据和之间的某一个度量得到与目标差异最小的权重。两种损失函数被广泛用于自动编码器:均方误差(MSE)和二进制交叉熵(BCE),同时两种损失函数也有不同的应用场景。
2.2.1 均方误差
由于自动编码器试图解决回归问题,最常见的损失函数是均方误差(MSE): 符号表示向量的范数 ,M为训练数据集中观测值的个数。它可以在几乎所有情况下使用,与您如何选择输出层激活函数或如何规范化输入数据无关。因为我们可以证明这个均方误差一定有一个最小值。
2.2.2 二元交叉熵
如果FF A输出层的激活函数是一个sigmoid函数,从而将神经元输出限制在0到1之间,而输入特征归一化为0到1之间,我们可以使用二元交叉熵作为损失函数,在这里用表示。这类损失函数通常用于分类问题,其在自动编码器中表现很好。 其中是第i个观测值的第j个分量。使用二元交叉熵损失函数的一个基本前提是输入必须在0到1之间归一化,最后一层的激活函数必须是sigmoid或softmax函数。
2.3 重建误差
重构误差(RE)是一个度量,它可以指示自动编码器重构输入观测的好坏。最典型的重建误差就是MSE。
当使用自动编码器进行异常检测时,经常使用RE,我们将在后面解释。对重构误差有一个简单直观的解释。当正则值显著时,自动编码器无法很好地重建输入,而当正则值较小时,自动编码器能很好地重建输入。图3显示了当自动编码器试图重构图像时,大小重构错误的示例。
图三:重建误差大小的例子
2.4 样例:手写数字重构
现在让我们使用MNIST数据集,看看自动编码器在一个真实的例子中是如何执行的。该数据集包含70000张从0到9的手写数字。每个图像是28 × 28像素,只有灰度值,这意味着我们有784个特征(像素灰度值)作为输入。让我们从一个有3层的自动编码器开始,每层的神经元数量等于(784,16,784)。注意,第一层和最后一层的维度必须等于输入维度。对于本例,我们使用Adam optimizer作为损失函数优化,我们训练模型30个周期,批次大小为256。在图4中,您可以看到两行数字图像。顶部的这行包含了来自原始数据集的10个随机图像,而底部的这些是用我们刚刚描述的自动编码器重建的图像。
图四:在最上面的一行中,您可以看到MNIST数据集的原始数字。相比之下,下面这行包含了由自动编码器重建的数字,神经元的数量为(784,16,784)。我们看到使用16个特征就能得到结果,虽然效果并不是特别理想。所以接下来我们可以看一下中间层使用64个特征(并且保持其他参数不变)。
图五:在最上面的一行中,您可以看到MNIST数据集的原始数字。而下面的线是由自动编码器重建的数字,神经元数为(784,64,784)。 一个中间层小于输入维度(瓶颈)的自动编码器可以用来提取输入数据集的基本特征,创建由函数给出的输入的学习表示。所以说FFA可以用来执行降维。如果中间层的神经元数量减少太多(如果瓶颈太极端),FF A将不能很好地重建输入数字。图6显示了使用中间层只有8个神经元的自动编码器对相同数字的重构。中间层只有8个神经元,你可以看到一些重构的数字是错误的。如图6所示,4被重构为9,2被重构为类似于3的东西。
图6:在最上面一行中,您可以看到MNIST数据集的原始数字。相比之下,下面这行包含了由自动编码器重建的数字,神经元的数量为(784,8,784)。
图7:在最上面一行中,您可以看到MNIST数据集的原始数字。第二行数字包含由FF A重构的数字(784,8784),第三行是由FF A重构的数字(784,16784),最后一行是由FF A重构的数字(784,64784)。 对于这些例子,我们使用二元交叉熵作为损失函数,但MSE也可以很好地工作。
图8:在最上面一行中,您可以看到来自MNIST数据集的十个随机原始数字。第二行数字包含用中间层有16个神经元的FF A和二进制交叉熵作为损失函数重构的数字。最后一行包含用MSE作为损失函数重建的图像。
3 自动编码器的应用
3.1 降维
正如我们在本文中提到的,使用瓶颈法,潜在特征的维数q将小于输入观测值n的维数。编码器部分通过训练来产生潜在特征,我们可以将潜在的特性用于各种任务,例如分类或聚类。同时与更经典的PCA方法相比,使用自编码器进行降维的一些优点。从计算的角度来看,自动编码器有一个主要的好处:它可以有效地处理大量的数据,因为它的训练可以用小批量完成,而PCA(最常用的降维算法之一)需要使用整个数据集进行计算。使用自动编码器进行降维有一个主要的优势:它可以有效地处理大量的数据,因为它的训练可以用小批量完成。
3.2 分类
3.2.1 具有潜在特征的分类
现在假设我们想对MNIST数据集的输入图像进行分类。我们可以简单地使用所有的特征,在我们的例子中,图像的784像素值。为了便于说明,我们可以简单地使用kNN算法。在训练MNIST数据集(60000张图像)上使用7个最近的近邻进行测试将花费大约16.6分钟13(约1000秒),并在10000张图像的测试数据集上获得96.4%的准确率。如果我们考虑一个中间层有8个神经元的FF A,并在潜在特征g (xi)∈R8上再次训练kNN算法,我们在1.1秒内获得89%的准确率。我们在运行时间中获得了1000倍的增益,而在准确率15上损失了7.4%(见表1)。
表1:将kNN算法应用于MNIST数据集的784个原始特征和8个潜在特征在精度和运行时间上的差异。
我们可以用另一个数据集,Fashion MNIST16数据集(来自Zalando的数据集与MNIST数据集非常相似,该数据集包括MNIST的60000张训练图像和10000张测试图像。在表2中,您可以看到将kNN应用于该数据集的测试部分的结果摘要。我们可以发现中间层有16个神经元的FFA在3秒内达到了83.6%的准确率。当对原始特征(784)应用kNN算法时,我们得到的准确率仅提高1.8%,但运行时间增加了约330倍。
表2:对于Fashion MNIST数据集,将kNN算法应用于带有8个神经元的FFA和带有16个神经元的FFA的原始784个特征时,准确性和运行时间的差异。
3.2 异常检测
自动编码器通常用于在大多数不同的数据集上执行异常检测。要理解自动编码器的异常检测是如何工作的,最好的方法是通过一个实际的例子来研究它。让我们考虑一个只有三层的自动编码器,第一层有784个神经元,潜在特征生成层有64个,输出层也有784个神经元。我们将使用MNIST数据集训练它。让我们从这个数据集中选择一个鞋子的图像(参见图9),并将其添加到MNIST数据集。MNIST的原始测试部分有10000张图像。有了鞋子,我们将有一个10001图像数据集。这只鞋是一个“异常”,因为它是完全不同的,我们将使用我们用60000 MNIST图像训练的自动编码器,用它我们将计算10001张测试图像的重构误差。其主要思想是:由于自动编码器只能看到手写数字图像,它将无法重建鞋子图像。因此我们期望该图像具有最大的重构误差。我们可以通过取前2个重构误差来检查是否如此。对于本例,我们使用MSE来表示重构误差,鞋的重建误差最高,为0.062。从图10中可以看出,自动编码器无法重建图像。
图10:鞋子和自动编码器在MNIST数据集的60000张手写图像上的重建训练。 在我们构建的整个10001测试数据集中,该图像具有最大的RE值,为0.062。第二大的RE略小于鞋子的三分之一:0.022,这表明自动编码器在理解如何重建手写数字方面做得相当好。第二大RE值的这张图片也可以被归类为离群值,因为不完全清楚它是4还是9。因为我们是在一个没有任何异常值的数据集上训练我们的自动编码器,并将其应用到另一个有异常值的数据集上。
图11:10001测试数据集中RE第二大的图像的重建值:0.022。
一般来说,人们希望在单个大数据集中找到异常值,而不知道有多少异常值或异常值的情况。可以按照如下步骤:
- 一个训练在整个数据集上的自动编码器(或者在可能的情况下,在已知的数据集中没有任何离群值的部分上)。
- 对于已知具有所需异常值的数据集部分的每个观察(或输入),计算RE。
- 人们根据RE对观察结果进行分类。
- 可以将异常值最高的分类为异常值,不过这个分类需要对结果进行分析,通常需要对数据和问题有大量的了解。需要注意一下,如果在整个数据集上训练自动编码器,有一个基本的假设:异常值是数据集中可以忽略的一部分,它们的存在不会影响(或将以不重要的方式影响)自动编码器学习重建观察结果的方式。
3.3.1 模型稳定性——简短的说明
按照上面所述的异常检测方法步骤很简单,但是容易出现过拟合,结果往往会不一致。这意味着用不同的架构训练一个自动编码器很可能会得到不同的REs和其他异常值。有几种方法可以解决这个问题,但是处理结果的不稳定性的最简单的方法之一是训练不同的模型,然后取REs的平均值。另一种常用的技术是从几个模型中求评估REs的最大值。
3.4 去噪自动编码器
去噪自动编码器19是为了自动纠正输入观测中的错误(噪声)而开发的。作为一个例子,想象一下我们之前考虑的手写数字,我们添加了一些噪声(例如高斯噪声),以随机改变像素的灰度值的形式。在这种情况下,自动编码器应该学会在没有附加噪声的情况下重建图像。作为一个具体的例子,考虑MNIST数据集。我们可以给每个像素加上一个随机值,噪声是由一个正态分布中0到1之间的实数相加产生的。我们可以训练一个自动编码器作为输入噪声图像,并原始图像作为输出。模型应该学会去除噪声,因为噪声在本质上是随机的,与图像没有关系。在图12中可以看到结果。左边一栏是有噪声的图像,中间是原始图像,右边是去噪后的图像。它的效果令人印象深刻。通过训练一个FF a自编码器,3层,中间层32个神经元,得到图12。
图12:3层FF a去噪自编码器的结果,中间层32个神经元。噪声是由一个正态分布中0到1之间的实数相加产生的。
工作原理:我们把损坏的数据送给自编码器的输入端,并要求它通过编码+解码两个步骤重构出无损的原始输入。那么当输入一个没有经过损坏的数据时,我们就能将其恢复到更理想的状态。