为啥不使用 Flatten 后跟 Dense 层而不是 TimeDistributed?

Posted

技术标签:

【中文标题】为啥不使用 Flatten 后跟 Dense 层而不是 TimeDistributed?【英文标题】:Why not use Flatten followed by a Dense layer instead of TimeDistributed?为什么不使用 Flatten 后跟 Dense 层而不是 TimeDistributed? 【发布时间】:2019-05-09 06:25:01 【问题描述】:

我正在尝试更好地理解 Keras 层。我正在研究一个序列到序列的模型,我在其中嵌入了一个句子并将其传递给返回序列的 LSTM。此后,我想对句子中的每个时间步(单词)应用一个 Dense 层,看起来 TimeDistributed 对这种情况下的三维张量做了这项工作。

据我了解,密集层仅适用于二维张量,而 TimeDistributed 仅在三个维度的每个时间步上应用相同的密集。那么,是否可以不简单地展平时间步长,应用密集层并执行重塑以获得相同的结果,或者这些在某种程度上不是我所缺少的?

【问题讨论】:

那么你会有一个大的密集层,每个时间步都有不同的参数,而不是对输入中的每个时间步应用相同的单时间步密集层。 我假设必须以某种方式将密集层连接到每个时间步,以便更新反向道具的权重?我认为我未能正确掌握这个概念是因为我无法想象这些方法。 正如@Andrey Kite Gorin 下面提到的,密集层可以应用 3D 张量,它们完全符合您的喜好。我认为有一些早期版本的 Keras,你必须使用 TimeDistributed,因为 Dense 仅适用于 2D 张量,这就是为什么一些教程仍然有它的原因。 【参考方案1】:

假设您有一批 4 个时间步长,每个时间步长包含一个 3 元素向量。让我们用这个来表示:

现在您想使用密集层转换此批次,因此每个时间步可得到 5 个特征。层的输出可以表示为:

您考虑两个选项,TimeDistributed 密集层,或将整形作为平面输入,应用密集层并重新整形回时间步。

在第一个选项中,您将在每个时间步应用一个具有 3 个输入和 5 个输出的密集层。这可能如下所示:

这里的每个蓝色圆圈都是密集层中的一个单元。通过对每个输入时间步执行此操作,您可以获得总输出。重要的是,这五个单元在所有时间步长上都是相同的,因此您只有一个具有 3 个输入和 5 个输出的密集层的参数。

第二种选择是将输入扁平化为 12 元素向量,应用具有 12 个输入和 20 个输出的密集层,然后将其重新整形。这就是它的外观:

为清楚起见,此处仅绘制了一个单元的输入连接,但每个单元都将连接到每个输入。显然,您有更多参数(具有 12 个输入和 20 个输出的密集层的参数),并且还请注意,每个输出值都受每个输入值的影响,因此一个时间步中的值会影响其他时间步中的输出.这是好事还是坏事取决于你的问题和模型,但它与之前的一个重要区别是,每个时间步的输入和输出都是独立的。除此之外,此配置要求您在每个批次上使用固定数量的时间步,而之前的配置独立于时间步数。

您还可以考虑使用四个密集层的选项,每个层独立应用于每个时间步(我没有画它,但希望您能明白)。这将类似于前一个,只有每个单元将仅从其各自的时间步输入接收输入连接。我认为在 Keras 中没有直接的方法可以做到这一点,您必须将输入分成四个,将密集层应用于每个部分并合并输出。同样,在这种情况下,时间步数将是固定的。

【讨论】:

【参考方案2】:

密集层可以作用于任何张量,不一定是 2 级。我认为 TimeDistributed 包装器不会改变密集层的作用方式。仅将 Dense 层应用于等级 3 的张量将与应用 Dense 层的 TimeDistributed 包装器完全相同。这是插图:

from tensorflow.keras.layers import *
from tensorflow.keras.models import *

model = Sequential()

model.add(Dense(5,input_shape=(50,10)))

model.summary()
_________________________________________________________________ 层(类型)输出形状参数# ==================================================== ================ dense_5(密集)(无、50、5)55 ==================================================== ================ 总参数:55 可训练参数:55 不可训练参数:0 _________________________________________________________________
model1 = Sequential()

model1.add(TimeDistributed(Dense(5),input_shape=(50,10)))

model1.summary()
_________________________________________________________________ 层(类型)输出形状参数# ==================================================== ================ time_distributed_3 (TimeDist (None, 50, 5) 55 ==================================================== ================ 总参数:55 可训练参数:55 不可训练参数:0 _________________________________________________________________

【讨论】:

【参考方案3】:

除了上面的答案, 这里有几张图片比较了两层的输出形状。因此,当在 LSTM(例如)之后使用这些层之一时,会有不同的行为。

【讨论】:

以上是关于为啥不使用 Flatten 后跟 Dense 层而不是 TimeDistributed?的主要内容,如果未能解决你的问题,请参考以下文章

输入0与图层flatten_15不兼容:预期min_ndim = 3,发现ndim = 2

为啥keras安装以后导入失败?

从Keras Layer获得权重

Dense 层上的 Dropout

BigQuery 文档 - 为啥 flatten 会消除重复

为啥 Dense SIFT 会产生这些关键点?