在Tensorflow 2.0的简单LSTM层之上添加关注

时间:2019-11-21 03:32:21

标签: python tensorflow keras lstm attention-model

我有一个包含一个LSTM和两个密集层的简单网络,

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

该模型运行良好。现在,我尝试用Attention层替换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)和这种情况下(具有固定长度输入的时间序列数据),我不理解此解决方案。欢迎您提出任何有关注意此类问题的想法。

2 个答案:

答案 0 :(得分:0)

您必须像这样调用关注层:

attention = layers.Attention()([#a list of input layers to the attention layer here])

The API documentation here

答案 1 :(得分:0)

我最终从pypi.org上的库中找到了该问题的两个答案。第一个是self-attention,可以通过Keras(Keras的TF 2.0集成版之前的版本)实现,如下所示...

preg_match('/\( *(.*) +as *(.*)\)$/is', $expression, $matches);

$iteratee = trim($matches[1]);

第二种方法是使用more general solution与TF 2.0集成后Keras配合使用,如下所示...

        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'))

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

关于结果,自我注意的确比单独的LSTM产生了更好的结果,但并不比其他增强效果更好,例如辍学或更密集的层次等。一般的关注似乎并没有给LSTM模型带来任何好处并且在很多情况下会使情况变得更糟,但我仍在调查中。

在任何情况下都可以做到,但是到目前为止,是否应该这样做还很可疑。

相关问题