Keras中的TimeDistributed(Dense)与Dense – 参数数量相同

我在构建一个使用循环层(GRU)将字符串转换为另一个字符串的模型。我尝试在倒数第二层使用了Dense层和TimeDistributed(Dense)层,但当使用return_sequences=True时,我不明白这两者之间的区别,特别是它们似乎拥有相同数量的参数。

我的简化模型如下:

InputSize = 15MaxLen = 64HiddenSize = 16inputs = keras.layers.Input(shape=(MaxLen, InputSize))x = keras.layers.recurrent.GRU(HiddenSize, return_sequences=True)(inputs)x = keras.layers.TimeDistributed(keras.layers.Dense(InputSize))(x)predictions = keras.layers.Activation('softmax')(x)

网络的摘要是:

_________________________________________________________________Layer (type)                 Output Shape              Param #   =================================================================input_1 (InputLayer)         (None, 64, 15)            0         _________________________________________________________________gru_1 (GRU)                  (None, 64, 16)            1536      _________________________________________________________________time_distributed_1 (TimeDist (None, 64, 15)            255       _________________________________________________________________activation_1 (Activation)    (None, 64, 15)            0         =================================================================

我认为这是合理的,因为我理解的TimeDistributed是它会在所有时间点应用相同的层,因此Dense层有16*15+15=255个参数(权重+偏置)。

然而,如果我切换到一个简单的Dense层:

inputs = keras.layers.Input(shape=(MaxLen, InputSize))x = keras.layers.recurrent.GRU(HiddenSize, return_sequences=True)(inputs)x = keras.layers.Dense(InputSize)(x)predictions = keras.layers.Activation('softmax')(x)

我仍然只有255个参数:

_________________________________________________________________Layer (type)                 Output Shape              Param #   =================================================================input_1 (InputLayer)         (None, 64, 15)            0         _________________________________________________________________gru_1 (GRU)                  (None, 64, 16)            1536      _________________________________________________________________dense_1 (Dense)              (None, 64, 15)            255       _________________________________________________________________activation_1 (Activation)    (None, 64, 15)            0         =================================================================

我怀疑这是因为Dense()只使用形状中的最后一个维度,并有效地将其他一切视为批次类似的维度。但这样一来,我就不确定Dense和TimeDistributed(Dense)之间的区别是什么了。

更新 查看https://github.com/fchollet/keras/blob/master/keras/layers/core.py,确实看起来Dense只使用最后一个维度来调整自身大小:

def build(self, input_shape):    assert len(input_shape) >= 2    input_dim = input_shape[-1]    self.kernel = self.add_weight(shape=(input_dim, self.units),

它还使用keras.dot来应用权重:

def call(self, inputs):    output = K.dot(inputs, self.kernel)

keras.dot的文档暗示它能很好地处理n维张量。我想知道它的确切行为是否意味着Dense()实际上会在每个时间步被调用。如果是这样,问题仍然存在:在这种情况下,TimeDistributed()实现了什么功能?


回答:

TimeDistributedDense 在GRU/LSTM单元展开过程中将相同的密集层应用于每个时间步。因此,误差函数将在预测标签序列和实际标签序列之间计算。(这通常是序列到序列标记问题的要求)。

然而,当return_sequences=False时,Dense层只在最后一个单元应用一次。这通常是使用RNN进行分类问题的情况。如果return_sequences=True,则Dense层就像TimeDistributedDense一样应用于每个时间步。

因此,根据你的模型,两者是相同的,但如果你将第二个模型改为return_sequences=False,那么Dense将只在最后一个单元应用。尝试更改它,模型将抛出错误,因为那时Y的大小将是[Batch_size, InputSize],它不再是序列到序列,而是一个完整序列到标签的问题。

from keras.models import Sequentialfrom keras.layers import Dense, Activation, TimeDistributedfrom keras.layers.recurrent import GRUimport numpy as npInputSize = 15MaxLen = 64HiddenSize = 16OutputSize = 8n_samples = 1000model1 = Sequential()model1.add(GRU(HiddenSize, return_sequences=True, input_shape=(MaxLen, InputSize)))model1.add(TimeDistributed(Dense(OutputSize)))model1.add(Activation('softmax'))model1.compile(loss='categorical_crossentropy', optimizer='rmsprop')model2 = Sequential()model2.add(GRU(HiddenSize, return_sequences=True, input_shape=(MaxLen, InputSize)))model2.add(Dense(OutputSize))model2.add(Activation('softmax'))model2.compile(loss='categorical_crossentropy', optimizer='rmsprop')model3 = Sequential()model3.add(GRU(HiddenSize, return_sequences=False, input_shape=(MaxLen, InputSize)))model3.add(Dense(OutputSize))model3.add(Activation('softmax'))model3.compile(loss='categorical_crossentropy', optimizer='rmsprop')X = np.random.random([n_samples,MaxLen,InputSize])Y1 = np.random.random([n_samples,MaxLen,OutputSize])Y2 = np.random.random([n_samples, OutputSize])model1.fit(X, Y1, batch_size=128, nb_epoch=1)model2.fit(X, Y1, batch_size=128, nb_epoch=1)model3.fit(X, Y2, batch_size=128, nb_epoch=1)print(model1.summary())print(model2.summary())print(model3.summary())

在上面的示例中,model1model2的架构是样本(序列到序列模型),而model3是一个完整序列到标签的模型。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注