Seq2Seq 用于字符串反转

Seq2Seq for string reversal

如果我有一个字符串,说 "abc" 和那个字符串的反向目标,说 "cba"。

神经网络(尤其是编码器-解码器模型)能否学习此映射?如果是这样,实现此目标的最佳模型是什么。

我问,因为这是一个结构翻译,而不是像普通机器翻译那样的简单字符映射

我怀疑神经网络会学习抽象结构转换。由于字符串的输入长度不受限制,因此有限 NN 将没有必要的信息。 NLP 过程通常用于识别小块和简单的 context-sensitive 转换。我认为他们不会确定 end-to-end 所需的交换。

但是,我希望适用于单一维度的图像处理器能够很快学会这一点。有些人可以学习如何旋转 sub-image.

如果您的网络是 old-fashioned encoder-decoder 模型(没有注意),那么,正如@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] ! 一般来说,你可以把这样的模型想象成一个奇怪的自动编码器(有一个反转side-effect),并选择适合自动编码器的架构和训练过程。并且有大量关于文本自动编码器的文献。

另外,如果你做一个encoder-decoder模型有attention,那么,它不会有内存瓶颈,所以,原则上,可以反转一个any[=的序列22=]长度与神经网络。然而,注意力需要二次方的计算时间,因此在实践中,即使是具有注意力的神经网络对于长序列也会非常低效。