翻译自Tensorflow官方教程Neural machine translation with attention
声明:
- 本文将实现一个将西班牙语翻译成英语的seq2seq模型;
- 需要读者对seq2seq模型有了解;
- 需要读者对nlp中一些数据处理方式有了解;
- 翻译并非直译,会比原文更直白和丰富。
- 有些不重要的代码已通过
(不重要)
标记
我们准备训练一个seq2seq模型,将西班牙语翻译成英语。
在翻译中,原文本和翻译文本的词与词之间通常都有一定的对应关系。最理想的情况是:原文本的第 i i i个词对应翻译文本的第 i i i个词。当然大多数情况下不会有这么严格的对其关系。通过attention,我们可以得到如下图所示的混淆矩阵。
图中颜色鲜艳的部分表示横轴单词和纵轴单词关系密切,深蓝部分表示横轴单词和纵轴单词的关系疏远。这里的关系就是attention,显然,todavia
pay more attention to you than at
。
code part 1: 导入需要的包(不重要)
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from sklearn.model_selection import train_test_split
import unicodedata
import re
import numpy as np
import os
import io
import time
数据准备
数据介绍: 西班牙语到英语的翻译数据。
下载地址: http://www.manythings.org/anki/
数据示例: May I borrow this book? ¿Puedo tomar prestado este libro?
code part 2:下载数据集(不重要)
# Download the file
path_to_zip = tf.keras.utils.get_file(
'spa-eng.zip', origin='http://storage.googleapis.com/download.tensorflow.org/data/spa-eng.zip',
extract=True)
path_to_file = os.path.dirname(path_to_zip)+"/spa-eng/spa.txt"
数据下载后,我们要做一些数据处理工作,包括一下4点:
- 在每句话的首尾添加开始符和终止符;
- 删除特殊符号;
- 将文本型的单词转化成数值型的索引(也就是建立一个字典,可以完成word->id或者id->word的映射);
- padding每句话,使它们长度一致
code part 3: 数据处理(不重要)
# Converts the unicode file to ascii
def unicode_to_ascii(s):
return ''.join(c for c in unicodedata.normalize('NFD', s)
if unicodedata.category(c) != 'Mn')
def preprocess_sentence(w):
w = unicode_to_ascii(w.lower().strip())
# creating a space between a word and the punctuation following it
# eg: "he is a boy." => "he is a boy ."
# Reference:- https://stackoverflow.com/questions/3645931/python-padding-punctuation-with-white-spaces-keeping-punctuation
w = re.sub(r"([?.!,¿])", r" \1 ", w)
w = re.sub(r'[" "]+', " ", w)
# replacing everything with space except (a-z, A-Z, ".", "?", "!", ",")
w = re.sub(r"[^a-zA-Z?.!,¿]+", " ", w)
w = w.rstrip().strip()
# adding a start and an end token to the sentence
# so that the model know when to start and stop predicting.
w = '<start> ' + w + ' <end>'
return w
en_sentence = u"May I borrow this book?"
sp_sentence = u"¿Puedo tomar prestado este libro?"
print(preprocess_sentence(en_sentence))
print(preprocess_sentence(sp_sentence).encode('utf-8'))
输出如下所示:
<start> may i borrow this book ? <end>
b'<start> \xc2\xbf puedo tomar prestado este libro ? <end>'
# 1. Remove the accents
# 2. Clean the sentences
# 3. Return word pairs in the format: [ENGLISH, SPANISH]
def create_dataset(path, num_examples):
lines = io.open(path, encoding='UTF-8').read().strip().split('\n')
word_pairs = [[preprocess_sentence(w) for w in l.split('\t')] for l in lines[:num_examples]]
return zip(*word_pairs)
en, sp = create_dataset(path_to_file, None)
print(en[-1])
print(sp[-1])
输出如下所示:
<start> if you want to sound like a native speaker , you must be willing to practice saying the same sentence over and over in the same way that banjo players practice the same phrase over and over until they can play it correctly and at the desired tempo . <end>
<start> si quieres sonar como un hablante nativo , debes estar dispuesto a practicar diciendo la misma frase una y otra vez de la misma manera en que un musico de banjo practica el mismo fraseo una y otra vez hasta que lo puedan tocar correctamente y en el tiempo esperado . <end>
def max_length(tensor):
return max(len(t) for t in tensor)
def tokenize(lang):
lang_tokenizer = tf.keras.preprocessing.text.Tokenizer(
filters='')
lang_tokenizer.fit_on_texts(lang)
tensor = lang_tokenizer.texts_to_sequences(lang)
tensor = tf.keras.preprocessing.sequence.pad_sequences(tensor,
padding='post')
return tensor, lang_tokenizer
构造一个包含30000样本的数据集
code part 4:构造一个包含3000样本的数据集(不重要)
def load_dataset(path, num_examples=None):
# creating cleaned input, output pairs
targ_lang, inp_lang = create_dataset(path, num_examples)
input_tensor