吴恩达团队NLP C4_W1_Assignment
任务:建立神经机器翻译模型(英语< — >德语)
Part1:数据准备
1.1 库的准备
1 | from termcolor import colored |
1.2 导入数据
1 | train_stream_fn = trax.data.TFDS('opus/medical', |
1.3 标记化和格式化
将字符串分割为一个个的单词,并转化为数字,同时只留下简单的原词:
- 如单词表中有
fear,some,fearsome
,可以只要fear,some
,因为fearsome
可通过其他单词组合而成
1 | # global variables that state the filename and directory of the vocabulary file |
1 | (array([ 2326, 13139, 605, 9214, 3337, 7932, 1047, 15, 1489, |
然后,在每个单词结尾加上一个结束标志,有助于推理/预测
1 | EOS = 1 |
最后,我们过滤长句,限制每个句子的标记数量
1 | filtered_train_stream = trax.data.FilterByLength( |
1 | Single tokenized example input: [ 8569 4094 2679 32826 22527 5 30650 4729 992 1] |
1.4 标记化和取消标记化辅助函数
1 | def tokenize(input_str, vocab_file=None, vocab_dir=None): |
1.5 Bucketing
我们将长度相似的句子放在一起,并提供最小的填充,如下图所示:
1 | boundaries = [8, 16, 32, 64, 128, 256, 512] |
Part2:神经机器翻译模型
2.1 Input encoder
创建嵌入,并送至LSTM网络将输出激活
1 | def input_encoder_fn(input_vocab_size, d_model, n_encoder_layers): |
2.2 Pre-attention decoder
在targets上运行。用于查询的激活
tl.ShiftRight
:会在目标开头添加一个标记,如[8, 34, 12] → [0, 8, 34, 12]
1 | def pre_attention_decoder_fn(mode, target_vocab_size, d_model): |
2.3 为注意力层准备输入
1 | def prepare_attention_input(encoder_activations, decoder_activations, inputs): |
2.4 实现机器翻译模型
1 | def NMTAttn(input_vocab_size=33300, |
Part3:训练模型
3.1 TrainTask
计算损失,更新权重
1 | train_task = training.TrainTask( |
3.2 EvalTask
查看模型在运行时的训练情况,观察交叉熵损失和准确性
1 | eval_task = training.EvalTask( |
3.3 Loop
1 | # define the output directory |
Part4:测试模型
首先加载刚才训练的模型
1 | # instantiate the model we built in eval mode |
4.1 贪婪解码,获取最高概率的单词
实现next_symbol()
,返回下一个单词的索引
1 | def next_symbol(NMTAttn, input_tokens, cur_output_tokens, temperature): |
多次利用上述函数,实现句子的翻译
1 | def sampling_decode(input_sentence, NMTAttn = None, temperature=0.0, vocab_file=None, vocab_dir=None): |
4.2 最小Bayes-Risk解码
- 随机抽取样本
- 其他的样本对这些抽取的样本每个进行评分
- 选择得分最高的一个
- 首先产生样本
1 | def generate_samples(sentence, n_samples, NMTAttn=None, temperature=0.6, vocab_file=None, vocab_dir=None): |
- 比较重叠的分数
1 | def jaccard_similarity(candidate, reference): |
ROUGE分数公式如下:
1 | def rouge1_similarity(system, reference): |
- 将每个样本与所有其他样本进行比较,计算平均分
1 | def average_overlap(similarity_fn, samples, *ignore_params): |
利用加权平均值来计算分数
1 | def weighted_avg_overlap(similarity_fn, samples, log_probs): |
- 把之前的步骤整合在一起,实现
mbr_decode()
函数
1 | def mbr_decode(sentence, n_samples, score_fn, similarity_fn, NMTAttn=None, temperature=0.6, vocab_file=None, vocab_dir=None): |