带有Keras的单词级Seq2Seq

Chr*_*ian 6 machine-learning machine-translation deep-learning keras

我正在关注Keras Seq2Seq教程,并且机智很好。但是,这是一个字符级模型,我想将其应用于单词级模型。作者甚至在段落中添加了需要更改的内容,但是我目前的所有尝试都导致关于拧紧尺寸的错误。

如果按照字符级型号,输入数据是3个变暗:#sequences#max_seq_len#num_char因为每个字符是一个热编码。当按照教程中的说明绘制模型的摘要时,我得到:

Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            (None, None, 71)     0                                            
_____________________________________________________________________________ __________________
input_2 (InputLayer)            (None, None, 94)     0                                            
__________________________________________________________________________________________________
lstm_1 (LSTM)                   [(None, 256), (None, 335872      input_1[0][0]                    
__________________________________________________________________________________________________
lstm_2 (LSTM)                   [(None, None, 256),  359424      input_2[0][0]                    
                                                                 lstm_1[0][1]                     
                                                                 lstm_1[0][2]                     
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, None, 94)     24158       lstm_2[0][0]                     
==================================================================================================
Run Code Online (Sandbox Code Playgroud)

这样编译和训练就可以了。

现在,本教程具有“如果我想对整数序列使用单词级模型该怎么办?”部分。而且我尝试遵循这些更改。首先,我使用单词索引对所有序列进行编码。这样,输入数据和目标数据现在为2个暗淡:#sequences#max_seq_len因为我不再是一键编码,而是现在使用了嵌入层。

encoder_input_data_train.shape   =>  (90000, 9)
decoder_input_data_train.shape   =>  (90000, 16)
decoder_target_data_train.shape  =>  (90000, 16)
Run Code Online (Sandbox Code Playgroud)

例如,一个序列可能看起来像这样:

[ 826.  288. 2961. 3127. 1260. 2108.    0.    0.    0.]
Run Code Online (Sandbox Code Playgroud)

当我使用列出的代码时:

# encoder
encoder_inputs = Input(shape=(None, ))
x = Embedding(num_encoder_tokens, latent_dim)(encoder_inputs)
x, state_h, state_c = LSTM(latent_dim, return_state=True)(x)
encoder_states = [state_h, state_c]

# decoder
decoder_inputs = Input(shape=(None,))
x = Embedding(num_decoder_tokens, latent_dim)(decoder_inputs)
x = LSTM(latent_dim, return_sequences=True)(x, initial_state=encoder_states)
decoder_outputs = Dense(num_decoder_tokens, activation='softmax')(x)

model = Model([encoder_inputs, decoder_inputs], decoder_outputs)
Run Code Online (Sandbox Code Playgroud)

该模型进行编译,如下所示:

Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_35 (InputLayer)           (None, None)         0                                            
__________________________________________________________________________________________________
input_36 (InputLayer)           (None, None)         0                                            
__________________________________________________________________________________________________
embedding_32 (Embedding)        (None, None, 256)    914432      input_35[0][0]                   
__________________________________________________________________________________________________
embedding_33 (Embedding)        (None, None, 256)    914432      input_36[0][0]                   
__________________________________________________________________________________________________
lstm_32 (LSTM)                  [(None, 256), (None, 525312      embedding_32[0][0]               
__________________________________________________________________________________________________
lstm_33 (LSTM)                  (None, None, 256)    525312      embedding_33[0][0]               
                                                                 lstm_32[0][1]                    
                                                                 lstm_32[0][2]                    
__________________________________________________________________________________________________
dense_21 (Dense)                (None, None, 3572)   918004      lstm_33[0][0]                    
Run Code Online (Sandbox Code Playgroud)

在编译工作时,进行培训

model.fit([encoder_input_data, decoder_input_data], decoder_target_data, batch_size=32, epochs=1, validation_split=0.2)
Run Code Online (Sandbox Code Playgroud)

失败并显示以下错误:ValueError: Error when checking target: expected dense_21 to have 3 dimensions, but got array with shape (90000, 16)后者是解码器输入/目标的形状。为什么该Dense层以解码器形状的数组输入数据?

我尝试过的事情:

  • 我发现LSTM解码器具有一个奇怪的地方,return_sequences=True因为我认为我不能给一个Dense层一个序列(原始字符级模型的解码器没有说明这一点)。但是,简单地删除或设置return_sequences=False无济于事。当然,该Dense层现在的输出形状为(None, 3572)
  • 我不太需要这些Input图层。我将它们分别设置为shape=(max_input_seq_len, )和,shape=(max_target_seq_len, )以便摘要不显示(None, None)而是显示各自的值,例如(None, 16)。没变。
  • Keras Docs中,我读到了Embedding层应与一起使用input_length,否则Dense上游层无法计算其输出。但是同样,当我进行相应设置时仍然会出错input_length

我有点陷入僵局了吧?我是否在正确的道路上,还是从根本上错过了一些东西?我的数据形状不对吗?为什么最后Dense一层得到具有形状的数组(90000, 16)?看来还不错。

更新:我发现问题似乎在于decoder_target_data当前具有形状(#sample, max_seq_len),例如(90000, 16)。但是我假设我需要针对词汇表对目标输出进行一次热编码:(#sample, max_seq_len, vocab_size)例如,(90000, 16, 3572)

不幸的是,这引发了Memory错误。但是,当我出于调试目的进行操作时,即假设词汇量为10:

decoder_target_data = np.zeros((len(input_sequences), max_target_seq_len, 10), dtype='float32')
Run Code Online (Sandbox Code Playgroud)

然后在解码器模型中:

x = Dense(10, activation='softmax')(x)
Run Code Online (Sandbox Code Playgroud)

然后模型会正确训练。万一这确实是我的问题,我必须使用手动生成的批次来训练模型,以便我可以保留词汇量,但可以将#samples每个shape 减少到例如90个批次(1000, 16, 3572)。我在正确的轨道上吗?

Abh*_*thi 0

最近我也面临这个问题。没有其他解决方案可以batch_size=64在 a 中创建小批量的 say generator,然后代替model.fitdo model.fit_generator。我在下面附上了我的generate_batch代码:

def generate_batch(X, y, batch_size=64):
    ''' Generate a batch of data '''
    while True:
        for j in range(0, len(X), batch_size):
            encoder_input_data = np.zeros((batch_size, max_encoder_seq_length),dtype='float32')
            decoder_input_data = np.zeros((batch_size, max_decoder_seq_length+2),dtype='float32')
            decoder_target_data = np.zeros((batch_size, max_decoder_seq_length+2, num_decoder_tokens),dtype='float32')

            for i, (input_text_seq, target_text_seq) in enumerate(zip(X[j:j+batch_size], y[j:j+batch_size])):
                for t, word_index in enumerate(input_text_seq):
                    encoder_input_data[i, t] = word_index # encoder input seq

                for t, word_index in enumerate(target_text_seq):
                    decoder_input_data[i, t] = word_index
                    if (t>0)&(word_index<=num_decoder_tokens):
                        decoder_target_data[i, t-1, word_index-1] = 1.

            yield([encoder_input_data, decoder_input_data], decoder_target_data)
Run Code Online (Sandbox Code Playgroud)

然后像这样训练:

batch_size = 64
epochs = 2

# Run training
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

model.fit_generator(
    generator=generate_batch(X=X_train_sequences, y=y_train_sequences, batch_size=batch_size),
    steps_per_epoch=math.ceil(len(X_train_sequences)/batch_size),
    epochs=epochs,
    verbose=1,
    validation_data=generate_batch(X=X_val_sequences, y=y_val_sequences, batch_size=batch_size),
    validation_steps=math.ceil(len(X_val_sequences)/batch_size),
    workers=1,
    )
Run Code Online (Sandbox Code Playgroud)

X_train_sequences是列表的列表,例如[[23,34,56], [2, 33544, 6, 10]].
其他人也同样如此。

还从这个博客获得了帮助 - word-level-english-to-marathi-nmt