【问题标题】:How to add an attention mechanism in keras?如何在 keras 中添加注意力机制?
【发布时间】:2017-08-12 14:34:42
【问题描述】:

我目前正在使用从one discussion on github 获得的这段代码 这里是注意力机制的代码:

_input = Input(shape=[max_length], dtype='int32')

# get the embedding layer
embedded = Embedding(
        input_dim=vocab_size,
        output_dim=embedding_size,
        input_length=max_length,
        trainable=False,
        mask_zero=False
    )(_input)

activations = LSTM(units, return_sequences=True)(embedded)

# compute importance for each step
attention = Dense(1, activation='tanh')(activations)
attention = Flatten()(attention)
attention = Activation('softmax')(attention)
attention = RepeatVector(units)(attention)
attention = Permute([2, 1])(attention)


sent_representation = merge([activations, attention], mode='mul')
sent_representation = Lambda(lambda xin: K.sum(xin, axis=-2), output_shape=(units,))(sent_representation)

probabilities = Dense(3, activation='softmax')(sent_representation)

这是正确的方法吗?我有点期待时间分布层的存在,因为注意力机制分布在 RNN 的每个时间步。我需要有人确认这个实现(代码)是注意力机制的正确实现。谢谢。

【问题讨论】:

标签: python keras


【解决方案1】:

如果您想关注时间维度,那么您的这部分代码对我来说似乎是正确的:

activations = LSTM(units, return_sequences=True)(embedded)

# compute importance for each step
attention = Dense(1, activation='tanh')(activations)
attention = Flatten()(attention)
attention = Activation('softmax')(attention)
attention = RepeatVector(units)(attention)
attention = Permute([2, 1])(attention)

sent_representation = merge([activations, attention], mode='mul')

你已经计算出形状(batch_size, max_length)的注意力向量:

attention = Activation('softmax')(attention)

我以前从未见过这段代码,所以我不能说这是否真的正确:

K.sum(xin, axis=-2)

进一步阅读(你可以看看):

【讨论】:

  • 你好,菲利普!检查 Bahdanau 等人的原始论文。等,您的实现与建议的方法之间似乎存在一些差距,即权重矩阵的维度和分数计算。如果这是一种自我注意的实现,正如@felixhao28 在您的回购中所建议的那样,那么类似的差距再次存在。可能是我不知道这种类型的实现,您介意分享您的实现基于哪篇论文或研究吗?
  • 注意力有很多种。 Bahdanau 的原始论文第一次引入了注意力,而且很复杂。现在有更简单的版本可以完成这项工作。 OP 的做法很好,只需稍作改动即可使其正常工作,如下所示
【解决方案2】:

注意力机制关注句子的不同部分:

activations = LSTM(units, return_sequences=True)(embedded)

它通过

来确定该句子的每个隐藏状态的贡献
  1. 计算每个隐藏状态的聚合 attention = Dense(1, activation='tanh')(activations)
  2. 为不同的状态分配权重 attention = Activation('softmax')(attention)

最后注意不同的状态:

sent_representation = merge([activations, attention], mode='mul')

这部分我不太明白:sent_representation = Lambda(lambda xin: K.sum(xin, axis=-2), output_shape=(units,))(sent_representation)

了解更多可以参考thisthis,还有这个one给出了很好的实现,看你自己能不能理解更多。

【讨论】:

    【解决方案3】:

    最近我在密集层上应用注意力机制,这里是一个示例实现:

    def build_model():
      input_dims = train_data_X.shape[1]
      inputs = Input(shape=(input_dims,))
      dense1800 = Dense(1800, activation='relu', kernel_regularizer=regularizers.l2(0.01))(inputs)
      attention_probs = Dense( 1800, activation='sigmoid', name='attention_probs')(dense1800)
      attention_mul = multiply([ dense1800, attention_probs], name='attention_mul')
      dense7 = Dense(7, kernel_regularizer=regularizers.l2(0.01), activation='softmax')(attention_mul)   
      model = Model(input=[inputs], output=dense7)
      model.compile(optimizer='adam',
                    loss='categorical_crossentropy',
                    metrics=['accuracy'])
      return model
    
    print (model.summary)
    
    model.fit( train_data_X, train_data_Y_, epochs=20, validation_split=0.2, batch_size=600, shuffle=True, verbose=1)
    

    【讨论】:

    • 嘿,感谢您关注这个玩具示例,但我可以提供一些建议吗?按原样编写完整模型,而不是 baseline_model()。就像 AryoPradiptaGema 如何编写模型一样。你能用数学i.stack.imgur.com/pyqhn.gif解释模型吗?例如attention_probs 可能是等式中的ut,类似attention_mul==v^T*ut .etc。我也在学习注意力模型,你的就是对注意力最直观、最简单的解释。
    【解决方案4】:

    我想你可以试试下面的代码,用 LSTM 网络添加 keras 自注意力机制

        from keras_self_attention import SeqSelfAttention
    
        inputs = Input(shape=(length,))
        embedding = Embedding(vocab_size, EMBEDDING_DIM, weights=[embedding_matrix], input_length=MAX_SEQUENCE_LENGTH, trainable=False)(inputs)
        lstm = LSTM(num_lstm, input_shape=(X[train].shape[0], X[train].shape[1]), return_sequences=True)(embedding)
        attn = SeqSelfAttention(attention_activation='sigmoid')(lstm)
        Flat = Flatten()(attn)
        dense = Dense(32, activation='relu')(Flat)
        outputs = Dense(3, activation='sigmoid')(dense)
        model = Model(inputs=[inputs], outputs=outputs)
        model.compile(loss='binary_crossentropy', optimizer=Adam(0.001), metrics=['accuracy'])
        model.fit(X_train, y_train, epochs=10, batch_size=32,  validation_data=(X_val,y_val), shuffle=True)
    

    【讨论】:

      【解决方案5】:

      虽然提供了许多不错的替代方案,但我已尝试修改您共享的代码以使其正常工作。我还回答了您迄今为止尚未解决的其他问题:

      第一季度。这是正确的做法吗? 注意层本身看起来不错。无需更改。您使用注意力层输出的方式可以稍微简化和修改,以结合最近的一些框架升级。

          sent_representation = merge.Multiply()([activations, attention])
          sent_representation = Lambda(lambda xin: K.sum(xin, axis=1))(sent_representation)
      

      你现在可以出发了!

      第二季度。我有点期待时间分布层的存在,因为注意力机制分布在 RNN 的每个时间步中

      不,您不需要时间分布层,否则权重将跨时间步共享,这不是您想要的。

      其他具体细节可以参考:https://towardsdatascience.com/create-your-own-custom-attention-layer-understand-all-flavours-2201b5e8be9e

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-20
        • 2019-05-22
        • 2019-04-08
        • 1970-01-01
        • 1970-01-01
        • 2022-07-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多