我正在尝试训练我的模型以生成不再超过 210 个字符的句子。从我读到的内容来看,我只看到了对“连续”文本的训练。就像一本书。不过,我正在尝试在单个句子上训练我的模型。
我对 tensorflow 和机器学习还很陌生,所以现在我可以训练我的模型,但它会生成垃圾、看似随机的文本。我有 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
当我给模型一个开始的序列时,我得到了绝对的废话,最终模型预测了一个不在 char_index 映射中的 0。
编辑
文本生成
epochs = 2
# Directory where the checkpoints will be saved
checkpoint_dir = './training_checkpoints'
# Name of the checkpoint files
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt_{epoch}")
checkpoint_callback=tf.keras.callbacks.ModelCheckpoint(
filepath=checkpoint_prefix,
save_weights_only=True)
model = create_model(vocab_size = vocab_size,
embed_dim=embed_dim,
rnn_neurons=rnn_neurons,
batch_size=1)
model.load_weights(tf.train.latest_checkpoint(checkpoint_dir))
model.build(tf.TensorShape([1, None]))
def generate_text(model, start_string):
num_generate = 200
input_eval = [char_2_index[s] for s in start_string]
input_eval = tf.expand_dims(input_eval, 0)
text_generated = []
temperature = 1
# model.reset_states()
for i in range(num_generate):
print(text_generated)
predictions = model(input_eval)
predictions = tf.squeeze(predictions, 0)
predictions = predictions / temperature
predicted_id = tf.random.categorical(predictions, num_samples=1)[-1,0].numpy()
print(predicted_id)
input_eval = tf.expand_dims([predicted_id], 0)
text_generated.append(index_2_char[predicted_id])
return (start_string + ''.join(text_generated))
最佳答案
乍一看,有一些事情必须改变。
- 分词器必须具有
num_words = vocab_size
- 一开始(没有深入分析),我无法想象如果数据集的结构可能正确,为什么要展平数据集并获取切片
- 如果您不希望“第 2 批是第 1 批的续集”,则不能使用
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
关于python - 使用 Tensorflow 模型正确构建文本数据以生成文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60170063/