数据预处理部分和上一篇一样,就不啰嗦了。重点看一下模型构造:
1. Attention层:核心在于对encoder端隐层权重进行计算
比如我们准备生成“machine”这个词:
- s_prev是"love"输出的隐层状态
- s_prev与Bi-LSTM隐层状态蓝色框a一起concat后,通过激活函数softmax输出权重红色框α(此时看到α3“机器”的attention线最粗)
- 再和Bi-LSTM隐层状态蓝色框a进行加权求和,得到“machine”的context vector(就是我们之前说的向量S)
- 最后将这个context vector(向量S)给Decoder进行处理
# 将s_prev复制Tx次
s_prev = repeator(s_prev)
# 拼接BiRNN隐层状态与s_prev
concat = concatenator([a, s_prev])
# 计算energies
e = densor_tanh(concat)
energies = densor_relu(e)
# 计算weights
alphas = activator(energies)
# 加权得到Context Vector
context = dotor([alphas, a])
return context
2.Embedding层:Embedding层是将输入的序列数字编码转化为词向量,能够使Encoder捕捉到句子的语义信息
# 加载预训练好的glove词向量
with open("data/glove.6B.100d.txt", 'r') as f:
words = set()
word_to_vec_map = {}
for line in f:
line = line.strip().split()
curr_word = line[0]
words.add(curr_word)
word_to_vec_map[curr_word] = np.array(line[1:], dtype=np.float64)
构造Embedding层并加载预训练好的词向量(这里使用的是100维)
vocab_len = len(source_vocab_to_int) + 1 # Keras Embedding的API要求+1
emb_dim = word_to_vec_map["the"].shape[0]
# 初始化embedding矩阵
emb_matrix = np.zeros((vocab_len, emb_dim))
# 用词向量填充embedding矩阵
for word, index in source_vocab_to_int.items():
word_vector = word_to_vec_map.get(word, np.zeros(emb_dim))
emb_matrix[index, :] = word_vector
# 定义Embedding层,并指定不需要训练该层的权重
embedding_layer = Embedding(vocab_len, emb_dim, trainable=False)
# build
embedding_layer.build((None,))
# set weights
embedding_layer.set_weights([emb_matrix])
return embedding_layer
获取embedding_layer
# 获取Embedding layer
embedding_layer = pretrained_embedding_layer(word_to_vec_map, source_vocab_to_int)
3.模型构造
- 在Encoder端,对输入句子进行学习,求得当前的Context Vector,并将其传递给Decoder处理;
- 在Decoder端,以t-1的输出和当前Context Vector作为LSTM输入,翻译得到结果。
# 定义输入层
X = Input(shape=(Tx,))
# Embedding层
embed = embedding_layer(X)
# Decoder端LSTM的初始状态
s0 = Input(shape=(n_s,), name='s0')
c0 = Input(shape=(n_s,), name='c0')
# Decoder端LSTM的初始输入
out0 = Input(shape=(target_vocab_size, ), name='out0')
out = reshapor(out0)
s = s0
c = c0
# 模型输出列表,用来存储翻译的结果
outputs = []
# 定义Bi-LSTM
a = Bidirectional(LSTM(n_a, return_sequences=True))(embed)
# Decoder端,迭代Ty轮,每轮生成一个翻译结果
for t in range(Ty):
# 获取Context Vector
context = one_step_attention(a, s)
# 将Context Vector与上一轮的翻译结果进行concat
context = concator([context, reshapor(out)])
s, _, c = decoder_LSTM_cell(context, initial_state=[s, c])
# 将LSTM的输出结果与全连接层链接
out = output_layer(s)
# 存储输出结果
outputs.append(out)
model = Model([X, s0, c0, out0], outputs)
return model
4. 预测与评估
这里使用的是BLEU: Bilingual Evaluation Understudy.是一种反映翻译文本和参考文本相似度的评估指标。
from nltk.translate.bleu_score import sentence_bleu
# 计算BLEU分数
score = sentence_bleu([reference.split()], pred.split())
image.png
网友评论