Organization Info

  • Дедлайн DD MM 2018 23:59 для всех групп.
  • В качестве решения задания нужно прислать ноутбук с подробными комментариями ( без присланного решения результат контеста не будет засчитан ).
  • Название команды в контесте должно соответствовать шаблону: НомерГруппы_Имя_Фамилия, например, 594_Ivan_Ivanov.

Оформление дз:

  • Присылайте выполненное задание на почту ml.course.mipt@gmail.com
  • Укажите тему письма в следующем формате ML2018_fall_<номер_группы>_<фамилия>, к примеру -- ML2018_fall_495_ivanov
  • Выполненное дз сохраните в файл <фамилия>_<группа>_task<номер>.ipnb, к примеру -- ivanov_401_task7.ipnb

Вопросы:

  • Присылайте вопросы на почту ml.course.mipt@gmail.com
  • Укажите тему письма в следующем формате ML2018_fall Question <Содержание вопроса>

  • PS1: Используются автоматические фильтры, и просто не найдем ваше дз, если вы неаккуратно его подпишите.
  • PS2: Просроченный дедлайн снижает максимальный вес задания по формуле, указнной на первом семинаре
  • PS3: Допустимы исправление кода предложенного кода ниже, если вы считаете

Checking Questions

Вопрос 1: Чем LSTM лучше/хуже чем обычная RNN?

Есть такая история: сначала были обычные нейросети. Оказалось, что если им давать и давать вход, то они сразу же забудут предыдщий вход. Поэтому придумали рекуррентные нейронные сети. Оказалось, что они помнят все, а в этом нет никакой необходимости (действительно, если вы читаете 4-й том "Войны и мира", то вы вполне можете выбросить сценку на французском из начала 1-го тома). Таким образом, мы не держим всякий старый мусор в памяти, и выходят более точные предсказания и большая эффективность.

Вопрос 2: Выпишите производную $\frac{d c_{n+1}}{d c_{k}}$ для LSTM http://colah.github.io/posts/2015-08-Understanding-LSTMs/, объясните формулу, когда производная затухает, когда взрывается?

По ссылке же вообще что-то непонятное расписано. Понятный пример есть на слайдах, там все расписано, но он для просто RNN. Этого мало?

Вопрос 3: Зачем нужен TBPTT почему BPTT плох?

Думаю, ответ на первый вопрос заложен в формулировке второго вопроса. Так что остановимся только на последнем. Основная причина — эффективность. Для того чтобы посчитать все градиенты, нужно идти по всему-всему-всему входу в backpropagation, а это значит, что градиенты могут затухнуть или взорваться. Ну и вообще это долго.

Вопрос 4: Как комбинировать рекуррентные и сверточные сети, а главное зачем? Приведите несколько примеров реальных задач.

Ну сверточные нейронные сети нужны для картинок, а рекуррентные полезны для текста. Соотвественно, если это совместить, то можно придумать реальную задачу. Первое, что приходит в голову: давайте генерировать или переводить стихи. Вот у нас есть отскнаненные фоточки страниц книг. Тогда мы можем а) распознать текст; б) учесть местоположение строк. Тогда у нас будет куда больше информации для воспроизведения рифмы. Ну и это уже поможет рекуррентным нейронным сетям работать получше.

Вопрос 5: Можно ли использовать сверточные сети для классификации текстов? Если нет обоснуйте :D, если да то как? как решить проблему с произвольной длинной входа?

Я думаю, да, посольку когда я вбил в гугле "cnn for", первый suggest был "cnn for text classification". :) Вообще, кажется, что ничто не мешает просто так взять и представить текст как изображение. Надо подумать, как это сделать. Давайте один пиксель будет представлять собой одно слово (или токены). Вместо цветов красный-синий-зеленый можно взять, например, стили (официальный, разговорный, высокий и так далее), ну или эмоциональный окрас. Просто по словарям пробьем. А располагать слова надо последовательно, чтобы угадывалась структура. Например, будем укладывать слова змейкой. Или спиралькой. Или диагональной змейкой. Но я думаю, что лучше всего спиралька, так как когда слова из разных строк находятся рядом друг с другом, то они будут при распознавании более важны друг для друга. И будет плохо, если с какой-то периодичностью "ширина изображения" какие-то рандомныке слова друг с другом свяжутся. В спиральке тоже будет закономерность, но не такая явная

