为啥不使用 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