正确训练 Stacked Autoencoder

Posted

技术标签:

【中文标题】正确训练 Stacked Autoencoder【英文标题】:Train Stacked Autoencoder Correctly 【发布时间】:2019-02-12 17:20:33 【问题描述】:

我尝试在 Keras (tf.keras) 中构建堆栈式自动编码器。 堆叠并不是指。我为 Keras 找到的所有示例都在生成,例如3 个编码器层,3 个解码器层,他们训练它并收工。然而,训练 Stacked 自编码器 (SAE) 的正确方法似乎是本文中描述的方法:Stacked Denoising Autoencoders: Learning Useful Representations in a Deep Network with a Local Denoising Criterion

简而言之,应按如下图所示逐层训练 SAE。第 1 层训练完成后,将其用作训练第 2 层的输入。重建损失应与第 1 层进行比较而不是输入层

这就是我的麻烦开始的地方。如何告诉 Keras 在哪些层上使用损失函数?

这就是我所做的。由于 Keras 中不再存在自动编码器模块,因此我构建了第一个自动编码器,并将其编码器的权重 (trainable = False) 设置在第二个自动编码器的第一层,总共 2 层。然后当我训练它时,它显然将重构层 out_s2 与输入层 in_s 进行比较,而不是第 1 层 hid1

# autoencoder layer 1
in_s = tf.keras.Input(shape=(input_size,))
noise = tf.keras.layers.Dropout(0.1)(in_s)
hid = tf.keras.layers.Dense(nodes[0], activation='relu')(noise)
out_s = tf.keras.layers.Dense(input_size, activation='sigmoid')(hid)

ae_1 = tf.keras.Model(in_s, out_s, name="ae_1")
ae_1.compile(optimizer='nadam', loss='binary_crossentropy', metrics=['acc'])

# autoencoder layer 2
hid1 = tf.keras.layers.Dense(nodes[0], activation='relu')(in_s)
noise = tf.keras.layers.Dropout(0.1)(hid1)
hid2 = tf.keras.layers.Dense(nodes[1], activation='relu')(noise)
out_s2 = tf.keras.layers.Dense(nodes[0], activation='sigmoid')(hid2)

ae_2 = tf.keras.Model(in_s, out_s2, name="ae_2")
ae_2.layers[0].set_weights(ae_1.layers[0].get_weights())
ae_2.layers[0].trainable = False

ae_2.compile(optimizer='nadam', loss='binary_crossentropy', metrics=['acc'])

解决方案应该相当简单,但我看不到它,也无法在网上找到它。我如何在 Keras 中做到这一点?

【问题讨论】:

请注意,您所指的论文是 2010 年的,并且已经过时了。没有人真正进行分层训练了。这样做只是为了好玩吗? 那么@xdurch0 如果不进行逐层训练,还有什么方法可以堆叠层?你能给我一个例子或指出我的来源吗?这是一个大项目的一部分,但不是为了好玩。 “堆叠”层实际上只是意味着使用深度网络/自动编码器。因此,只需根据初始输入和最终输出一次性训练它。进行分层训练和“堆叠”是因为几年前人们不知道如何训练深度网络。随着 relu 激活、批量归一化等的出现,进行分层训练 (恕我直言) 是不值得的。 本教程是关于自动编码器的一个很好的例子,是用keras编写的blog.keras.io/building-autoencoders-in-keras.html @xdurch0 感谢您的意见,看来您是对的。我找到了这篇论文,它解决了我的大部分问题“联合训练是否更适合深度自动编码器?” arxiv.org/pdf/1405.1380.pdf 【参考方案1】:

通过查看 cmets,这个问题似乎已经过时了。但我仍然会回答这个问题,因为这个问题中提到的用例不仅特定于自动编码器,而且可能对其他一些情况有所帮助。

所以,当你说“逐层训练整个网络”时,我宁愿将其解释为“在一个序列中训练一个单层的小型网络”。

看这个问题贴出的代码,看来OP已经搭建了小型网络了。 但是这两个网络都不是由一层组成。

这里的第二个自动编码器,将第一个自动编码器的输入作为输入。但是,它实际上应该将第一个自动编码器的输出作为输入。

然后,您训练第一个自动编码器并在训练后收集它的预测值。然后你训练第二个自动编码器,它将第一个自动编码器的输出(预测)作为输入。

现在让我们关注这部分:“第1层训练后,作为输入来训练第2层。重建损失应该与第1层而不是输入层进行比较。”

由于网络将第 1 层的输出(在 OP 的情况下为自动编码器 1)作为输入,它会将其输出与此进行比较。任务完成。

但要实现这一点,您需要编写问题中提供的代码中缺少的 model.fit(...) 行。

另外,如果您希望模型计算输入层的损失,您只需将 model,fit(...) 中的 y 参数替换为自动编码器 1 的输入即可。

简而言之,您只需将这些自动编码器解耦成单层的微型网络,然后按照您的意愿训练它们。现在不用trainable = False,也可以随意使用。

【讨论】:

以上是关于正确训练 Stacked Autoencoder的主要内容,如果未能解决你的问题,请参考以下文章

Stacked AutoEncoder(堆栈自动编码器)

matplotlib绘制带比例(percentile)的堆叠(stacked)条形图(bar plot)

html IF_03_14_Inputs_Stacked

jasper create a new stacked chart

R语言ggplot2可视化堆叠条形图(stacked bar plot)并且在每个条形图的顶端使用数值标签表示整个条形的加和值(sum value above the stacked bar)

stacked generalization 堆积正则化 堆积泛化 加权特征线性堆积