Keras 注意力层
适用于 Keras 的注意力层。支持 Luong 和 Bahdanau 的评分函数。
已通过 Tensorflow 2.8, 2.9, 2.10, 2.11, 2.12, 2.13 和 2.14 测试(2023 年 9 月 26 日)。
安装
PyPI
pip install attention
注意力层
Attention(
units=128,
score='luong',
**kwargs
)
参数
-
units
:整数。注意力向量 ($a_t$) 中的(输出)单元数量。 -
score
:字符串。评分函数 $score(h_t, \bar{h_s})$。可能的值是luong
或bahdanau
。
输入形状
形状为 (batch_size, timesteps, input_dim)
的 3D 张量。
输出形状
- 形状为
(batch_size, num_units)
($a_t$) 的 2D 张量。
如果你想查看注意力权重,可以参考这个例子 examples/add_two_numbers.py。
示例
import numpy as np
from tensorflow.keras import Input
from tensorflow.keras.layers import Dense, LSTM
from tensorflow.keras.models import load_model, Model
from attention import Attention
def main():
# 虚拟数据。在此示例中没有任何需要学习的内容。
num_samples, time_steps, input_dim, output_dim = 100, 10, 1, 1
data_x = np.random.uniform(size=(num_samples, time_steps, input_dim))
data_y = np.random.uniform(size=(num_samples, output_dim))
# 定义/编译模型。
model_input = Input(shape=(time_steps, input_dim))
x = LSTM(64, return_sequences=True)(model_input)
x = Attention(units=32)(x)
x = Dense(1)(x)
model = Model(model_input, x)
model.compile(loss='mae', optimizer='adam')
model.summary()
# 训练。
model.fit(data_x, data_y, epochs=10)
# 测试保存/重新加载模型。
pred1 = model.predict(data_x)
model.save('test_model.h5')
model_h5 = load_model('test_model.h5', custom_objects={'Attention': Attention})
pred2 = model_h5.predict(data_x)
np.testing.assert_almost_equal(pred1, pred2)
print('成功。')
if __name__ == '__main__':
main()
其他示例
浏览 examples。
在运行示例之前安装依赖项:pip install -r examples/examples-requirements.txt
。
IMDB 数据集
在此实验中,我们展示了使用注意力在 IMDB 数据集上可以获得更高的准确性。我们考虑两个 LSTM 网络:一个有此注意力层,另一个有全连接层。这两个模型具有相同数量的参数 (250K),以进行公平的比较。
以下是 10 次运行的结果。对于每次运行,我们记录为期 10 轮训练中测试集上的最大准确率。
测量 | 无注意力 (250K 参数) | 注意力 (250K 参数) |
---|---|---|
最大准确率 | 88.22 | 88.76 |
平均准确率 | 87.02 | 87.62 |
标准差准确率 | 0.18 | 0.14 |
正如预期的那样,使用注意力的模型准确性有所提升。它还减少了运行之间的变异性,这是一个很好的特性。
计算两个数的和
让我们考虑一个任务:将一些分隔符 (此处为 0) 之后出现的两个数字相加:
x = [1, 2, 3, 0, 4, 5, 6, 0, 7, 8]
。结果是 y = 4 + 7 = 11
。
我们期望在分隔符之后注意力最高。下面展示了训练的概述,其中顶部代表注意力图,底部代表真实值。随着训练的进行,模型学习任务并且注意力图接近真实值。
查找序列的最大值
我们考虑多个等长的一维序列。任务是找到每个序列的最大值。
我们将由 RNN 层处理的完整序列传递给注意力层。我们期望注意力层聚焦于每个序列的最大值。
经过几轮训练后,注意力层完美地收敛到我们期望的结果。