Sklearn 与 TensorFlow 机器学习实用指南——第十五章总结

自编码器是能够在无监督的情况下学习输入数据的有效表示(叫做编码)的人工神经网络(即,训练集是未标记),即一个输出等于输入的网络。这些编码通常具有比输入数据低得多的维度,使得自编码器对降维有用(参见第 8 章)。

在本章中,我们将更深入地解释自编码器如何工作,可以施加什么类型的约束以及如何使用 TensorFlow 实现它们,无论是用来降维,特征提取,无监督预训练还是作为生成式模型。参考地址

有效的数据表示

自编码器是一个输出等于输入的网络,而中间层是输入的高效表达。自编码器总是由两部分组成:将输入转换为内部表示的编码器(或识别网络),然后是将内部表示转换为输出的解码器(或生成网络)(见图 15-1)。

可以看到,自编码器和多层感知器(MLP,第10章)有着相同的结构,但是输出层中的神经元数量等于输入数量,因为输出等于输入。在这个例子中,只有一个由两个神经元(编码器)组成的隐藏层和一个由三个神经元(解码器)组成的输出层。 由于自编码器试图重构输入,所以输出通常被称为重建,并且损失函数包含重建损失,当重建与输入不同时,重建损失会对模型进行惩罚。

为了防止自编码器简单地将输入复制到编码,隐含层通常比输入数据具有更低的维度(比如上图时2D而不是3D),它被迫学习输入数据中最重要的特征(并删除不重要的特征)。

用不完整的线性自编码器执行 PCA

如果自编码器仅使用线性激活并且损失函数是均方误差(MSE),则可以显示它最终执行主成分分析(参见第 8 章)。

以下代码构建了一个简单的线性自编码器,以在 3D 数据集上执行 PCA,并将其投影到 2D:

import tensorflow as tf

reset_graph()

n_inputs = 3 # 3D inputs
n_hidden = 2 # 2D codings
n_outputs = n_inputs

learning_rate = 0.01

X = tf.placeholder(tf.float32, shape=[None, n_inputs])
hidden = tf.layers.dense(X, n_hidden)
outputs = tf.layers.dense(hidden, n_outputs)
# 损失函数为MSE
reconstruction_loss = tf.reduce_mean(tf.square(outputs - X))

optimizer = tf.train.AdamOptimizer(learning_rate)
training_op = optimizer.minimize(reconstruction_loss)

init = tf.global_variables_initializer()

需要注意的两件事:

  • 输出的数量等于输入的数量
  • 为了执行简单的 PCA,我们设置activation_fn = None(即,所有神经元都是线性的)

图 15-2 显示了原始 3D 数据集(左侧)和自编码器隐藏层的输出(即编码层,右侧)。 正如您所看到的,自编码器找到了将数据投影到数据上的最佳二维平面,保留了数据的尽可能多的差异(就像 PCA 一样)。

栈式自编码器(SAE)

像前面讨论的神经网络一样,自编码器可以有多个隐藏层。 在这种情况下,它们被称为栈式自编码器(或深度自编码器),添加更多层有助于自编码器了解更复杂的编码。

栈式自编码器的架构关于中央隐藏层(编码层)通常是对称的。例如,一个用于 MNIST 的自编码器(在第 3 章中介绍)可能有 784 个输入,其次是一个隐藏层,有 300 个神经元,然后是一个中央隐藏层,有 150 个神经元,然后是另一个隐藏层,有 300 个神经元,输出层有 784 神经元。 这个栈式自编码器如图 15-3 所示。

TensorFlow实现

我们可以像常规深度 MLP一样实现栈式自编码器。特别是,我们在第 11 章中用于训练深度网络的技术也可以应用。例如,下面的代码使用 He 初始化,ELU 激活函数和 l2 正则化为 MNIST 构建一个栈式自编码器。 代码应该看起来很熟悉,除了没有标签(没有y):

reset_graph()

from functools import partial

n_inputs = 28 * 28
n_hidden1 = 300
n_hidden2 = 150  # codings
n_hidden3 = n_hidden1
n_outputs = n_inputs

learning_rate = 0.01
l2_reg = 0.0001

X = tf.placeholder(tf.float32, shape=[None, n_inputs])

he_init = tf.contrib.layers.variance_scaling_initializer() # He initialization
#Equivalent to:
#he_init = lambda shape, dtype=tf.float32: tf.truncated_normal(shape, 0., stddev=np.sqrt(2/shape[0]))
l2_regularizer = tf.contrib.layers.l2_regularizer(l2_reg)
my_dense_layer = partial(tf.layers.dense,
                         activation=tf.nn.elu,
                         kernel_initializer=he_init,
                         kernel_regularizer=l2_regularizer)

hidden1 = my_dense_layer(X, n_hidden1)
hidden2 = my_dense_layer(hidden1, n_hidden2)
hidden3 = my_dense_layer(hidden2, n_hidden3)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值