为什么Tensorflow双向LSTM不匹配正向和反向LSTM?

kxeu7u2r  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(95)

在Tensorflow 2.x中,Bidirectional层的默认merge_mode是concat,如下所示。

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

但是,为什么fb_out不是f_outb_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)>
b1zrtrql

b1zrtrql1#

双向的原理并不像你把向前和向后的总和那么简单。BiLSTM的输出将在两个方向上进行处理,它们的组合将由LSTM的tanh和sigmoid门决定。因此,如果你把它分成两个过程,结果不可能是一样的。一个用于原始双向输入的权重学习,一个用于2个分离的层。

7ajki6be

7ajki6be2#

这似乎是晚了这个答案,但我希望它会帮助任何人...
好吧,keras中的双向层做了类似于合并(sum/concat等)两个常规LSTM的行为,但它不会处理初始化权重,这就是为什么你有不同的输出。
例如,您有一个简单的输入,每个步骤有3个时间戳和2个特征。

import tensorflow as tf

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

让我们有三个层次:前向LSTM、后向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)>

相关问题