为什么 Tensorflow 双向 LSTM 不匹配前向和后向 LSTM?

问题描述 投票:0回答:2

在 Tensorflow 2.x 中,双向层默认的 merge_mode 为

concat
,如下所示。

tf.keras.layers.Bidirectional(
    layer, merge_mode='concat', weights=None, backward_layer=None, **kwargs
)

但是,为什么

fb_out
不是
f_out
b_out
的串联,如下面的测试代码所示?

>>> import copy
>>> inputs = tf.random.normal([1, 5, 10])
>>> forward_layer = LSTM(1, return_sequences=True)
>>>
>>> backward_layer = LSTM(1, return_sequences=True, go_backwards=True)
>>>
>>> f_copy = copy.deepcopy(forward_layer)
>>>
>>> b_copy = copy.deepcopy(backward_layer)
>>>
>>> fb = Bidirectional(forward_layer, backward_layer=backward_layer)
>>>
>>> f_out = f_copy(inputs)
>>> b_out = b_copy(inputs)
>>>
>>> fb_out = fb(inputs)
>>> f_out
<tf.Tensor: shape=(1, 5, 1), dtype=float32, numpy=
array([[[ 0.11658007],
        [-0.0704283 ],
        [-0.17762654],
        [ 0.0304627 ],
        [-0.19515464]]], dtype=float32)>
>>> b_out
<tf.Tensor: shape=(1, 5, 1), dtype=float32, numpy=
array([[[-0.18902111],
        [-0.00259904],
        [ 0.23515013],
        [ 0.22268802],
        [ 0.4035125 ]]], dtype=float32)>
>>> fb_out
<tf.Tensor: shape=(1, 5, 2), dtype=float32, numpy=
array([[[ 0.21822408,  0.07384206],
        [ 0.0036808 , -0.0700341 ],
        [-0.11105614, -0.38493848],
        [-0.13826807, -0.12408008],
        [ 0.05806111, -0.05853282]]], dtype=float32)>
python tensorflow lstm
2个回答
2
投票

BiDirectional的原理并不像向前和向后求和那么简单。 BiLSTM 的输出将在两个方向上进行处理,它们的组合将由 LSTM 的 tanh 和 sigmoid 门决定。因此,如果将其分为2个过程,结果不可能相同。一种用于原始双向输入的权重学习,一种用于 2 个独立的层。


0
投票

这个回复似乎有点晚了,但我希望它能对其他人有所帮助......

好吧,keras 中的双向层的行为类似于合并(求和/连接等)两个常规 LSTM,但它不会负责初始化权重,这就是为什么你有不同的输出。

例如,您有一个简单的输入,每个步骤有 3 个时间戳和 2 个特征。

import tensorflow as tf

unit = 1
dim = 2
timestamp = 3
inputs = tf.random.normal([1, timestamp, dim])

我们设置三层:前向 LSTM、后向 LSTM 和双向层。

forward_layer = tf.keras.layers.LSTM(unit, return_sequences=True)
backward_layer = tf.keras.layers.LSTM(unit, return_sequences=True, 
                                      go_backwards=True)
fb = tf.keras.layers.Bidirectional(forward_layer, backward_layer=backward_layer)

forward_layer.build((None, timestamp, dim))
backward_layer.build((None, timestamp, dim))
fb.build((None, timestamp, dim))

只需检查初始化的权重,您就会看到双向层为前向部分初始化了一组新的权重,但为后向部分使用了相同的权重集。如果相应地重置权重,您最终可以获得相同的结果。

a, b, c = forward_layer.get_weights()
a1, b1, c1 = backward_layer.get_weights()
a2, b2, c2 , a3, b3, c3 = fb.get_weights()

fb.set_weights([a, b, c, a1, b1, c1])

forward_layer(inputs)
array([[[ 0.0342516 ],
    [ 0.0213093 ],
    [-0.06462004]]], dtype=float32)>

backward_layer(inputs)
array([[[-0.08782256],
    [-0.16806953],
    [-0.17708375]]], dtype=float32)>

fb(inputs)
array([[[ 0.0342516 , -0.17708375],
    [ 0.0213093 , -0.16806953],
    [-0.06462004, -0.08782256]]], dtype=float32)>
© www.soinside.com 2019 - 2024. All rights reserved.