Seq2Seq для обращения строк - PullRequest
0 голосов
/ 27 июня 2019

Если у меня есть строка, скажите «abc», а цель этой строки в обратном порядке, скажите «cba».

Может ли нейронная сеть, в частности модель кодера-декодера, изучить это отображение?Если да, то какая модель лучше для этого?

Я спрашиваю, поскольку это структурный перевод, а не простое отображение символов, как в обычном машинном переводе

Ответы [ 2 ]

2 голосов
/ 27 июня 2019

Я сомневаюсь, что NN научится абстрактной структурной трансформации.Поскольку строка имеет неограниченную входную длину, конечный NN не будет иметь необходимой информации.Процессы НЛП обычно работают с идентификацией небольших блоков и простых контекстно-зависимых сдвигов.Я не думаю, что они определили бы необходимость сквозных обменов.

Однако я ожидаю, что процессор изображений, адаптированный к одному измерению, научится этому довольно быстро.Некоторые могут научиться вращать подизображение.

1 голос
/ 28 июня 2019

Если ваша сеть является устаревшей моделью кодера-декодера (без внимания), то, как сказал @Prune, она имеет узкое место в памяти (размерность кодера). Таким образом, такая сеть не может научиться обращать строки произвольного размера. Тем не менее, вы можете обучить такой RNN реверсировать строки ограниченного размера. Например, следующая игрушка seq2seq LSTM способна инвертировать последовательности цифр длиной до 10. Вот как вы ее тренируете:

from keras.models import Model
from keras.layers import Input, LSTM, Dense, Embedding
import numpy as np

emb_dim = 20
latent_dim = 100  # Latent dimensionality of the encoding space.
vocab_size = 12 # digits 0-9, 10 is for start token, 11 for end token

encoder_inputs = Input(shape=(None, ), name='enc_inp')
common_emb = Embedding(input_dim=vocab_size, output_dim=emb_dim)
encoder_emb = common_emb(encoder_inputs)
encoder = LSTM(latent_dim, return_state=True)
encoder_outputs, state_h, state_c = encoder(encoder_emb)
encoder_states = [state_h, state_c]

decoder_inputs = Input(shape=(None,), name='dec_inp')
decoder_emb = common_emb(decoder_inputs)
decoder_lstm = LSTM(latent_dim, return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(decoder_emb, initial_state=encoder_states)
decoder_dense = Dense(vocab_size, activation='softmax')
decoder_outputs = decoder_dense(decoder_outputs)

model = Model([encoder_inputs, decoder_inputs], decoder_outputs)

def generate_batch(length=4, batch_size=64):
    x = np.random.randint(low=0, high=10, size=(batch_size, length))
    y = x[:, ::-1]
    start = np.ones((batch_size, 1), dtype=int) * 10
    end = np.ones((batch_size, 1), dtype=int) * 11
    enc_x = np.concatenate([start, x], axis=1)
    dec_x = np.concatenate([start, y], axis=1)
    dec_y = np.concatenate([y, end], axis=1)
    dec_y_onehot = np.zeros(shape=(batch_size, length+1, vocab_size), dtype=int)
    for row in range(batch_size):
        for col in range(length+1):
            dec_y_onehot[row, col, dec_y[row, col]] = 1
    return [enc_x, dec_x], dec_y_onehot

def generate_batches(batch_size=64, max_length=10):
    while True:
        length = np.random.randint(low=1, high=max_length)
        yield generate_batch(length=length, batch_size=batch_size)

model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['categorical_accuracy'])
model.fit_generator(generate_batches(), steps_per_epoch=1000, epochs=20)

Теперь вы можете применить его для изменения последовательности (мой декодер очень неэффективен, но он иллюстрирует принцип)

input_seq = np.array([[10, 2, 1, 2, 8, 5, 0, 6]])
result = np.array([[10]])
next_digit = -1
for i in range(100):
    next_digit = model.predict([input_seq, result])[0][-1].argmax()
    if next_digit == 11:
        break
    result = np.concatenate([result, [[next_digit]]], axis=1)
print(result[0][1:])

Ура, печатает [6 0 5 8 2 1 2]! Как правило, вы можете думать о такой модели как о странном автоэнкодере (с обратным побочным эффектом) и выбирать архитектуру и процедуру обучения, подходящую для автоэнкодеров. И есть довольно обширная литература по текстовым автоэнкодерам.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...