如何从 Pandas DataFrame 到 NLP 的 Tensorflow BatchDataset?

How do I go from Pandas DataFrame to Tensorflow BatchDataset for NLP?

老实说,我正在尝试弄清楚如何将数据集(格式:pandas DataFrame 或 numpy 数组)转换为简单文本分类张量流模型可以训练的形式情绪分析。我使用的数据集类似于 IMDB(包含文本和标签(正面或负面))。我看过的每个教程要么以不同的方式准备数据,要么没有为数据准备而烦恼,而是任由您想象。 (例如,所有 IMDB 教程都从 tensorflow_datasets 导入预处理的 Tensorflow BatchDataset,这在我使用自己的数据集时没有帮助)。我自己将 Pandas DataFrame 转换为 Tensorflow 的 Dataset 类型的尝试导致了 ValueErrors 或训练期间的负损失。任何帮助将不胜感激。

我最初准备的数据如下,其中 trainingvalidation 已经洗牌 Pandas DataFrames 包含 textlabel 列:

# IMPORT STUFF

from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf # (I'm using tensorflow 2.0)
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.preprocessing.text import Tokenizer
import pandas as pd
import numpy as np
# ... [code for importing and preparing the pandas dataframe omitted]

# TOKENIZE

train_text = training['text'].to_numpy()
tok = Tokenizer(oov_token='<unk>')
tok.fit_on_texts(train_text)
tok.word_index['<pad>'] = 0
tok.index_word[0] = '<pad>'

train_seqs = tok.texts_to_sequences(train_text)
train_seqs = tf.keras.preprocessing.sequence.pad_sequences(train_seqs, padding='post')

train_labels = training['label'].to_numpy().flatten()

valid_text = validation['text'].to_numpy()
valid_seqs = tok.texts_to_sequences(valid_text)
valid_seqs = tf.keras.preprocessing.sequence.pad_sequences(valid_seqs, padding='post')

valid_labels = validation['label'].to_numpy().flatten()

# CONVERT TO TF DATASETS

train_ds = tf.data.Dataset.from_tensor_slices((train_seqs,train_labels))
valid_ds = tf.data.Dataset.from_tensor_slices((valid_seqs,valid_labels))

train_ds = train_ds.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
valid_ds = valid_ds.batch(BATCH_SIZE)

# PREFETCH

train_ds = train_ds.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
valid_ds = valid_ds.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)

这导致 train_ds 和 valid_ds 被标记化并且类型为 PrefetchDataset<PrefetchDataset shapes: ((None, None, None, 118), (None, None, None)), types: (tf.int32, tf.int64)>

然后我按如下方式训练,但得到了 大的负损失和 0 的准确度。

model = keras.Sequential([
    layers.Embedding(vocab_size, embedding_dim),
    layers.GlobalAveragePooling1D(),
    layers.Dense(1, activation='sigmoid') # also tried activation='softmax'
])

model.compile(optimizer='adam',
              loss='binary_crossentropy', # binary_crossentropy
              metrics=['accuracy'])

history = model.fit(
    train_ds,
    epochs=1,
    validation_data=valid_ds, validation_steps=1, steps_per_epoch=BUFFER_SIZE)

如果我不做花哨的预取操作,train_ds 将是 BatchDataset<BatchDataset shapes: ((None, 118), (None,)), types: (tf.int32, tf.int64)> 类型,但这也会让我产生负损失和准确度0.

如果我只执行以下操作:

x, y = training['text'].to_numpy(), training['label'].to_numpy()
x, y = tf.convert_to_tensor(x),tf.convert_to_tensor(y)

然后 xy 属于 EagerTensor 类型,但我似乎无法弄清楚如何批处理 EagerTensor.

train_ds我真正需要什么类型和形状?我错过了什么或做错了什么?

text_classification_with_hub tutorial 训练一个已经准备好的 imdb 数据集,如下所示:

model = tf.keras.Sequential()
model.add(hub_layer)
model.add(tf.keras.layers.Dense(16, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

history = model.fit(train_data.shuffle(10000).batch(512),
                    epochs=20,
                    validation_data=validation_data.batch(512),
                    verbose=1)

在此示例中,train_data 的格式为 tensorflow.python.data.ops.dataset_ops._OptionsDataset,而 train_data.shuffle(1000).batch(512)tensorflow.python.data.ops.dataset_ops.BatchDataset(或 <BatchDataset shapes: ((None,), (None,)), types: (tf.string, tf.int64)>)。

他们显然不关心这个数据集的标记化,但我怀疑标记化是我的问题。为什么他们的 train_data.shuffle(10000).batch(512) 有效而我的 train_ds 无效?

问题可能与模型设置、Embedding 层或标记化有关,但我不太确定情况是否如此。我已经看过以下教程以获取灵感:

https://www.tensorflow.org/tutorials/keras/text_classification_with_hub

https://www.kaggle.com/drscarlat/imdb-sentiment-analysis-keras-and-tensorflow

https://www.tensorflow.org/tutorials/text/image_captioning

https://www.tensorflow.org/tutorials/text/word_embeddings#learning_embeddings_from_scratch

https://thedatafrog.com/word-embedding-sentiment-analysis/

更新: 我发现问题是我忽略了将目标标签转换为 0 和 1 以进行二元交叉熵。该问题与转换为 Tensorflow 数据集类型无关。我上面的代码可以很好地实现这一点。