Вопрос 6: Attention - что это такое, где применяют и как? Приведите пример использования на какой-нибудь задаче

Attention нужны для решения проблемы bottleneck - произвольные объемы информации надо уложить в один фиксированный вектор. Так мы будет что-то терять (вся информация должна пролезть в маленькое бутылочное горлышко). Чтобы побороть проблему, используют Attention - маханизм запомнить какую-либо информацию о нашем входе. На каждом шаге декодера будет фокусироваться на каждом отдельном шаге входа, в зависимости от того, что мы делаем. Пример задач NMT, можно посмотреть задачи из этого ноутбука (но не решения).

Grading

  • starting at zero points
  • +2 for describing your iteration path in a report below (compare models).
  • +2 for correct check questions
  • +3 (7 total) for 99% accuracy with simple NMT model on TEST dataset
  • +3 (10 total) for 99% accuracy with attention NMT model on TEST dataset

  • tatoeba bonus for accuracy on TEST dataset:
    • +2 for report
    • 60% (14 total)
    • 65% (16 total)
    • 70% (18 total)
    • 75% (20 total)

Bonus points

Common ways to get bonus points are:

  • Get higher score, obviously.
  • Anything special about your NN. For example "A super-small/fast NN that gets 99%" gets a bonus.
  • Any detailed analysis of the results. (attention maps, whatever)


In [0]:
# additional packages for this notebook

In [4]:
! pip install faker tqdm babel


Requirement already satisfied: faker in /usr/local/lib/python3.6/dist-packages (0.8.14)
Requirement already satisfied: tqdm in /usr/local/lib/python3.6/dist-packages (4.23.3)
Requirement already satisfied: babel in /usr/local/lib/python3.6/dist-packages (2.5.3)
Requirement already satisfied: six>=1.10 in /usr/local/lib/python3.6/dist-packages (from faker) (1.11.0)
Requirement already satisfied: python-dateutil>=2.4 in /usr/local/lib/python3.6/dist-packages (from faker) (2.5.3)
Requirement already satisfied: text-unidecode==1.2 in /usr/local/lib/python3.6/dist-packages (from faker) (1.2)
Requirement already satisfied: pytz>=0a in /usr/local/lib/python3.6/dist-packages (from babel) (2018.4)

Task - translation

The machine translation is old and well-known field in natural language processing. From the 1950s scientists tried to create a model to automatically translate from say French to English. Nowadays it became possible and the attention mechanism takes great part in that. Here the example image with attention map for the neural machine translation of sample phrase:

In our lab we will concentrate on much simplier task: we will translate from human readable date to machine readable one.

To do this we need to get one more concept - Sequence-to-Sequence language modeling. The idea of such architecture is here:

There is an Embeding layer at the bottom, the RNN in the middle and softmax as an output.


In [5]:
from keras.layers import Embedding, Bidirectional
from keras.layers.core import *
from keras.layers.recurrent import LSTM
from keras.models import *
from keras.layers.merge import Multiply
from keras.utils import to_categorical
from keras.layers import TimeDistributed

import keras.backend as K
import numpy as np


Using TensorFlow backend.

Data

Now we need to generate data. It will be dates in different text formats and in fixed output format.


In [0]:
from faker import Faker
import random
from tqdm import tqdm
from babel.dates import format_date
import numpy as np

In [0]:
fake = Faker()

FORMATS = ['short',
           'medium',
           'long',
           'full',
           'd MMM YYY', 
           'd MMMM YYY',
           'dd MMM YYY',
           'd MMM, YYY',
           'd MMMM, YYY',
           'dd, MMM YYY',
           'd MM YY',
           'd MMMM YYY',
           'MMMM d YYY',
           'MMMM d, YYY',
           'dd.MM.YY']

# change this if you want it to work with another language
LOCALES = ['en_US']

In [0]:
def create_date():
    """
        Creates some fake dates 
        :returns: tuple containing human readable string, machine readable string, and date object
    """
    dt = fake.date_object()

    try:
        human_readable = format_date(dt, format=random.choice(FORMATS), locale=random.choice(LOCALES))

        case_change = random.choice([0,1,2])
        if case_change == 1:
            human_readable = human_readable.upper()
        elif case_change == 2:
            human_readable = human_readable.lower()
        # if case_change == 0, do nothing

        machine_readable = dt.isoformat()
    except AttributeError as e:
        return None, None, None

    return human_readable, machine_readable, dt

