双向GRU如何获取序列输出、隐藏状态及单元状态?
双向GRU解包报错:返回值数量不符合预期问题解答
问题复现
尝试编写双向GRU编码器代码,期望获取序列输出、前向/反向隐藏状态、单元状态时,代码如下:
encoder_gru = Bidirectional(GRU(nb_gru_cells,return_sequences=True, return_state=True)) encoder_outputs, encoder_state_fwd_h, encoder_state_fwd_c, encoder_state_bwd_h, encoder_state_bwd_c = encoder_gru(encoder_inputs)
运行抛出异常:
ValueError: not enough values to unpack (expected 5, got 3)
核心原因
报错本质是混淆了GRU和LSTM的结构差异,同时对Bidirectional包装器的返回规则不熟悉:
- GRU不存在单元状态(cell state):和LSTM同时维护隐藏状态h、单元状态c的结构不同,GRU仅靠隐藏状态传递信息,无论怎么设置参数,单向GRU都不会返回c相关的张量。
当设置return_sequences=True, return_state=True时,单向GRU仅返回2个值:所有时间步的序列输出、最后一个时间步的隐藏状态h。 - Bidirectional包装器不会自动拼接前后向的状态,只会按顺序拼接前向层、反向层的返回值。因此双向GRU在上述参数设置下,固定返回3个值,顺序为:
- 双向拼接后的序列输出:最后一维维度为
2*nb_gru_cells,是每个时间步前向、反向隐藏状态的拼接结果 - 前向GRU最后一个时间步的隐藏状态
fwd_h - 反向GRU最后一个时间步的隐藏状态
bwd_h
- 双向拼接后的序列输出:最后一维维度为
- 你代码中预期接收的
encoder_state_fwd_c、encoder_state_bwd_c两个单元状态变量,在GRU结构中根本不存在,属于错误套用了双向LSTM的返回值规则——双向LSTM因为单向层本身会返回序列、h、c三个值,最终才会返回总共5个值。
修正方案
删除两个不存在的单元状态接收变量即可,正确写法:
encoder_gru = Bidirectional(GRU(nb_gru_cells,return_sequences=True, return_state=True)) encoder_outputs, encoder_state_fwd_h, encoder_state_bwd_h = encoder_gru(encoder_inputs)
如果后续需要将双向GRU的最终状态作为解码器初始状态,手动拼接前后向隐藏状态即可:
from tensorflow.keras.layers import Concatenate encoder_final_h = Concatenate()([encoder_state_fwd_h, encoder_state_bwd_h])
内容的提问来源于stack exchange,提问作者S.San
相关产品推荐
相关产品推荐

