#python #pandas #tensorflow
#python #панды #тензорный поток
Вопрос:
Я использую набор данных tensorflow imdb_review и хочу предварительно обработать его с помощью Tokenizer и pad_sequences
Когда я использую экземпляр Tokenizer и использую следующий код:
tokenizer=Tokenizer(num_words=100)
tokenizer.fit_on_texts(df['text'])
word_index = tokenizer.word_index
sequences=tokenizer.texts_to_sequences(df['text'])
print(word_index)
print(sequences)
Я получаю ошибку TypeError: требуется объект, подобный байтам, а не «dict»
Что я пробовал
сохраните dataset как dataframe, а затем выполните итерацию по текстовому столбцу и сохраните его в списке, а затем маркируйте его.
df = tfds.as_dataframe(ds.take(4), info)
# list to store corpus
corpus = []
for sentences in df['text'].iteritems():
corpus.append(sentences)
tokenizer=Tokenizer(num_words=100)
tokenizer.fit_on_texts(corpus)
word_index=tokenizer.word_index
print(word_index)
Но я получаю ошибку AttributeError: объект ‘tuple’ не имеет атрибута ‘lower’
Как я могу использовать столбец «текст» и предварительно обработать его, чтобы передать его в мою нейронную сеть?
Ответ №1:
Все, что вам нужно, это преобразовать ['text']
столбец в numpy
первый с последующей необходимой маркировкой и заполнением. Ниже приведен полный рабочий код. Наслаждайтесь.
Набор данных
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
# get the data first
imdb = tfds.load('imdb_reviews', as_supervised=True)
Подготовка данных
# we will only take train_data (for demonstration purpose)
# do the same for test_data in your case
train_data, test_data = imdb['train'], imdb['test']
training_sentences = []
training_labels = []
for sentence, label in train_data:
training_sentences.append(str(sentence.numpy()))
training_labels.append(str(label.numpy()))
training_labels_final = np.array(training_labels).astype(np.float)
print(training_sentences[0]) # first samples
print(training_labels_final[0]) # first label
# b"This was an absolutely terrible movie. ...."
# 0.0
Предварительная обработка — токенизатор заполнение
vocab_size = 2000 # The maximum number of words to keep, based on word frequency.
embed_size = 30 # Dimension of the dense embedding.
max_len = 100 # Length of input sequences, when it is constant.
# https://keras.io/api/preprocessing/text/
tokenizer = Tokenizer(num_words=vocab_size,
filters='!"#$%amp;()* ,-./:;<=>?@[\]^_`{|}~tn',
lower=True,
split=" ",
oov_token="<OOV>")
tokenizer.fit_on_texts(training_sentences)
print(tokenizer.word_index)
# {'<OOV>': 1, 'the': 2, 'and': 3, 'a': 4, 'of': 5, 'to': 6, 'is': 7, ...
# tokenized and padding
training_sequences = tokenizer.texts_to_sequences(training_sentences)
training_padded = pad_sequences(training_sequences, maxlen=max_len, truncating='post')
print(training_sentences[0])
print()
print(training_padded[0])
# b"This was an absolutely terrible movie. ...."
#
[ 59 12 14 35 439 400 18 174 29 1 9 33 1378 1
42 496 1 197 25 88 156 19 12 211 340 29 70 248
213 9 486 62 70 88 116 99 24 1 12 1 657 777
12 18 7 35 406 1 178 1 426 2 92 1253 140 72
149 55 2 1 1 72 229 70 1 16 1 1 1 1
1506 1 3 40 1 119 1608 17 1 14 163 19 4 1253
927 1 9 4 18 13 14 1 5 102 148 1237 11 240
692 13]
Модель
Пример модели.
# Input for variable-length sequences of integers
inputs = tf.keras.Input(shape=(None,), dtype="int32")
# Embed each integer
x = tf.keras.layers.Embedding(input_dim = vocab_size,
output_dim = embed_size,
input_length=max_len)(inputs)
# Add 2 bidirectional LSTMs
x = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64, return_sequences=True))(x)
x = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64))(x)
# Add a classifier
outputs = tf.keras.layers.Dense(1, activation="sigmoid")(x)
model = tf.keras.Model(inputs, outputs)
# Compile and Run
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
model.fit(training_padded,
training_labels_final,
epochs=10,
verbose=1)
Epoch 1/10
782/782 [==============================] - 25s 18ms/step - loss: 0.5548 - accuracy: 0.6915
Epoch 2/10
782/782 [==============================] - 14s 18ms/step - loss: 0.3921 - accuracy: 0.8248
...
782/782 [==============================] - 14s 18ms/step - loss: 0.2171 - accuracy: 0.9121
Epoch 9/10
782/782 [==============================] - 14s 17ms/step - loss: 0.1807 - accuracy: 0.9275
Epoch 10/10
782/782 [==============================] - 14s 18ms/step - loss: 0.1486 - accuracy: 0.9428
Комментарии:
1. Спасибо! У меня была проблема с частью подготовки данных, которая была очень полезной.
Ответ №2:
Вы можете преобразовать df[ 'text' ]
столбец в массив NumPy, вызвав to_numpy()
метод. Смотрите документы здесь. Кроме того, рассмотрите документы Tokenizer.fit_on_texts
отсюда.
corpus = df[ 'text' ].to_numpy()
tokenizer = Tokenizer( num_words=100 )
tokenizer.fit_on_texts(corpus)
Tokenizer.fit_on_texts
Метод вызывается text_elem.lower()
внутренне. Но поскольку вы не предоставляете ему список String
, вы получаете исключение. Вот фрагмент из исходного кода.
...
for text in texts:
self.document_count = 1
if self.char_level or isinstance(text, list):
if self.lower:
if isinstance(text, list):
text = [text_elem.lower() for text_elem in text]
else:
...
Комментарии:
1. Я попытался использовать .to_numpy() после прочтения вашего ответа, но все равно получаю ту же ошибку, что странно, потому что, когда я проверял тип корпуса, это o / p равно dtype=obj , и в соответствии с ошибкой должен использоваться объект. Я даже попытался использовать список строк, как показано в документации tf. Я попытаюсь использовать набор данных извне, загрузив его, я обновлю, когда найду решение.