Tensorflow中LSTM的一键编码(OHE)庞大语料库

时间:2019-11-20 08:44:42

标签: tensorflow keras nlp lstm one-hot-encoding

问题

我刮擦了一个受欢迎的网站的大量评论,为此我试图使用TensorFlow来构建LSTM架构来生成文本生成器。通常,这非常简单,但是考虑到数据集的大小,即使对GCP的AI平台进行一次热编码,我仍然遇到内存问题不太喜欢用大量内存来完成一项昂贵的工作。

我可以通过限制来解决它:

  1. 语料库长度
  2. 词汇量

但是我正在努力使它真正变得更好,而不是让价格降低。否则,我只能使用马尔可夫链。

可能的解决方案

  1. 我不应该将完整的数据集加载到内存中是常识。 我正在寻找与ImageDataGenerator等效的方法,但对于文本。我可以将One-Hot编码器安装在完整的数据集上,但是要逐批转换数据。我对TensorFlow的了解太有限,无法正确完成。

  2. 是否可以通过稀疏方式撕开内存中的OHEd标签

我遇到了一些遇到相同问题的人,但找不到解决方案。有人可以帮我吗?

提前谢谢!

这是我的代码。

代码

这是我的 task.py 中的相关部分,我在其中进行标记和一键编码。

# tokenize corpus
if hparams.trim_corpus != 0:
    corpus = corpus[:hparams.trim_corpus]
tokenizer = Tokenizer(num_words = hparams.n_words_to_keep, oov_token = '<OOV>')
tokenizer.fit_on_texts(corpus)

# create input sequences using list of tokens
input_sequences = []
for line in corpus:
    token_list = tokenizer.texts_to_sequences([line])[0]
    for i in range(1, len(token_list)):
        n_gram_sequence = token_list[:i+1]
        input_sequences.append(n_gram_sequence)

# pad sequences 
input_sequences = np.array(pad_sequences(input_sequences, maxlen=model.MAX_SEQUENCE_LENGTH, padding='pre'))

# Create predictors and label
predictors, labels = input_sequences[:,:-1],input_sequences[:,-1]

# Filter most common words
most_common_items = [item[0] for item in Counter(labels).most_common(hparams.vocab_size)]
indices_to_keep = [True if b in most_common_items else False for b in labels]
predictors = predictors[indices_to_keep]
labels = labels[indices_to_keep]

这是发生问题的地方。将OHE转换应用于训练数据集时,在本地和GCP中都会出现内存错误。


# Train-test split + encoding
X_train, X_test, y_train, y_test = train_test_split(predictors, labels, test_size = 0.2)

enc = OneHotEncoder(handle_unknown='ignore')
enc.fit(y_train.reshape(-1,1))
y_train = enc.transform(y_train.reshape(-1,1)).toarray()
y_test = enc.transform(y_test.reshape(-1,1)).toarray()

exporter = tf.estimator.LatestExporter('exporter', model.serving_input_fn) # What is this?

train_input_fn = lambda: model.input_fn(X_train, y_train, hparams.batch_size, mode = tf.estimator.ModeKeys.TRAIN)
eval_input_fn = lambda: model.input_fn(X_test, y_test, hparams.batch_size, mode = tf.estimator.ModeKeys.EVAL)

train_steps = hparams.num_epochs * len(y_train) / hparams.batch_size

train_spec = tf.estimator.TrainSpec(train_input_fn, max_steps = train_steps)
eval_spec = tf.estimator.EvalSpec(eval_input_fn, steps = None, start_delay_secs=10, throttle_secs=10, exporters=exporter)

# Generate Configuration.
run_config = tf.estimator.RunConfig(save_checkpoints_steps=500)

# Create estimator
estimator = model.keras_estimator(model_dir=hparams.job_dir, config=run_config, learning_rate=hparams.learning_rate, vocab_size=hparams.vocab_size, n_words_to_keep = hparams.n_words_to_keep)

# Start training
tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)

最后,这是我的模型。py。

def input_fn(features, labels, batch_size, mode):
    inputs = (features, labels)
    # Convert the inputs to a Dataset.
    dataset = tf.data.Dataset.from_tensor_slices(inputs)
    if mode == tf.estimator.ModeKeys.TRAIN:
        dataset = dataset.shuffle(1000).repeat().batch(batch_size)
    if mode in (tf.estimator.ModeKeys.EVAL, tf.estimator.ModeKeys.PREDICT):
        dataset = dataset.batch(batch_size)
    return dataset.make_one_shot_iterator().get_next()

1 个答案:

答案 0 :(得分:0)

您是否尝试过使用tf.data.TextLineDataset? 这将从文本文件的每一行中读取。读完每一行后,您可以标记和一键编码。

示例

def read_data(fname, batch_size):
   dataset=tf.data.TextLineDataset(fname)
   # Can tokenize and one-hot encode here
   dataset=dataset.batch(batch_size)
   return dataset

data = read_data(fname)
iterator = iter(data)
example = next(iterator)