【问题标题】:Correctly structuring text data for text generation with Tensorflow model使用 Tensorflow 模型正确构建文本数据以生成文本
【发布时间】:2020-02-11 13:33:57
【问题描述】:

我正在尝试训练我的模型生成不再有 210 个字符的句子。从我读过的内容来看,我只看到了关于“连续”文本的培训。像一本书。但是我正在尝试用单个句子训练我的模型。

我对 tensorflow 和 ML 还很陌生,所以现在我可以训练我的模型,但它会生成垃圾,看似随机的文本。我有一万个句子,所以我认为我有足够的数据。

我的数据概览

结构 [['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))

【问题讨论】:

  • 您愿意展示您的训练方式和预测方式吗?

标签: python tensorflow machine-learning keras recurrent-neural-network


【解决方案1】:

有几件事必须一见钟情。

  • Tokenizer 必须有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

【讨论】:

  • 仍然得到看似随机的输出。
猜你喜欢
  • 2016-08-05
  • 2020-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
  • 2017-10-22
  • 1970-01-01
相关资源
最近更新 更多