我正在尝试训练我的模型以生成不再超过210个字符的句子。从我所读的书中,我仅看到有关“连续”文本的培训。就像一本书。但是我试图用单句话训练我的模型。
我对tensorflow和ML相当陌生,所以现在我可以训练我的模型,但是它会产生垃圾,看似随机的文本。我有10,000个句子,所以我认为我有足够的数据。
我的数据概述
结构[['SENTENCE'],['SENTENCE2'] ...]
数据准备
tokenizer = keras.preprocessing.text.Tokenizer(num_words=209, lower=False, char_level=True, filters='#$%&()*+-<=>@[\\]^_`{|}~\t\n')
tokenizer.fit_on_texts(df['title'].values)
df['encoded_with_keras'] = tokenizer.texts_to_sequences(df['title'].values)
dataset = df['encoded_with_keras'].values
dataset = tf.keras.preprocessing.sequence.pad_sequences(dataset, padding='post')
dataset = dataset.flatten()
dataset = tf.data.Dataset.from_tensor_slices(dataset)
sequences = dataset.batch(seq_len+1, drop_remainder=True)
def create_seq_targets(seq):
input_txt = seq[:-1]
target_txt = seq[1:]
return input_txt, target_txt
dataset = sequences.map(create_seq_targets)
dataset = dataset.shuffle(buffer_size).batch(batch_size, drop_remainder=True)
模型
def create_model(vocab_size, embed_dim, rnn_neurons, batch_size):
model = Sequential()
model.add(Embedding(vocab_size, embed_dim, batch_input_shape=[batch_size, None],input_length=209, mask_zero=True))
model.add(LSTM(rnn_neurons, return_sequences=True, stateful=True,))
model.add(Dropout(0.2))
model.add(Dense(258, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(vocab_size, activation='softmax'))
model.compile(optimizer='adam', loss="sparse_categorical_crossentropy")
return model
[当我给模型一个序列以开始时,我得到绝对的废话,并且最终模型预测到0,该值不在char_index映射中。
乍一看,有些事情必须更改。
num_words = vocab_size
stateful=True
,因为您有单独的句子,所以stateful=False
。 (除非您正在使用手动训练循环进行正确的训练并为每个批次重置状态,否则这在训练阶段是不必要的麻烦)您需要目视检查的内容:
输入数据必须具有以下格式:
[
[1,2,3,6,10,4,10, ...up to sentence length - 1...],
[5,6,3,6,7,3,11,... up to sentence length - 1...],
.... up to number of sentences ...
]
输出数据必须是:
[
[2,3,6,10,4,10,15 ...], #equal to input data, shifted by 1
[6,3,6,7,3,11,13, ...],
...
]
打印其中的几行,以检查它们是否按预期进行了正确的预处理。
培训然后很容易:
model.fit(input_data, output_data, epochs=....)
是的,您的模型将预测零,因为您的数据中有零,这并不奇怪:您做了pad_sequences
。在这种情况下,您可以将零解释为“句子结尾”,因为您进行了'post'
填充。当您的模型给您一个零时,它决定所生成的句子应在该点结束-如果它受过良好的训练,从那时起,它可能会继续为该句子输出零。
这部分比较复杂,您需要重写模型,现在是stative=True
,并将权重从训练有素的模型转移到这个新模型。
之前,请致电model.reset_states()
。
您将需要手动喂入形状为(number_of_sentences=batch_size, 1)
的批次。这将是它将生成的每个句子的“第一个字符”。输出将是每个句子的“第二个字符”。
获取此输出,并随其输入模型。它将生成每个句子的“第三个字符”。等等。
当所有输出均为零时,将完全生成所有句子,您可以停止循环。
在尝试生成新的句子之前,再次呼叫model.reset_states()
。
您可以在此处找到这种预测的示例:https://stackoverflow.com/a/50235563/2097240