Keras 中的 TimeDistributed(Dense) 与 Dense - 相同数量的参数
TimeDistributed(Dense) vs Dense in Keras - Same number of parameters
我正在构建一个模型,该模型使用循环层 (GRU) 将一个字符串转换为另一个字符串。我已经尝试将 Dense 和 TimeDistributed(Dense) 层作为最后一层,但我不明白使用 return_sequences=True 时两者之间的区别,尤其是因为它们似乎具有相同数量的参数。
我的简化模型如下:
InputSize = 15
MaxLen = 64
HiddenSize = 16
inputs = 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 Sequential
from keras.layers import Dense, Activation, TimeDistributed
from keras.layers.recurrent import GRU
import numpy as np
InputSize = 15
MaxLen = 64
HiddenSize = 16
OutputSize = 8
n_samples = 1000
model1 = 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())
在上面的示例架构中,model1
和 model2
是样本(序列到序列模型),model3
是完整序列到标签模型。
这是一段验证 TimeDistirbuted(Dense(X))
与 Dense(X)
相同的代码:
import numpy as np
from keras.layers import Dense, TimeDistributed
import tensorflow as tf
X = np.array([ [[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
],
[[3, 1, 7],
[8, 2, 5],
[11, 10, 4],
[9, 6, 12]
]
]).astype(np.float32)
print(X.shape)
(2, 4, 3)
dense_weights = np.array([[0.1, 0.2, 0.3, 0.4, 0.5],
[0.2, 0.7, 0.9, 0.1, 0.2],
[0.1, 0.8, 0.6, 0.2, 0.4]])
bias = np.array([0.1, 0.3, 0.7, 0.8, 0.4])
print(dense_weights.shape)
(3, 5)
dense = Dense(input_dim=3, units=5, weights=[dense_weights, bias])
input_tensor = tf.Variable(X, name='inputX')
output_tensor1 = dense(input_tensor)
output_tensor2 = TimeDistributed(dense)(input_tensor)
print(output_tensor1.shape)
print(output_tensor2.shape)
(2, 4, 5)
(2, ?, 5)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
output1 = sess.run(output_tensor1)
output2 = sess.run(output_tensor2)
print(output1 - output2)
区别在于:
[[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]]
我正在构建一个模型,该模型使用循环层 (GRU) 将一个字符串转换为另一个字符串。我已经尝试将 Dense 和 TimeDistributed(Dense) 层作为最后一层,但我不明白使用 return_sequences=True 时两者之间的区别,尤其是因为它们似乎具有相同数量的参数。
我的简化模型如下:
InputSize = 15
MaxLen = 64
HiddenSize = 16
inputs = 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 Sequential
from keras.layers import Dense, Activation, TimeDistributed
from keras.layers.recurrent import GRU
import numpy as np
InputSize = 15
MaxLen = 64
HiddenSize = 16
OutputSize = 8
n_samples = 1000
model1 = 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())
在上面的示例架构中,model1
和 model2
是样本(序列到序列模型),model3
是完整序列到标签模型。
这是一段验证 TimeDistirbuted(Dense(X))
与 Dense(X)
相同的代码:
import numpy as np
from keras.layers import Dense, TimeDistributed
import tensorflow as tf
X = np.array([ [[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
],
[[3, 1, 7],
[8, 2, 5],
[11, 10, 4],
[9, 6, 12]
]
]).astype(np.float32)
print(X.shape)
(2, 4, 3)
dense_weights = np.array([[0.1, 0.2, 0.3, 0.4, 0.5],
[0.2, 0.7, 0.9, 0.1, 0.2],
[0.1, 0.8, 0.6, 0.2, 0.4]])
bias = np.array([0.1, 0.3, 0.7, 0.8, 0.4])
print(dense_weights.shape)
(3, 5)
dense = Dense(input_dim=3, units=5, weights=[dense_weights, bias])
input_tensor = tf.Variable(X, name='inputX')
output_tensor1 = dense(input_tensor)
output_tensor2 = TimeDistributed(dense)(input_tensor)
print(output_tensor1.shape)
print(output_tensor2.shape)
(2, 4, 5)
(2, ?, 5)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
output1 = sess.run(output_tensor1)
output2 = sess.run(output_tensor2)
print(output1 - output2)
区别在于:
[[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]]