In [0]:
def create_dataset(n_examples):
    """
        Creates a dataset with n_examples and vocabularies
        :n_examples: the number of examples to generate
    """
    human_vocab = set()
    machine_vocab = set()
    dataset = []

    for i in tqdm(range(n_examples)):
        h, m, _ = create_date()
        if h is not None:
            dataset.append((h, m))
            human_vocab.update(tuple(h))
            machine_vocab.update(tuple(m))

    human = dict(zip(list(human_vocab) + ['<unk>', '<pad>'], 
                     list(range(len(human_vocab) + 2))))
    inv_machine = dict(enumerate(list(machine_vocab) + ['<unk>', '<pad>']))
    machine = {v:k for k,v in inv_machine.items()}
 
    return dataset, human, machine, inv_machine

In [0]:
def string_to_int(string, lenght, vocab):
    if len(string) > lenght:
        string = string[:lenght]
        
    rep = list(map(lambda x: vocab.get(x, '<unk>'), string))
    
    if len(string) < lenght:
        rep += [vocab['<pad>']] * (lenght - len(string))
    
    return rep

In [0]:
def int_to_string(ints, inv_vocab):
    return [inv_vocab[i] for i in ints]

Actually generating data:


In [12]:
fake.seed(42)
random.seed(42)
N = int(3e5)
dataset, human_vocab, machine_vocab, inv_machine_vocab = create_dataset(N)


100%|██████████| 300000/300000 [00:18<00:00, 16201.74it/s]

In [13]:
dataset[2]


Out[13]:
('tuesday, september 14, 1971', '1971-09-14')

In [0]:
# Пришлось переместить эту ячейку сюда, чтобы код заработал.
# :good-enouht:
ENCODER_UNITS = 32 # change me if u want
DECODER_UNITS = 32 # change me if u want
TIME_STEPS = 20 # change me if u want

In [0]:
inputs, targets = zip(*dataset)
inputs = np.array([string_to_int(i, TIME_STEPS, human_vocab) for i in inputs])
targets = [string_to_int(t, TIME_STEPS, machine_vocab) for t in targets]
targets = np.array(list(map(lambda x: to_categorical(x, num_classes=len(machine_vocab)), targets)))

In [0]:
X_train, y_train, X_valid, y_valid, X_test, y_test = (
    inputs[:int(2e5)], targets[:int(2e5)], 
    inputs[int(2e5):-int(5e4)], targets[int(2e5):-int(5e4)],  
    inputs[-int(5e4):], targets[-int(5e4):], )

Part 1: Simple NMT


In [0]:
class NeuroNetwork:
  def __init__(self):
    self.layers = []
    
  def AddLayer(self, layer):
    self.layers += [layer]
    return self
    
  def GetOutput(self, inputs):
    output = inputs
    for layer in self.layers:
      output = layer(output)
    return output

In [0]:
# input - [bs; in_time_len]
# output - [bs; out_time_len]; out_time_len=10

def model_simple_nmt(in_chars, out_chars):
    # RNN encoder -> hidden representation -> RNN decoder
    inputs = Input(shape=(TIME_STEPS,))
    
    # your code
    output = NeuroNetwork() \
    .AddLayer(Embedding(in_chars, 10)) \
    .AddLayer(LSTM(ENCODER_UNITS)) \
    .AddLayer(RepeatVector(TIME_STEPS)) \
    .AddLayer(LSTM(DECODER_UNITS, return_sequences=True)) \
    .AddLayer(TimeDistributed(Dense(out_chars, activation='softmax'))) \
    .GetOutput(inputs)
    # source: https://machinelearningmastery.com/encoder-decoder-attention-sequence-to-sequence-prediction-keras/

    model = Model(input=[inputs], output=output)
    return model

In [19]:
m = model_simple_nmt(len(human_vocab), len(machine_vocab))

m.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
print(m.summary())


