Olá pessoal!
A segunda parte da tradução, que publicamos algumas semanas atrás, em preparação para o lançamento do segundo fluxo do curso
"Cientista de dados" . À frente é outro material interessante e uma lição aberta.
Enquanto isso, fomos mais longe na selva de modelos.
Modelo de tradução neuralEmbora o núcleo do modelo de sequência a sequência seja criado por funções de
tensorflow/tensorflow/python/ops/seq2seq.py
, ainda existem alguns truques usados em nosso modelo de tradução em
models/tutorials/rnn/translate/seq2seq_model.py
, sobre vale a pena mencionar.
Softmax amostrado e projeção de saídaComo mencionado acima, queremos usar o softmax amostrado para trabalhar com um grande dicionário de saída. Para decodificar, é necessário rastrear a projeção da saída. A perda softmax amostrada e a projeção de saída são geradas pelo código a seguir em
seq2seq_model.py
.
if num_samples > 0 and num_samples < self.target_vocab_size: w_t = tf.get_variable("proj_w", [self.target_vocab_size, size], dtype=dtype) w = tf.transpose(w_t) b = tf.get_variable("proj_b", [self.target_vocab_size], dtype=dtype) output_projection = (w, b) def sampled_loss(labels, inputs): labels = tf.reshape(labels, [-1, 1])
Primeiro, observe que apenas criamos softmax amostrado se o número de amostras (512 por padrão) for menor que o tamanho do dicionário de destino. Para dicionários menores que 512, é melhor usar a perda softmax padrão.
Em seguida, crie uma projeção da saída. Este é um par que consiste em uma matriz de pesos e um vetor de deslocamento. Quando usada, a célula rnn retorna os vetores de forma do número de amostras de treinamento por
size
, e não o número de amostras de treinamento por
target_vocab_size
. Para restaurar logits, você precisa multiplicá-lo pela matriz de pesos e adicionar um deslocamento, o que ocorre nas linhas 124-126 em
seq2seq_model.py
.
if output_projection is not None: for b in xrange(len(buckets)): self.outputs[b] = [tf.matmul(output, output_projection[0]) + output_projection[1] for ...]
Bucketing and paddingAlém do softmax amostrado, nosso modelo de tradução também usa o
bucketing , um método que permite gerenciar com eficiência frases de diferentes comprimentos. Para começar, explique o problema. Ao traduzir do inglês para o francês, temos sentenças em inglês de diferentes comprimentos L1 na entrada e sentenças em francês de diferentes comprimentos L1 na saída. Como a sentença em inglês é transmitida como
encoder_inputs
e a sentença em francês é exibida como
decoder_inputs
(com o prefixo do símbolo GO), é necessário criar um modelo seq2seq para cada par (L1, L2 + 1) de comprimentos de sentenças em inglês e francês. Como resultado, obtemos um gráfico enorme que consiste em muitos subgráficos semelhantes. Por outro lado, podemos “preencher” cada frase com caracteres especiais do PAD. E então precisamos de apenas um modelo seq2seq para comprimentos "compactados". Mas esse modelo será ineficaz em frases curtas - você precisa codificar e decodificar muitos caracteres inúteis do PAD.
Como um compromisso entre a criação de um gráfico para cada par de comprimentos e o preenchimento em um único comprimento, usamos um certo número de intervalos e preenchemos cada sentença pelo comprimento do grupo acima. No
translate.py
, usamos os seguintes grupos por padrão.
buckets = [(5, 10), (10, 15), (20, 25), (40, 50)]
Assim, se uma frase em inglês com 3 tokens chegar na entrada e a sentença francesa correspondente contiver 6 tokens na saída, eles irão para o primeiro grupo e serão preenchidos com o comprimento 5 na entrada do codificador e o comprimento 10 na entrada do decodificador. E se houver 8 tokens na oferta em inglês e no francês correspondente 18, eles não pertencerão ao grupo (10, 15) e serão transferidos para o grupo (20, 25), ou seja, a oferta em inglês aumentará para 20 e a francesa para 25.
Lembre-se de que, ao criar a entrada do decodificador, adicionamos o caractere
GO
especial à entrada. Isso acontece na função
get_batch()
em
seq2seq_model.py
, que também inverte a sentença em inglês. A inversão da entrada ajudou a melhorar os resultados do modelo de tradução neural de
Sutskever et al., 2014 (pdf). Para finalmente descobrir, imagine que a entrada seja “eu vou.”, Dividida em tokens
["I", "go", "."]
, E a saída é a frase "Je vais.", Dividida em tokens
["Je", "vais", "."]
. Eles serão adicionados ao grupo (5, 10), com uma representação do codificador de entrada
[PAD PAD "." "go" "I"]
[PAD PAD "." "go" "I"]
e entrada do decodificador
[GO "Je" "vais" "." EOS PAD PAD PAD PAD PAD]
[GO "Je" "vais" "." EOS PAD PAD PAD PAD PAD]
.
ExecutePara treinar o modelo descrito acima, você precisará de um grande corpo anglo-francês. Para treinamento, usaremos o corpo de 10 ^ 9 francês-inglês do
site WMT'15 e testaremos notícias no mesmo site como uma amostra de trabalho. Os dois conjuntos de dados serão carregados no
train_dir
quando o próximo comando for executado.
python translate.py --data_dir [your_data_directory] --train_dir [checkpoints_directory] --en_vocab_size=40000 --fr_vocab_size=40000
Você precisará de 18 GB de espaço no disco rígido e de várias horas para preparar o prédio de treinamento. O caso é descompactado, os arquivos de dicionário são criados em
data_dir,
e
data_dir,
depois disso, o caso é tokenizado e convertido em identificadores inteiros. Preste atenção aos parâmetros responsáveis pelo tamanho do dicionário. No exemplo acima, todas as palavras fora das 40.000 palavras usadas com mais freqüência serão convertidas em um token UNK que representa uma palavra desconhecida. Assim, ao alterar o tamanho do dicionário, o binário reformará o alojamento pelo ID do token. Após o início da preparação dos dados, o treinamento.
Os valores especificados na
translate
são muito altos por padrão. Modelos grandes que aprendem por muito tempo mostram bons resultados, mas isso pode levar muito tempo ou muita memória da GPU. Você pode especificar um treino de modelo menor, como no exemplo abaixo.
python translate.py --data_dir [your_data_directory] --train_dir [checkpoints_directory] --size=256 --num_layers=2 --steps_per_checkpoint=50
O comando acima treinará o modelo com duas camadas (há três por padrão), cada uma com 256 unidades (1024 por padrão), com um ponto de verificação a cada 50 etapas (200 por padrão). Experimente essas opções para ver qual modelo de tamanho é adequado para sua GPU.
Durante o treinamento, cada etapa do binário
steps_per_checkpoin
t fornecerá estatísticas sobre as etapas anteriores. Com parâmetros padrão (3 camadas do tamanho 1024), a primeira mensagem é a seguinte:
global step 200 learning rate 0.5000 step-time 1.39 perplexity 1720.62 eval: bucket 0 perplexity 184.97 eval: bucket 1 perplexity 248.81 eval: bucket 2 perplexity 341.64 eval: bucket 3 perplexity 469.04 global step 400 learning rate 0.5000 step-time 1.38 perplexity 379.89 eval: bucket 0 perplexity 151.32 eval: bucket 1 perplexity 190.36 eval: bucket 2 perplexity 227.46 eval: bucket 3 perplexity 238.66
Observe que cada etapa leva um pouco menos de 1,4 segundos, confundindo a amostra de treinamento e confundindo a amostra de trabalho em cada grupo. Após cerca de 30 mil etapas, vemos como os perplexos das frases curtas (grupos 0 e 1) se tornam inequívocos. O edifício de treinamento contém cerca de 22 milhões de frases, uma iteração (uma série de dados de treinamento) leva cerca de 340 mil etapas com o número de amostras de treinamento no valor de 64. Nesta fase, o modelo pode ser usado para traduzir frases em inglês para o francês usando a opção
--decode
.
python translate.py --decode --data_dir [your_data_directory] --train_dir [checkpoints_directory] Reading model parameters from /tmp/translate.ckpt-340000 > Who is the president of the United States? Qui est le président des États-Unis ?
O que vem a seguir?O exemplo acima mostra como criar seu próprio tradutor inglês-francês de ponta a ponta. Execute-o e veja como o modelo funciona. A qualidade é aceitável, mas um modelo de conversão ideal não pode ser obtido com parâmetros padrão. Aqui estão algumas coisas que você pode melhorar.
Primeiro, usamos a tokenização primitiva, a função básica do
basic_tokenizer
em
data_utils
. Um tokenizador melhor pode ser encontrado no
site do WMT'15 . Se você o usar e um dicionário grande, poderá obter melhores traduções.
Além disso, os parâmetros padrão do modelo de conversão não estão configurados perfeitamente. Você pode tentar alterar a velocidade de aprendizado, atenuação e inicialização dos pesos do modelo. Você também pode substituir o
GradientDescentOptimizer
padrão no
seq2seq_model.py
por algo mais avançado, como o
AdagradOptimizer
. Experimente e assista para obter melhores resultados!
Finalmente, o modelo apresentado acima pode ser usado não apenas para tradução, mas também para qualquer outra tarefa de sequência a sequência. Mesmo que você queira transformar uma sequência em uma árvore, por exemplo, gerar uma árvore de análise, esse modelo pode produzir resultados de última geração, como mostra
Vinyals & Kaiser et al., 2014 (pdf) . Assim, você pode criar não apenas um tradutor, mas também um analisador, bot de bate-papo ou qualquer outro programa que desejar. Experimente!
Isso é tudo!
Estamos aguardando seus comentários e perguntas aqui ou convidamos você a perguntar ao
professor em
uma aula aberta .