在 Tensorflow 2.0 中的简单 LSTM 层之上添加 Attention

2024-05-09

我有一个由一个 LSTM 和两个 Dense 层组成的简单网络,如下所示:

model = tf.keras.Sequential()
model.add(layers.LSTM(20, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(layers.Dense(20, activation='sigmoid'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(loss='mean_squared_error')

它对具有 3 个输入(标准化 0 到 1.0)和 1 个输出(二进制)的数据进行训练,以进行分类。数据是时间序列数据,其中时间步之间存在关系。

    var1(t)   var2(t)   var3(t)  var4(t)
0  0.448850  0.503847  0.498571      0.0
1  0.450992  0.503480  0.501215      0.0
2  0.451011  0.506655  0.503049      0.0

该模型的训练方式如下:

history = model.fit(train_X, train_y, epochs=2800, batch_size=40, validation_data=(test_X, test_y), verbose=2, shuffle=False)
model.summary()

给出模型摘要:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm (LSTM)                  (None, 20)                1920      
_________________________________________________________________
dense (Dense)                (None, 20)                420       
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 21        
=================================================================
Total params: 2,361
Trainable params: 2,361
Non-trainable params: 0

该模型运行得相当好。现在我尝试用注意力层替换 Dense(20) 层。所有在线示例、教程等(包括 TF 文档)都是针对在输入层具有嵌入层的 seq2seq 模型。我了解 TF v1.x 中的 seq2seq 实现,但我找不到任何有关我正在尝试执行的操作的文档。我相信新的 API (v2.0) 我需要做这样的事情:

lstm = layers.LSTM(20, input_shape=(train_X.shape[1], train_X.shape[2]), return_sequences=True)
lstm = tf.keras.layers.Bidirectional(lstm)
attention = layers.Attention() # this does not work

model = tf.keras.Sequential()
model.add(lstm)
model.add(attention)
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(loss='mean_squared_error')

当然我得到了错误“注意力层必须在输入列表上调用,即 [query, value] 或 [query, value, key]"

我不明白版本(2.0)和这种情况(具有固定长度输入的时间序列数据)的解决方案。欢迎任何关于增加对此类问题的关注的想法。


我最终找到了这个问题的两个答案,都来自 pypi.org 上的库。第一个是自我关注 https://pypi.org/project/keras-self-attention/并且可以使用 Keras(Keras 的 TF 2.0 之前的集成版本)来实现,如下所示...

        model = keras.models.Sequential()
        model.add(keras.layers.LSTM(cfg.LSTM, input_shape=(cfg.TIMESTEPS,
                  cfg.FEATURES),
                  return_sequences=True))
        model.add(SeqSelfAttention(attention_width=cfg.ATTNWIDTH,
                attention_type=SeqSelfAttention.ATTENTION_TYPE_MUL,
                attention_activation='softmax',
                name='Attention'))
        model.add(keras.layers.Dense(cfg.DENSE))
        model.add(keras.layers.Dense(cfg.OUTPUT, activation='sigmoid'))

第二种方法是更通用的解决方案 https://pypi.org/project/attention/与 TF 2.0 后集成 Keras 一起使用,如下所示...

        model = tf.keras.models.Sequential()
        model.add(layers.LSTM(cfg.LSTM, input_shape=(cfg.SEQUENCES,
                  train_X.shape[2]),
                  return_sequences=True))
        model.add(Attention(name='attention_weight'))
        model.add(layers.Dense(train_Y.shape[2], activation='sigmoid'))

它们各自的行为略有不同,并产生截然不同的结果。自注意力库将维度从 3 减少到 2,并且在预测时您会得到每个输入向量的预测。一般注意力机制维护 3D 数据并输出 3D,并且在预测时您只能获得每批次的预测。如果您想要每个输入向量进行预测,您可以通过将预测数据重塑为批量大小为 1 来解决此问题。

至于结果,自注意力确实比单独的 LSTM 产生了更好的结果,但并不比其他增强功能更好,例如 dropout 或更密集的层等。一般注意力似乎并没有给 LSTM 模型带来任何好处,而且在许多方面案件让事情变得更糟,但我仍在调查。

无论如何,这是可以做到的,但到目前为止,是否应该这样做还值得怀疑。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Tensorflow 2.0 中的简单 LSTM 层之上添加 Attention 的相关文章

随机推荐