【问题标题】:How to pass initial hidden state to the lstm layer?如何将初始隐藏状态传递给 lstm 层?
【发布时间】:2020-04-30 07:09:39
【问题描述】:

我想将自定义初始状态传递给 lstm 输出,但我只有一个隐藏状态,所以如何传递零初始状态。

from tensorflow.keras import layers

x = layers.Input((None,))
x = layers.Embedding(....)(x)
x = layers.Flatten()(x)
imp_vec = Dense()(x)

现在我想使用 imp_vec 作为隐藏的初始状态并将其传递给解码器 lstm

out, states = layers.LSTM(...., return_state=True)(inputs, initial_state=[imp_vec])

以上代码返回值错误:,

ValueError: An `initial_state` was passed that is not compatible with `cell.state_size`. Received `state_spec`=ListWrapper([InputSpec(shape=(None, 200), ndim=2)]); however `cell.state_size` is [10, 10]

我发现 lstm 需要两个状态作为初始状态(即 hidden_​​state、cell_state)对吗?但是我只有一个隐藏状态向量可以将其传递给模型,所以我怎样才能只初始化 hidden_​​state 并让 lstm 自动用零初始化另一个?

【问题讨论】:

    标签: python python-3.x tensorflow lstm tensorflow2.0


    【解决方案1】:

    LSTM 有两种状态,但您只传递一个输入。因此有几个选择

    选项 1:使用 GRU 代替 LSTM

    GRU 只有一种状态,initial_state=imp_vec 可以正常工作。

    选项 2:创建两个不同的状态

    创建imp_vec_1imp_vec_2 而不是单个imp_vec 并将其传递为,

    layers.LSTM(..)(..., initial_state=[imp_vec_1, imp_vec_2])
    

    请记住,LSTM 图层按h_statec_state 的顺序排列。

    选项 3:将 c_state 设为零

    如果您不想传递 c_state,只需传递一组零。

    zero_out = layers.Lambda(lambda x: tf.zeros_like(x))(imp_vec)
    layers.LSTM(..)(..., initial_state=[imp_vec, zero_out])
    

    【讨论】:

    • @thushv86 谢谢,我只是有一个疑问,tf.zeros_like(x) 中的x 指的是什么?它应该是什么形状?
    • @user_12,所以这是获得与imp_vec 具有完全相同形状的充满零的状态的技巧。因为hc 状态的大小相同。这是一个很好的方法,因为即使批量维度为None,它也允许它工作。
    • 如果您看到我在问题中给出的架构,x 指的是扁平层,对吧?所以如果我们使用tf.zeros_like(x),这不是相同形状的扁平层吗?您的意思是imp_veczero_out 的形状相同吗?
    • 是的,形状完全相同。 LSTM 具有两种状态的精确形状
    • 隐藏状态 (h) 是第一个状态,单元格状态 (c) 是第二个。