如何从 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 或训练期间的负损失。任何帮助将不胜感激。
我最初准备的数据如下,其中 training
和 validation
已经洗牌 Pandas DataFrame
s 包含 text
和 label
列:
# 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)
然后 x
和 y
属于 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
更新: 我发现问题是我忽略了将目标标签转换为 0 和 1 以进行二元交叉熵。该问题与转换为 Tensorflow 数据集类型无关。我上面的代码可以很好地实现这一点。
老实说,我正在尝试弄清楚如何将数据集(格式:pandas DataFrame
或 numpy 数组)转换为简单文本分类张量流模型可以训练的形式情绪分析。我使用的数据集类似于 IMDB(包含文本和标签(正面或负面))。我看过的每个教程要么以不同的方式准备数据,要么没有为数据准备而烦恼,而是任由您想象。 (例如,所有 IMDB 教程都从 tensorflow_datasets
导入预处理的 Tensorflow BatchDataset
,这在我使用自己的数据集时没有帮助)。我自己将 Pandas DataFrame
转换为 Tensorflow 的 Dataset
类型的尝试导致了 ValueErrors 或训练期间的负损失。任何帮助将不胜感激。
我最初准备的数据如下,其中 training
和 validation
已经洗牌 Pandas DataFrame
s 包含 text
和 label
列:
# 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)
然后 x
和 y
属于 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
更新: 我发现问题是我忽略了将目标标签转换为 0 和 1 以进行二元交叉熵。该问题与转换为 Tensorflow 数据集类型无关。我上面的代码可以很好地实现这一点。