Как перейти от Pandas DataFrame к Tensorflow BatchDataset для НЛП? - PullRequest
0 голосов
/ 13 октября 2019

Я, честно говоря, пытаюсь выяснить, как преобразовать набор данных (формат: pandas DataFrame или массив numpy) в форму, которую простая модель тензорного потока с классификацией текста может использовать для анализа настроений. Набор данных, который я использую, аналогичен IMDB (содержит текст и метки (положительные или отрицательные)). В каждом уроке, на который я смотрел, либо данные готовились по-разному, либо они не занимались подготовкой данных и оставляли их на ваше воображение. (Например, все руководства по IMDB импортируют предварительно обработанный Tensorflow BatchDataset из tensorflow_datasets, что бесполезно, когда я использую свой собственный набор данных). Мои собственные попытки конвертировать Pandas DataFrame в типы Tensorflow Dataset привели к ValueErrors или отрицательным потерям во время обучения. Буду признателен за любую помощь.

Я изначально подготовил свои данные следующим образом, где training и validation - это уже перетасованные панды 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 обучает уже подготовленный набор данных 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/

1 Ответ

0 голосов
/ 17 октября 2019

ОБНОВЛЕНИЕ: Я выяснил, что проблема заключалась в том, что я забыл преобразовать целевые метки в 0 и 1 для двоичной перекрестной энтропии. Проблема не имела ничего общего с преобразованием в тип набора данных Tensorflow. Мой приведенный выше код отлично подходит для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...