编码器处理并浓缩输入数据后,我们就到达了自编码器一个很特别的部分:瓶颈层。该层是自编码器架构和功能的核心,充当信息必须通过的最窄点。设想一下,将水从一个宽容器通过窄漏斗倒入另一个容器中。漏斗的颈部就是瓶颈;它限制了一次可以流过的水量。类似地,在自编码器中,瓶颈层的神经元(或维度)明显少于输入层或编码器中紧邻它的层。这种设计迫使自编码器学习输入数据的一种高效、压缩的概括。一个压缩概括在自编码器中常表示为 $z$(有时也称作“潜在空间表示”或“编码”)。这个 $z$ 是编码器的最终输出,也是自编码器认为从输入 $X$ 中提炼出的主要信息。编码器部分的目的就是智能地将高维输入数据转换成这种低维的 $z$。digraph G { rankdir=TB; node [shape=box, style="filled", color="#adb5bd", fillcolor="#e9ecef", fontname="sans-serif"]; edge [fontname="sans-serif"]; subgraph cluster_encoder { label="编码器"; bgcolor="#d0bfff20"; node [fillcolor="#d0bfff60"]; input_layer [label="输入 X\n(例如, 784 维度)"]; encoder_hidden1 [label="隐藏层 1"]; encoder_hidden2 [label="隐藏层 2"]; } bottleneck [label="瓶颈 z\n(例如, 32 维度)", shape=box, style="filled", fillcolor="#f06595", color="#d6336c", fontcolor="white"]; subgraph cluster_decoder { label="解码器"; bgcolor="#96f2d720"; node [fillcolor="#96f2d760"]; decoder_hidden1 [label="隐藏层 1"]; decoder_hidden2 [label="隐藏层 2"]; output_layer [label="输出 X'\n(例如, 784 维度)"]; } input_layer -> encoder_hidden1 [label="压缩"]; encoder_hidden1 -> encoder_hidden2; encoder_hidden2 -> bottleneck; bottleneck -> decoder_hidden1 [label="重建"]; decoder_hidden1 -> decoder_hidden2; decoder_hidden2 -> output_layer; {rank=same; encoder_hidden1; decoder_hidden2;} {rank=same; encoder_hidden2; decoder_hidden1;} }一个自编码器架构展示了输入数据 $X$ 经过编码器,被压缩成瓶颈表示 $z$,然后由解码器重建为 $X'$。瓶颈层是最窄的点。瓶颈层中神经元的数量是你在构建自编码器时做出的一个设计选择。这个数量决定了压缩表示 $z$ 的维度。例如,如果你的输入数据是一个有 784 像素的图像(就像一张 28x28 的灰度图像),输入层将有 784 个维度。瓶颈层可能被设计为具有,比如说,32 个维度。这意味着自编码器必须学习将来自 784 个值的所有信息概括成仅仅 32 个值。为什么这种压缩很重要?效率:它迫使网络进行选择。它不能简单地复制输入;它必须学习丢弃噪声并仅保留信号,即数据最重要的属性。特征学习:瓶颈层 $z$ 中的值代表了学习到的特征。因为网络被训练成尽可能准确地从 $z$ 重建原始输入,所以这些特征必须信息量很大。自编码器会找出数据中哪些方面对捕获和实现良好重建最主要。因此,瓶颈不仅仅是一个结构组件。它是自编码器学习有意义表示能力的核心。解码器的全部工作(我们接下来会讨论)是,从瓶颈层获取这个紧凑表示 $z$,并尝试反转压缩过程,旨在重新创建原始输入数据。在瓶颈层学习到特征的质量直接影响解码器执行其重建任务的效果。如果瓶颈层太小,它可能会丢失太多信息,导致解码器无法很好地重建输入。如果它太大(但仍然小于输入),它可能无法学习到非常有用或压缩的表示。找到瓶颈层的合适大小是设计一个有效自编码器的一部分。