_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 20)                0         
_________________________________________________________________
embedding_1 (Embedding)      (None, 20, 10)            600       
_________________________________________________________________
lstm_1 (LSTM)                (None, 32)                5504      
_________________________________________________________________
repeat_vector_1 (RepeatVecto (None, 20, 32)            0         
_________________________________________________________________
lstm_2 (LSTM)                (None, 20, 32)            8320      
_________________________________________________________________
time_distributed_1 (TimeDist (None, 20, 13)            429       
=================================================================
Total params: 14,853
Trainable params: 14,853
Non-trainable params: 0
_________________________________________________________________
None
/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:10: UserWarning: Update your `Model` call to the Keras 2 API: `Model(inputs=[<tf.Tenso..., outputs=Tensor("ti...)`
  # Remove the CWD from sys.path while we load stuff.

In [21]:
m.fit(
    [X_train], y_train, 
    validation_data=(X_valid, y_valid),  # Пришлось добавить запятую, без нее не работало
    epochs=10, batch_size=64,
    validation_split=0.1)


Train on 200000 samples, validate on 50000 samples
Epoch 1/10
 42880/200000 [=====>........................] - ETA: 4:37 - loss: 1.1037 - acc: 0.6304199936/200000 [============================>.] - ETA: 0s - loss: 0.6523 - acc: 0.7614200000/200000 [==============================] - 370s 2ms/step - loss: 0.6522 - acc: 0.7614 - val_loss: 0.3638 - val_acc: 0.8495
Epoch 2/10
 28096/200000 [===>..........................] - ETA: 5:00 - loss: 0.3514 - acc: 0.8544199936/200000 [============================>.] - ETA: 0s - loss: 0.2780 - acc: 0.8864200000/200000 [==============================] - 369s 2ms/step - loss: 0.2780 - acc: 0.8865 - val_loss: 0.2075 - val_acc: 0.9203
Epoch 3/10
 28096/200000 [===>..........................] - ETA: 4:58 - loss: 0.2010 - acc: 0.9229199936/200000 [============================>.] - ETA: 0s - loss: 0.1499 - acc: 0.9480200000/200000 [==============================] - 370s 2ms/step - loss: 0.1499 - acc: 0.9480 - val_loss: 0.0996 - val_acc: 0.9687
Epoch 4/10
 28096/200000 [===>..........................] - ETA: 4:58 - loss: 0.0940 - acc: 0.9701199936/200000 [============================>.] - ETA: 0s - loss: 0.0730 - acc: 0.9769200000/200000 [==============================] - 366s 2ms/step - loss: 0.0730 - acc: 0.9769 - val_loss: 0.0597 - val_acc: 0.9806
Epoch 5/10
 28096/200000 [===>..........................] - ETA: 4:58 - loss: 0.0542 - acc: 0.9826199936/200000 [============================>.] - ETA: 0s - loss: 0.0456 - acc: 0.9855200000/200000 [==============================] - 368s 2ms/step - loss: 0.0456 - acc: 0.9855 - val_loss: 0.0357 - val_acc: 0.9884
Epoch 6/10
 28096/200000 [===>..........................] - ETA: 4:52 - loss: 0.0370 - acc: 0.9880186176/200000 [==========================>...] - ETA: 23s - loss: 0.0325 - acc: 0.9892200000/200000 [==============================] - 363s 2ms/step - loss: 0.0322 - acc: 0.9893 - val_loss: 0.0271 - val_acc: 0.9904
Epoch 7/10
 22912/200000 [==>...........................] - ETA: 4:58 - loss: 0.0274 - acc: 0.9907113472/200000 [================>.............] - ETA: 2:24 - loss: 0.0266 - acc: 0.9907191168/200000 [===========================>..] - ETA: 14s - loss: 0.0261 - acc: 0.9907200000/200000 [==============================] - 353s 2ms/step - loss: 0.0260 - acc: 0.9907 - val_loss: 0.0270 - val_acc: 0.9899
Epoch 8/10
 24512/200000 [==>...........................] - ETA: 4:47 - loss: 0.0258 - acc: 0.9906103744/200000 [==============>...............] - ETA: 2:36 - loss: 0.0238 - acc: 0.9912176000/200000 [=========================>....] - ETA: 38s - loss: 0.0230 - acc: 0.9914200000/200000 [==============================] - 344s 2ms/step - loss: 0.0227 - acc: 0.9915 - val_loss: 0.0199 - val_acc: 0.9923
Epoch 9/10
 18304/200000 [=>............................] - ETA: 4:52 - loss: 0.0211 - acc: 0.9919199936/200000 [============================>.] - ETA: 0s - loss: 0.0211 - acc: 0.9918200000/200000 [==============================] - 348s 2ms/step - loss: 0.0211 - acc: 0.9918 - val_loss: 0.0199 - val_acc: 0.9921
Epoch 10/10
200000/200000 [==============================] - 369s 2ms/step - loss: 0.0195 - acc: 0.9922 - val_loss: 0.0200 - val_acc: 0.9922
Out[21]:
<keras.callbacks.History at 0x7f63986098d0>

In [22]:
m.evaluate([X_test], y_test)


50000/50000 [==============================] - 48s 967us/step
Out[22]:
[0.019978798908479513, 0.9922040000724792]

Lets check our model:


In [0]:
EXAMPLES = ['3 May 1979', '5 Apr 09', '20th February 2016', 'Wed 10 Jul 2007']

def run_example(model, input_vocabulary, inv_output_vocabulary, text):
    encoded = string_to_int(text, TIME_STEPS, input_vocabulary)
    prediction = model.predict(np.array([encoded]))
    prediction = np.argmax(prediction[0], axis=-1)
    return int_to_string(prediction, inv_output_vocabulary)

def run_examples(model, input_vocabulary, inv_output_vocabulary, examples=EXAMPLES):
    predicted = []
    for example in examples:
        predicted.append(''.join(run_example(model, input_vocabulary, inv_output_vocabulary, example)))
        print('input:', example)
        print('output:', predicted[-1])
    return predicted

In [24]:
run_examples(m, human_vocab, inv_machine_vocab)


input: 3 May 1979
output: 1979-05-03<pad><pad><pad><pad><pad><pad><pad><pad><pad><pad>
input: 5 Apr 09
output: 2009-04-05<pad><pad><pad><pad><pad><pad><pad><pad><pad><pad>
input: 20th February 2016
output: 2016-02-20<pad><pad><pad><pad><pad><pad><pad><pad><pad><pad>
input: Wed 10 Jul 2007
output: 2007-08-10<pad><pad><pad><pad><pad><pad><pad><pad><pad><pad>
Out[24]:
['1979-05-03<pad><pad><pad><pad><pad><pad><pad><pad><pad><pad>',
 '2009-04-05<pad><pad><pad><pad><pad><pad><pad><pad><pad><pad>',
 '2016-02-20<pad><pad><pad><pad><pad><pad><pad><pad><pad><pad>',
 '2007-08-10<pad><pad><pad><pad><pad><pad><pad><pad><pad><pad>']

Part 2: All u need is attention

Here we use more complex idea that simple seq2seq: we're adding two explicit parts of our network - encoder and decoder (which is applied attention on). The explanatory picture for this idea is below:

The lower part of the network is encoding the input to some hidden intermediate representation and the upper part is decoing the hidвen represenataion into some readable output.


In [0]:
# :good-enouht:
ENCODER_UNITS = 32 # change me if u want
DECODER_UNITS = 32 # change me if u want
TIME_STEPS = 20 # change me if u want

In [0]:
def model_attention_nmt(in_chars, out_chars):
    # RNN encoder -> hidden representation -> RNN decoder
    inputs = Input(shape=(TIME_STEPS,))
    
    # your code
    assert(False)

    model = Model(input=[inputs], output=output)
    return model

In [29]:
m = model_attention_nmt(len(human_vocab), len(machine_vocab))

m.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
print(m.summary())


---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-29-447b073830b5> in <module>()
----> 1 m = model_attention_nmt(len(human_vocab), len(machine_vocab))
      2 
      3 m.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
      4 print(m.summary())

<ipython-input-28-fb641b1b95cf> in model_attention_nmt(in_chars, out_chars)
      4 
      5     # your code
----> 6     assert(False)
      7 
      8     model = Model(input=[inputs], output=output)

AssertionError: 

In [0]:
m.fit(
    [X_train], y_train, 
    validation_data=(X_valid, y_valid)
    epochs=10, batch_size=64, 
    validation_split=0.1)

In [0]:
m.evaluate([X_test], y_test)

Report

  • final architectures
  • comparison
  • as well as training method and tricks

Итак, ну я посмотрел на нейросеть с семинара, и код с ней не заработал из-за несовпадения каких-то размерностей. Поэтому я начал гуглить. Другого выбора не было, так как на семинаре и лекции вообще не объясняли, что такое енкодер и декодер. Да и вообще почти ничего связанного с домашкой не было. Впрочем, как и всегда.

Так вот, где-то первая-третья ссылка в гугле по запросу "keras encode decoder attention" оказалась весьма пристойной, по крайней мере там на удивление даже совпадали названия слоев и вообще были какие-то куски, которые можно опознать в задании. Это клево, и я решил ей воспользоваться.

Взял эту архитектуру, пофиксил параметры под наши обозначения и решил избавляться от излишеств. Для начала какой-то непонятный RepeatVector. Попробовал убрать - опять что-то не совпало. Вернул. Еще там есть TimeDistributed. На удивление код работал и без него, поэтому в соответствии с принципом "бритва Оккама" (не плоди лишнего, если это не нужно), решил оставить. Наверняка это как-то помогает увеличить скор.

Я стал думать, попробовать запускать без TimeDistributed или нет. Простые рассуждения привели меня к и без того очевидному выводу: нет. Нет, я не готов ждать дважды по часу, чтобы заметить разницу в 0.0000001. Тем более, если бы второй вариант оказался хуже, то мне пришлось бы ждать еще час, когда я вернул все обратно.

Дальше я стал думать, какой же там окажется скор. На всякий случай решил взять 20 эпох вместо 10 и запустил. Но к счастью, после 8 эпох (то есть примерно 40 минут) коллаб дисконнектнулся, и все пропало. Почему к счатью? Потому что хотя это и вызвалу очередную бурю негативных эмоций, я смог сократить число эпох до 10. Действительно, за 8 эпох мне уже выдали примерный скор, и там уже набиралось 99%. Но это на трейне. На тесте могло быть чуть похуже. Но я решил, что 12 эпох для теста - роскошь. И вернул 10 эпох. Запустил - и на тесте 99% набралось. По итогу: если бы колаб не рухнул, то мне пришлось бы ждать 12 эпох (час), когда все закончится. А он рухнул, поэтому я запустил с 10 эпохами, и все кончилось за 50 минут. Вот такие чудеса случаются.

Получив скор 99%, мотивация делать задание сразу же пропала. Впрочем, ее особо и не было, разве что я не хочу удовл за курс. Ну а атеншн я не осилил вообще, всякие гуглимые коды слишком большие и сложные, чтобы в них разбираться, если нет интереса, на лекции ничего не понятно, а на семинаре, разумеется, нет даже упоминаний атеншена. Видимо, не очень важная тема.

Третью часть тоже не стал делать, раз не смог атеншн.


Part 3*: tatoeba - real NMT

Data


In [0]:
# dataset from http://www.manythings.org/anki/

In [0]:
! wget http://www.manythings.org/anki/rus-eng.zip

In [0]:
! unzip ./rus-eng.zip

In [0]:
with open("./rus.txt") as fin:
    data = fin.readlines()
data = list(map(lambda x: x.replace("\n", "").lower(), data))

In [0]:
len(data)

In [0]:
data = data[:int(1e5)]

In [0]:
len(data)

In [0]:
data[-1]


In [0]:
source = list(map(lambda x: x.split("\t")[0], data))
target = list(map(lambda x: x.split("\t")[1], data))

In [0]:
source_vocab = set("".join(source).strip())
target_vocab = set("".join(target).strip())

In [0]:
source_vocab = dict(zip(
    list(source_vocab) + ['<unk>', '<pad>'], 
    list(range(len(source_vocab) + 2))))
target_vocab = dict(zip(
    list(target_vocab) + ['<unk>', '<pad>'], 
    list(range(len(target_vocab) + 2))))
inv_target_vocab = dict(enumerate(list(target_vocab) + ['<unk>', '<pad>']))

In [0]:
TIME_STEPS = 32
ENCODER_UNITS = 256
DECODER_UNITS = 256

In [0]:
def model_simple_nmt_tatoeba(in_chars, out_chars):
    inputs = Input(shape=(TIME_STEPS,))
    
    # your code

    model = Model(input=[inputs], output=output)
    return model

In [0]:
m = model_attention_nmt(len(human_vocab), len(machine_vocab))

m.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
print(m.summary())

In [0]:
inputs = np.array([string_to_int(i, TIME_STEPS, source_vocab) for i in source])
targets = [string_to_int(t, TIME_STEPS, target_vocab) for t in target]
targets = np.array(list(map(lambda x: to_categorical(x, num_classes=len(target_vocab)), targets)))

In [0]:
m.fit(
    [inputs], targets, 
    epochs=10, batch_size=64, 
    validation_split=0.1)

In [0]:
run_example(m, source_vocab, inv_target_vocab, 'hello')

Tatoeba Report

  • final architectures
  • comparison
  • as well as training method and tricks