Tensorflow 和 Keras:LSTM 在 seq2seq 问题上表现不佳,解决方案清晰
Tensorflow & Keras: LSTM performs bad on seq2seq problem with clear solution
我正在学习机器翻译的 tensorflow 和 seq2seq 问题。
为此,我给了我以下任务:
我创建了一个 Excel,包含不同类型的随机日期,例如:
- 05.09.2192
- martes, 07 de mayo de 2329
- 2129 年 12 月 30 日星期五
在我的数据集中,每种类型都出现了 1000 次。这些是我的火车 (X) 值。
我的目标 (Y) 值总是占一半:
- 05.09.2192
- 07.03.2329
- 30.12.2129
另外一半是这样的:
- Samstag, 12. Juni 2669
- Donnerstag,2990 年 4 月 1 日
- Freitag,2124 年 11 月 10 日
为了使模型能够区分这两个 Y 值,另一个上下文信息 (C) 以文本形式给出:
- Ausgeschrieben(写出来)
- 基准(日期)
所以有些行看起来像这样:
所以我的目标是创建一个模型,它能够将任何日期类型“翻译”为德语日期类型,例如05.09.2192.
数据集包含 34.000 对。
为了解决这个问题,我使用基于字符的分词器将文本转换为整数:
tokenizer = keras.preprocessing.text.Tokenizer(filters='', char_level=True, oov_token="|")
我使用 LSTM 编码器-解码器模型,我希望它能达到完美的精度,因为 X 和 Y 之间的依赖关系可以完美解决。
但是,我最多达到 72% 的准确率。更糟糕的是,准确度只能达到那么多,因为填充生成得很好。例如。大多数 Y 值都非常短,因此会被填充。所以 12.02.2001
变成例如||||||||||||||||||||12.02.2001
。所以模型学得很好,生成了 padding token,但不是期望值。
这是我最近一次测试使用的模型结构:
from tensorflow.keras.layers import Concatenate
encoder_inputs = keras.layers.Input(batch_input_shape=[32,None], dtype=np.int32)
decoder_inputs = keras.layers.Input(batch_input_shape=[32,None], dtype=np.int32)
embeddings = keras.layers.Embedding(vocab_size, 1)
encoder_embeddings = embeddings(encoder_inputs)
decoder_embeddings = embeddings(decoder_inputs)
encoder_0 = keras.layers.Dense(128)(encoder_embeddings)
encoder_0d = keras.layers.Dropout(0.4)(encoder_0)
encoder_0_1 = keras.layers.Dense(256)(encoder_0d)
encoder_0_1d = keras.layers.Dropout(0.2)(encoder_0_1)
encoder_0_2 = keras.layers.Dense(128)(encoder_0_1d)
encoder_0_2d = keras.layers.Dropout(0.05)(encoder_0_2)
encoder_0_3 = keras.layers.Dense(64)(encoder_0_2d)
encoder_1 = keras.layers.LSTM(64, return_state=True, return_sequences=True, recurrent_dropout=0.2)
encoder_lstm_bidirectional = keras.layers.Bidirectional(encoder_1)
encoder_output, state_h1, state_c1, state_h2, state_c2 = encoder_lstm_bidirectional(encoder_0_3)
encoder_state = [Concatenate()([state_h1, state_h2]), Concatenate()([state_c1, state_c2])]
sampler = tfa.seq2seq.sampler.TrainingSampler()
decoder_cell = keras.layers.LSTMCell(64*2)
output_layer = keras.layers.Dense(vocab_size)
decoder = tfa.seq2seq.basic_decoder.BasicDecoder(decoder_cell, sampler, output_layer=output_layer)
final_outputs, final_state, final_sequence_lengths = decoder(decoder_embeddings, initial_state=encoder_state,
sequence_length=[sequence_length], training=True)
y_proba = tf.nn.softmax(final_outputs.rnn_output)
model = keras.Model(inputs=[encoder_inputs, decoder_inputs], outputs=[y_proba])
如果需要,我可以在github中部署整个笔记本,但也许有一个简单的解决方案,我只是到目前为止没有看到。
感谢您的帮助!
因此,如果这对将来的任何人有帮助:
该模型完全按照我的要求去做。
但是
您需要小心,您的数据预处理不会导致歧义。
所以你必须防止这样的事情:
a -> b and also a -> c
在改进一个方程式的同时,另一个方程式将丢失。那是我的问题。
看这个例子:
eq1: 26.04.1994 -> 26.04.1994
eq2: 26.04.1994 -> Tuesday, 26.04.1994
一方面,模型提高了 eq1 的准确性。另一方面,它减少了 eq2 的损失。所以 74% 是一种妥协,模型找到了。
为了解决这个问题,我不得不添加另一个因素,它更具体地描述了数据。所以我额外加了一个条件,描述y是写出来还是只写成date类型。所以现在我有一个像下面这样的数据结构,我的准确率增长到 98%:
eq1: 26.04.1994, dateformat -> 26.04.1994
eq2: 26.04.1994, written_out -> Tuesday, 26.04.1994
我正在学习机器翻译的 tensorflow 和 seq2seq 问题。 为此,我给了我以下任务:
我创建了一个 Excel,包含不同类型的随机日期,例如:
- 05.09.2192
- martes, 07 de mayo de 2329
- 2129 年 12 月 30 日星期五
在我的数据集中,每种类型都出现了 1000 次。这些是我的火车 (X) 值。 我的目标 (Y) 值总是占一半:
- 05.09.2192
- 07.03.2329
- 30.12.2129
另外一半是这样的:
- Samstag, 12. Juni 2669
- Donnerstag,2990 年 4 月 1 日
- Freitag,2124 年 11 月 10 日
为了使模型能够区分这两个 Y 值,另一个上下文信息 (C) 以文本形式给出:
- Ausgeschrieben(写出来)
- 基准(日期)
所以有些行看起来像这样:
所以我的目标是创建一个模型,它能够将任何日期类型“翻译”为德语日期类型,例如05.09.2192.
数据集包含 34.000 对。
为了解决这个问题,我使用基于字符的分词器将文本转换为整数:
tokenizer = keras.preprocessing.text.Tokenizer(filters='', char_level=True, oov_token="|")
我使用 LSTM 编码器-解码器模型,我希望它能达到完美的精度,因为 X 和 Y 之间的依赖关系可以完美解决。
但是,我最多达到 72% 的准确率。更糟糕的是,准确度只能达到那么多,因为填充生成得很好。例如。大多数 Y 值都非常短,因此会被填充。所以 12.02.2001
变成例如||||||||||||||||||||12.02.2001
。所以模型学得很好,生成了 padding token,但不是期望值。
这是我最近一次测试使用的模型结构:
from tensorflow.keras.layers import Concatenate
encoder_inputs = keras.layers.Input(batch_input_shape=[32,None], dtype=np.int32)
decoder_inputs = keras.layers.Input(batch_input_shape=[32,None], dtype=np.int32)
embeddings = keras.layers.Embedding(vocab_size, 1)
encoder_embeddings = embeddings(encoder_inputs)
decoder_embeddings = embeddings(decoder_inputs)
encoder_0 = keras.layers.Dense(128)(encoder_embeddings)
encoder_0d = keras.layers.Dropout(0.4)(encoder_0)
encoder_0_1 = keras.layers.Dense(256)(encoder_0d)
encoder_0_1d = keras.layers.Dropout(0.2)(encoder_0_1)
encoder_0_2 = keras.layers.Dense(128)(encoder_0_1d)
encoder_0_2d = keras.layers.Dropout(0.05)(encoder_0_2)
encoder_0_3 = keras.layers.Dense(64)(encoder_0_2d)
encoder_1 = keras.layers.LSTM(64, return_state=True, return_sequences=True, recurrent_dropout=0.2)
encoder_lstm_bidirectional = keras.layers.Bidirectional(encoder_1)
encoder_output, state_h1, state_c1, state_h2, state_c2 = encoder_lstm_bidirectional(encoder_0_3)
encoder_state = [Concatenate()([state_h1, state_h2]), Concatenate()([state_c1, state_c2])]
sampler = tfa.seq2seq.sampler.TrainingSampler()
decoder_cell = keras.layers.LSTMCell(64*2)
output_layer = keras.layers.Dense(vocab_size)
decoder = tfa.seq2seq.basic_decoder.BasicDecoder(decoder_cell, sampler, output_layer=output_layer)
final_outputs, final_state, final_sequence_lengths = decoder(decoder_embeddings, initial_state=encoder_state,
sequence_length=[sequence_length], training=True)
y_proba = tf.nn.softmax(final_outputs.rnn_output)
model = keras.Model(inputs=[encoder_inputs, decoder_inputs], outputs=[y_proba])
如果需要,我可以在github中部署整个笔记本,但也许有一个简单的解决方案,我只是到目前为止没有看到。 感谢您的帮助!
因此,如果这对将来的任何人有帮助: 该模型完全按照我的要求去做。
但是
您需要小心,您的数据预处理不会导致歧义。 所以你必须防止这样的事情:
a -> b and also a -> c
在改进一个方程式的同时,另一个方程式将丢失。那是我的问题。 看这个例子:
eq1: 26.04.1994 -> 26.04.1994
eq2: 26.04.1994 -> Tuesday, 26.04.1994
一方面,模型提高了 eq1 的准确性。另一方面,它减少了 eq2 的损失。所以 74% 是一种妥协,模型找到了。
为了解决这个问题,我不得不添加另一个因素,它更具体地描述了数据。所以我额外加了一个条件,描述y是写出来还是只写成date类型。所以现在我有一个像下面这样的数据结构,我的准确率增长到 98%:
eq1: 26.04.1994, dateformat -> 26.04.1994
eq2: 26.04.1994, written_out -> Tuesday, 26.04.1994