在keras中为RNN实现自定义单元格时,是否有方法在给定的时间步长内返回多个输出?例如,具有形状的输出:(sequences=[batch,timesteps,hidden_units],other_outputs=[batch,timesteps,arbitrary_units],last_hidden_states=[batch,hidden_units])
我这样做的动机源于“用于总结的变分顺序学习中的自注意力”(Chien,ISCA 2019)的算法1“循环解码器”,它“累积变分目标”,因此必须跟踪给定循环时间步的多个输出。
对于keras RNN,如果在示例化图层时传递return_sequences=True
和return_state=True
参数,则通过RNN的前向传递的输出为([batch,timesteps,hidden_units],[batch,hidden_units]),它们分别是所有时间步的隐藏状态和最后隐藏状态。我想使用RNN跟踪每个时间步的其他输出,我想我可以在自定义单元格类中更改output_size
属性,但我不确定这是否有效,因为TensorFlow RNN文档似乎表明每个时间步只能输出一个输出(即“单个整数或TensorShape”):
output_size属性。这可以是一个整数或TensorShape,表示输出的形状。出于向后兼容的原因,如果此属性不适用于单元格,则值将由state_size的第一个元素推断。
这是我迄今为止自定义实现的“RNN单元”:
class CustomGRUCell(tf.keras.layers.Layer):
def __init__(self, units, arbitrary_units, **kwargs):
super().__init__(**kwargs)
self.units = units
# Custom computation for a timestep t
self.dense = tf.keras.layers.Dense(units=arbitrary_units)
# The RNN cell
self.gru = tf.keras.layers.GRUCell(units=self.units)
# Required for custom cells...
self.state_size = tf.TensorShape([self.units])
# PERHAPS I CHANGE THIS????
self.output_size = tf.TensorShape([self.units])
def call(self, input_at_t, states_at_t):
"""Forward pass that uses a constant to modify the hidden state.
:param inputs_at_t: (batch, features) tensor from (batch, t, features)
inputs
:param states_at_t: <class 'tuple'> Why? Perhaps generically,
this is because an LSTM for example takes two hidden states
instead of just one like the GRU
:param constants: <class 'tuple'> Why? To accomodate multiple
constants
"""
# Standard GRU cell call
output_at_t, states_at_t_plus_1 = self.gru(input_at_t, states_at_t)
# Another output at particular timestep t
special_output_at_t = self.dense(input_at_t)
# The outputs
# 'output_at_t' will be automatically tracked by 'return_sequences'.... how do I track
# other comptuations at each timestep????
return [output_at_t, special_output_at_t], states_at_t_plus_1
然后我想让细胞像这样工作:
# Custom cell and rnn
custom_cell = CustomGRUCell(units=10, arbitrary_units=5)
custom_rnn = tf.keras.layers.RNN(cell=custom_cell, return_sequences=True, return_state=True)
# Arbitrary data
batch = 4
timesteps = 6
features = 8
dummy_data = tf.random.normal(shape=(batch, timesteps, features))
# The output I want
seqs, special_seqs, last_hidden_state = custom_rnn(inputs=dummy_data)
print('batch, timesteps, units):', seqs.shape)
print('batch, timesteps, arbitrary_units:', special_seqs.shape)
print('batch, units:', last_hidden_state.shape)
>>> batch, timesteps, units : (4, 6, 10)
>>> batch, timesteps, arbitrary_units: (4, 6, 5)
>>> batch, units: (4, 10)
1条答案
按热度按时间u0sqgete1#
解决了这个问题。你可以把输出大小做成一个任意维度的列表,然后RNN会跟踪输出。下面的类还包括在RNN调用中使用常量,因为前面提到的论文传递了一个编码器潜在空间(z_enc)给递归解码器: