Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/tutorials/load_data/text.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Carga de texto

En este tutorial se demuestran dos formas de cargar y preprocesar texto.

  • Primero, deberá usar las utilidades y las capas de procesamiento de Keras. Esto incluye tf.keras.utils.text_dataset_from_directory para convertir los datos en un tf.data.Dataset y tf.keras.layers.TextVectorization para la estandarización, la "tokenización" y la vectorización de datos. Si no ha trabajado antes con TensorFlow, debería empezar con esto.

  • Después, usará utilidades de bajo nivel como tf.data.TextLineDataset para cargar los archivos de texto y las API TensorFlow Text, como text.UnicodeScriptTokenizer y text.case_fold_utf8, para procesar previamente los datos y lograr un control de granulado fino.

!pip install "tensorflow-text==2.11.*"
import collections import pathlib import tensorflow as tf from tensorflow.keras import layers from tensorflow.keras import losses from tensorflow.keras import utils from tensorflow.keras.layers import TextVectorization import tensorflow_datasets as tfds import tensorflow_text as tf_text

Ejemplo 1: predicción de la etiqueta para una pregunta de Stack Overflow

Como primer ejemplo, deberá descargar un conjunto de datos de preguntas sobre programación de Stack Overflow. Cada pregunta ("How do I sort a dictionary by value?") (¿Cómo ordeno un diccionario por valores?) está marcada exactamente con una etiqueta (Python, CSharp, JavaScript o Java). La tarea consiste en desarrollar un modelo que prediga la etiqueta para una pregunta. Este es un ejemplo de clasificación en clases múltiples, un tipo importante y ampliamente aplicable de problemas relacionados con el aprendizaje automático.

Descarga y exploración de conjuntos de datos

Comience por descargar el conjunto de datos de Stack Overflow con tf.keras.utils.get_file y explore la estructura del directorio:

data_url = 'https://storage.googleapis.com/download.tensorflow.org/data/stack_overflow_16k.tar.gz' dataset_dir = utils.get_file( origin=data_url, untar=True, cache_dir='stack_overflow', cache_subdir='') dataset_dir = pathlib.Path(dataset_dir).parent
list(dataset_dir.iterdir())
train_dir = dataset_dir/'train' list(train_dir.iterdir())

Los directorios train/csharp, train/java, train/python y train/javascript contienen muchos archivos de texto, cada uno es una pregunta de Stack Overflow.

Imprima un archivo de ejemplo e inspeccione los datos:

sample_file = train_dir/'python/1755.txt' with open(sample_file) as f: print(f.read())

Carga del conjunto de datos

A continuación, deberá cargar los datos en memoria y prepararlos en un formato adecuado para el entrenamiento. Para hacerlo, deberá usar la utilidad tf.keras.utils.text_dataset_from_directory, a fin de crear un tf.data.Dataset marcado. Si no ha usado antes tf.data, deberá saber que es una recopilación potente de herramientas para construir canalizaciones de entrada. (Para más información, consulte la guía sobre tf.data: Construir canalizaciones de entrada de TensorFlow).

La API tf.keras.utils.text_dataset_from_directory espera una estructura de directorio como la siguiente:

train/ ...csharp/ ......1.txt ......2.txt ...java/ ......1.txt ......2.txt ...javascript/ ......1.txt ......2.txt ...python/ ......1.txt ......2.txt

A la hora de hacer un experimento de aprendizaje automático, lo mejor es dividir el conjunto de datos en tres partes: entrenamiento, validación y prueba.

El conjunto de datos Stack Overflow ya se ha dividido en conjuntos de prueba y entrenamiento, pero aún falta un conjunto de validación.

Cree un conjunto de validación con una proporción de 80:20 de los datos de entrenamiento tf.keras.utils.text_dataset_from_directory con validation_split configurado como 0.2 (es decir, 20 %):

batch_size = 32 seed = 42 raw_train_ds = utils.text_dataset_from_directory( train_dir, batch_size=batch_size, validation_split=0.2, subset='training', seed=seed)

Tal como lo sugieren los resultados de celdas anteriores, hay 8000 ejemplos en la carpeta de entrenamiento, de los cuales se usará el 80% (o 6400) para entrenamiento. En un momento aprenderá que puede entrenar un modelo pasando un tf.data.Dataset directamente a Model.fit.

Primero, itere sobre el conjunto de datos e imprima algunos ejemplos para familiarizarse con los datos.

Nota: Para aumentar la dificultad del problema de clasificación, el autor del conjunto de datos reemplazó las apariciones de las palabras Python, CSharp, JavaScript o Java en la pregunta de programación con la palabra blank.

for text_batch, label_batch in raw_train_ds.take(1): for i in range(10): print("Question: ", text_batch.numpy()[i]) print("Label:", label_batch.numpy()[i])

Las etiquetas son 0, 1, 2 o 3. Para comprobar cuáles corresponden a qué etiqueta de cadena, se puede inspeccionar la propiedad class_names en el conjunto de datos:

for i, label in enumerate(raw_train_ds.class_names): print("Label", i, "corresponds to", label)

A continuación, creará un conjunto de datos de validación y prueba con tf.keras.utils.text_dataset_from_directory. Usará las 1600 reseñas restantes del conjunto de entrenamiento para ejecutar la validación.

Nota: Cuando use los argumentos validation_split y subset de tf.keras.utils.text_dataset_from_directory, asegúrese de especificar una semilla aleatoria o de pasar shuffle=False, para que las fracciones de validación y entrenamiento no se superpongan.

# Create a validation set. raw_val_ds = utils.text_dataset_from_directory( train_dir, batch_size=batch_size, validation_split=0.2, subset='validation', seed=seed)
test_dir = dataset_dir/'test' # Create a test set. raw_test_ds = utils.text_dataset_from_directory( test_dir, batch_size=batch_size)

Preparación del conjunto de datos para entrenamiento

A continuación, usará la capa tf.keras.layers.TextVectorization para estandarizar, tokenizar y vectorizar los datos.

  • La estandarización se refiere al procesamiento previo del texto. Normalmente, quitar la puntuación o los elementos HTML para simplificar el conjunto de datos.

  • La tokenización se refiere a la separación de cadenas en tokens (por ejemplo, al separar una oración en palabras individuales haciendo la división en los espacios en blanco).

  • La vectorización se refiere a convertir tokens en números para que se puedan usar para alimentar una red neuronal.

Todas estas tareas se pueden cumplir con esta capa. (Para más información sobre cada una de estas opciones, consulte los documentos sobre la API tf.keras.layers.TextVectorization).

Tenga en cuenta que:

  • La estandarización predeterminada transforma el texto en minúscula y quita la puntuación (standardize='lower_and_strip_punctuation').

  • El tokenizador predeterminado hace las divisiones en los espacios en blanco (split='whitespace').

  • El modo de vectorización predeterminado es 'int' (output_mode='int'). Devuelve índices enteros (uno por token). Este modo se puede usar para crear modelos que tengan en cuenta el orden de las palabras. También puede usar otros modelos, como 'binary' para crear modelos bolsa de palabras.

Cree dos modelos para aprender más sobre la estandarización, la tokenización y la vectorización con TextVectorization:

  • Primero, use el modo de vectorización 'binary' para crear un modelo de bolsa de palabras.

  • Después, use el modo 'int' con una ConvNet de 1 D.

VOCAB_SIZE = 10000 binary_vectorize_layer = TextVectorization( max_tokens=VOCAB_SIZE, output_mode='binary')

Para el modo 'int', además del tamaño de vocabulario máximo, necesitará establecer una longitud de secuencia máxima (MAX_SEQUENCE_LENGTH) explícita, que hará que la capa rellene o trunque las secuencias según los valores output_sequence_length exactos:

MAX_SEQUENCE_LENGTH = 250 int_vectorize_layer = TextVectorization( max_tokens=VOCAB_SIZE, output_mode='int', output_sequence_length=MAX_SEQUENCE_LENGTH)

A continuación, llamará TextVectorization.adapt para que ajuste el estado de la capa de preprocesamiento al conjunto de datos. Esto hará que el modelo convierta un índice de cadenas a enteros.

Nota: Es importante que solamente use los datos de entrenamiento para llamar a TextVectorization.adapt, ya que si usa el conjunto de prueba, se podría filtrar información.

# Make a text-only dataset (without labels), then call `TextVectorization.adapt`. train_text = raw_train_ds.map(lambda text, labels: text) binary_vectorize_layer.adapt(train_text) int_vectorize_layer.adapt(train_text)

Imprima el resultado de usar estas capas para el procesamiento previo de los datos:

def binary_vectorize_text(text, label): text = tf.expand_dims(text, -1) return binary_vectorize_layer(text), label
def int_vectorize_text(text, label): text = tf.expand_dims(text, -1) return int_vectorize_layer(text), label
# Retrieve a batch (of 32 reviews and labels) from the dataset. text_batch, label_batch = next(iter(raw_train_ds)) first_question, first_label = text_batch[0], label_batch[0] print("Question", first_question) print("Label", first_label)
print("'binary' vectorized question:", binary_vectorize_text(first_question, first_label)[0])
print("'int' vectorized question:", int_vectorize_text(first_question, first_label)[0])

Tal como se muestra arriba, el modo 'binary' de TextVectorization devuelve un arreglo que denota qué tokens existen al menos una vez en la entrada; mientras que el modo 'int' reemplaza a cada token por un entero y así conserva su orden.

Se puede llamar a TextVectorization.get_vocabulary en la capa para buscar el token (cadena) al que corresponde cada entero:

print("1289 ---> ", int_vectorize_layer.get_vocabulary()[1289]) print("313 ---> ", int_vectorize_layer.get_vocabulary()[313]) print("Vocabulary size: {}".format(len(int_vectorize_layer.get_vocabulary())))

Ya esta casi todo listo para entrenar el modelo.

Como último paso, deberá aplicara las capas de TextVectorization que creó antes para los conjuntos de entrenamiento, validación y prueba:

binary_train_ds = raw_train_ds.map(binary_vectorize_text) binary_val_ds = raw_val_ds.map(binary_vectorize_text) binary_test_ds = raw_test_ds.map(binary_vectorize_text) int_train_ds = raw_train_ds.map(int_vectorize_text) int_val_ds = raw_val_ds.map(int_vectorize_text) int_test_ds = raw_test_ds.map(int_vectorize_text)

Configuración del conjunto de datos para rendimiento

Hay dos métodos importantes que debería usar cuando cargue los datos para garantizar que la entrada o la salida no se bloqueen.

  • .cache() conserva los datos en la memoria después de que descarga del disco. Esto evitará que el conjunto de datos se transforme en un cuello de botella mientras entrena su modelo. Si su conjunto de datos es demasiado grande para caber en la memoria, también puede usar este método para crear un potente caché en disco, que se lea de forma más eficiente que muchos archivos pequeños.

  • Dataset.prefetch se superpone con el procesamiento de los datos y la ejecución del modelo durante el entrenamiento.

Para más información sobre ambos métodos y sobre cómo almacenar los datos en la memoria caché del disco, consulte la sección Preextracción de la guía Mejor rendimiento con la API tf.data API.

AUTOTUNE = tf.data.AUTOTUNE def configure_dataset(dataset): return dataset.cache().prefetch(buffer_size=AUTOTUNE)
binary_train_ds = configure_dataset(binary_train_ds) binary_val_ds = configure_dataset(binary_val_ds) binary_test_ds = configure_dataset(binary_test_ds) int_train_ds = configure_dataset(int_train_ds) int_val_ds = configure_dataset(int_val_ds) int_test_ds = configure_dataset(int_test_ds)

Entrenamiento del modelo

Llegó la hora de crear su red neuronal.

Para los datos 'binary' vectorizados, defina un modelo lineal de bolsa de palabras simple. Luego, prepárelo y entrénelo:

binary_model = tf.keras.Sequential([layers.Dense(4)]) binary_model.compile( loss=losses.SparseCategoricalCrossentropy(from_logits=True), optimizer='adam', metrics=['accuracy']) history = binary_model.fit( binary_train_ds, validation_data=binary_val_ds, epochs=10)

Luego, use la capa vectorizada 'int' para crear una ConvNet de 1 D:

def create_model(vocab_size, num_labels): model = tf.keras.Sequential([ layers.Embedding(vocab_size, 64, mask_zero=True), layers.Conv1D(64, 5, padding="valid", activation="relu", strides=2), layers.GlobalMaxPooling1D(), layers.Dense(num_labels) ]) return model
# `vocab_size` is `VOCAB_SIZE + 1` since `0` is used additionally for padding. int_model = create_model(vocab_size=VOCAB_SIZE + 1, num_labels=4) int_model.compile( loss=losses.SparseCategoricalCrossentropy(from_logits=True), optimizer='adam', metrics=['accuracy']) history = int_model.fit(int_train_ds, validation_data=int_val_ds, epochs=5)

Compare los dos modelos:

print("Linear model on binary vectorized data:") print(binary_model.summary())
print("ConvNet model on int vectorized data:") print(int_model.summary())

Evalúe ambos modelos con los datos de prueba:

binary_loss, binary_accuracy = binary_model.evaluate(binary_test_ds) int_loss, int_accuracy = int_model.evaluate(int_test_ds) print("Binary model accuracy: {:2.2%}".format(binary_accuracy)) print("Int model accuracy: {:2.2%}".format(int_accuracy))

Nota: En este ejemplo el conjunto de datos representa un problema de clasificación bastante simple. Los conjuntos de datos y problemas más complejos presentan diferencias sutiles pero importantes en las estrategias de procesamiento de datos y las arquitecturas del modelo. Pruebe diferentes hiperparámetros y épocas para comparar los distintos métodos.

Exportación del modelo

En el código que vimos arriba, se aplicó tf.keras.layers.TextVectorization al conjunto de datos antes de alimentar el modelo con el texto. Si desea que su modelo sea capaz de procesar cadenas sin procesar (por ejemplo, para simplificar la implementación), puede incluir la capa TextVectorization dentro del modelo.

Para hacerlo, puede crear un modelo nuevo con los pesos que ha entrenado recién:

export_model = tf.keras.Sequential( [binary_vectorize_layer, binary_model, layers.Activation('sigmoid')]) export_model.compile( loss=losses.SparseCategoricalCrossentropy(from_logits=False), optimizer='adam', metrics=['accuracy']) # Test it with `raw_test_ds`, which yields raw strings loss, accuracy = export_model.evaluate(raw_test_ds) print("Accuracy: {:2.2%}".format(accuracy))

Ahora, su modelo puede tomar las cadenas sin procesar como entradas y predecir un puntaje para cada etiqueta con Model.predict. Defina una función para buscar la etiqueta con el puntaje máximo:

def get_string_labels(predicted_scores_batch): predicted_int_labels = tf.math.argmax(predicted_scores_batch, axis=1) predicted_labels = tf.gather(raw_train_ds.class_names, predicted_int_labels) return predicted_labels

Ejecución de la inferencia en datos nuevos

inputs = [ "how do I extract keys from a dict into a list?", # 'python' "debug public static void main(string[] args) {...}", # 'java' ] predicted_scores = export_model.predict(inputs) predicted_labels = get_string_labels(predicted_scores) for input, label in zip(inputs, predicted_labels): print("Question: ", input) print("Predicted label: ", label.numpy())

Incluir la lógica de preprocesamiento de textos en su modelo le permitirá exportar un modelo para producción que simplifique la implementación y reduzca la probabilidad de que se produzca un sesgo entre entrenamiento y prueba.

Hay una diferencia de rendimiento que debemos tener en cuenta a la hora de elegir dónde aplicar la capa tf.keras.layers.TextVectorization. Si la usa fuera del modelo puede hacer un procesamiento asincrónico en CPU y almacenar en búfer los datos cuando se entrena en GPU. Por lo tanto, si entrena su modelo en GPU, probablemente debería elegir esta opción para obtener el mejor rendimiento mientras desarrolla su modelo y luego, cambiar para incluir la capa TextVectorization dentro de su modelo, cuando esté listo para prepararse para la implementación.

Para más información acerca de cómo guardar modelos, consulte el tutorial sobre cómo guardar y cargar modelos.

Ejemplo 2: predicción de los autores de las traducciones de La Ilíada

A continuación, se brinda un ejemplo de cómo se usa tf.data.TextLineDataset para cargar ejemplos a partir de archivos de texto y TensorFlow Text para procesar los datos. Usará tres traducciones diferentes del mismo trabajo, la Ilíada de Homero, al idioma inglés y entrenará un modelo para identificar al autor con una sola línea de texto.

Descarga y exploración de conjuntos de datos

Los autores de los textos de las tres traducciones son:

Los archivos de texto usados en este tutorial ya sufrieron algunas modificaciones realizadas con algunas tareas típicas de procesamiento como las de quitar el encabezado y el pie de página, los números de línea y los títulos de los capítulos.

Descargue estos archivos ligeramente modificados en un dispositivo local:

DIRECTORY_URL = 'https://storage.googleapis.com/download.tensorflow.org/data/illiad/' FILE_NAMES = ['cowper.txt', 'derby.txt', 'butler.txt'] for name in FILE_NAMES: text_dir = utils.get_file(name, origin=DIRECTORY_URL + name) parent_dir = pathlib.Path(text_dir).parent list(parent_dir.iterdir())

Carga del conjunto de datos

Anteriormente, con tf.keras.utils.text_dataset_from_directory todo el contenido de un archivo se trataba como un único ejemplo. Ahora, usará tf.data.TextLineDataset, que está diseñado para crear un tf.data.Dataset a partir de un archivo de texto en el que cada ejemplo es una línea de texto del archivo original. TextLineDataset es útil para datos de texto que se basa principalmente en líneas (por ejemplo, registros de poesía o errores).

Itere en estos archivos, cargando cada uno en su propio conjunto de datos. Los ejemplos se deben etiquetar cada uno por separado. Entonces, use Dataset.map para aplicar una función para etiquetar a cada uno. Esto hará que se itere sobre cada ejemplo en el conjunto de datos, devolviendo pares (example, label).

def labeler(example, index): return example, tf.cast(index, tf.int64)
labeled_data_sets = [] for i, file_name in enumerate(FILE_NAMES): lines_dataset = tf.data.TextLineDataset(str(parent_dir/file_name)) labeled_dataset = lines_dataset.map(lambda ex: labeler(ex, i)) labeled_data_sets.append(labeled_dataset)

A continuación, combinará estos conjuntos de datos etiquetados en un único conjunto de datos con Dataset.concatenate y lo aleatorizará con Dataset.shuffle:

BUFFER_SIZE = 50000 BATCH_SIZE = 64 VALIDATION_SIZE = 5000
all_labeled_data = labeled_data_sets[0] for labeled_dataset in labeled_data_sets[1:]: all_labeled_data = all_labeled_data.concatenate(labeled_dataset) all_labeled_data = all_labeled_data.shuffle( BUFFER_SIZE, reshuffle_each_iteration=False)

Imprima algunos ejemplos como antes. El conjunto de datos todavía no se ha agrupado, por lo tanto cada entrada de all_labeled_data corresponde a un dato puntual:

for text, label in all_labeled_data.take(10): print("Sentence: ", text.numpy()) print("Label:", label.numpy())

Preparación del conjunto de datos para entrenamiento

En vez de usar tf.keras.layers.TextVectorization para el proceso previo del conjunto de datos de texto; en este caso, usará las API TensorFlow Text para estandarizar y tokenizar los datos. Además, elaborará un vocabulario y usará tf.lookup.StaticVocabularyTable para mapear los tokens con los enteros a fin de incorporarlos al modelo. (Acceda a más información sobre TensorFlow Text).

Defina una función para convertir el texto, pasarlo a minúsculas y tokenizarlo:

  • TensorFlow Text brinda varios tokenizadores. En este ejemplo, se usará el text.UnicodeScriptTokenizer para tokenizar el conjunto de datos.

  • Para aplicar la tokenización al conjunto de datos, deberá usar Dataset.map.

tokenizer = tf_text.UnicodeScriptTokenizer()
def tokenize(text, unused_label): lower_case = tf_text.case_fold_utf8(text) return tokenizer.tokenize(lower_case)
tokenized_ds = all_labeled_data.map(tokenize)

Se puede iterar sobre el conjunto de datos e imprimir algunos ejemplos tokenizados:

for text_batch in tokenized_ds.take(5): print("Tokens: ", text_batch.numpy())

A continuación, creará un vocabulario. Para ello, deberá ordenar los tokens por frecuencia y conservará los principales tokens VOCAB_SIZE:

tokenized_ds = configure_dataset(tokenized_ds) vocab_dict = collections.defaultdict(lambda: 0) for toks in tokenized_ds.as_numpy_iterator(): for tok in toks: vocab_dict[tok] += 1 vocab = sorted(vocab_dict.items(), key=lambda x: x[1], reverse=True) vocab = [token for token, count in vocab] vocab = vocab[:VOCAB_SIZE] vocab_size = len(vocab) print("Vocab size: ", vocab_size) print("First five vocab entries:", vocab[:5])

Para convertir los tokens en enteros, use el conjunto vocab y cree con él una tf.lookup.StaticVocabularyTable. Lo que hará será vincular (mapear) los tokens con los enteros en el rango [2, vocab_size + 2]. Del mismo modo, con la capa TextVectorization, se reserva 0 para denotar el amortiguado y se reserva 1 para denotar un token fuera del vocabulario (OOV).

keys = vocab values = range(2, len(vocab) + 2) # Reserve `0` for padding, `1` for OOV tokens. init = tf.lookup.KeyValueTensorInitializer( keys, values, key_dtype=tf.string, value_dtype=tf.int64) num_oov_buckets = 1 vocab_table = tf.lookup.StaticVocabularyTable(init, num_oov_buckets)

Finalmente, defina una función para estandarizar, tokenizar y vectorizar el conjunto de datos con el tokenizador y la tabla de búsqueda:

def preprocess_text(text, label): standardized = tf_text.case_fold_utf8(text) tokenized = tokenizer.tokenize(standardized) vectorized = vocab_table.lookup(tokenized) return vectorized, label

Puede intentarlo con un ejemplo solo para imprimir el resultado:

example_text, example_label = next(iter(all_labeled_data)) print("Sentence: ", example_text.numpy()) vectorized_text, example_label = preprocess_text(example_text, example_label) print("Vectorized sentence: ", vectorized_text.numpy())

Ahora, ejecute la función de preproceso del conjunto de datos con Dataset.map:

all_encoded_data = all_labeled_data.map(preprocess_text)

División de los conjuntos de datos en conjuntos de entrenamiento y prueba

La capa TextVectorization de Keras también se agrupa en lotes y amortigua los datos vectorizados. El amortiguado (padding) es necesario porque los ejemplos que se encuentran dentro de cada lote deben tener el mismo tamaño y la misma forma, pero los ejemplos de estos conjuntos de datos no son todos del mismo tamaño, cada línea de texto tiene una cantidad diferente de palabras.

tf.data.Dataset es compatible con la división y el agrupamiento amortiguado de los conjuntos de datos:

train_data = all_encoded_data.skip(VALIDATION_SIZE).shuffle(BUFFER_SIZE) validation_data = all_encoded_data.take(VALIDATION_SIZE)
train_data = train_data.padded_batch(BATCH_SIZE) validation_data = validation_data.padded_batch(BATCH_SIZE)

Ahora, validation_data y train_data no son recopilaciones de pares (example, label), sino de lotes. Cada lote es un par (muchos ejemplos, muchas etiquetas) representado como arreglo.

A modo ilustrativo:

sample_text, sample_labels = next(iter(validation_data)) print("Text batch shape: ", sample_text.shape) print("Label batch shape: ", sample_labels.shape) print("First text example: ", sample_text[0]) print("First label example: ", sample_labels[0])

Como usa 0 para el amortiguado y 1 para los tokens fuera de vocabulario (OOV), el tamaño del vocabulario ha aumentado a 2:

vocab_size += 2

Configure los conjuntos de datos para mejorar el rendimiento como antes:

train_data = configure_dataset(train_data) validation_data = configure_dataset(validation_data)

Entrenamiento del modelo

Igual que antes, puede entrenar el modelo de este conjunto de datos:

model = create_model(vocab_size=vocab_size, num_labels=3) model.compile( optimizer='adam', loss=losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) history = model.fit(train_data, validation_data=validation_data, epochs=3)
loss, accuracy = model.evaluate(validation_data) print("Loss: ", loss) print("Accuracy: {:2.2%}".format(accuracy))

Exportación del modelo

Para que el modelo sea capaz de tomar cadenas sin procesar como entradas, deberá crear una capa TextVectorization de Keras que realice los mismos pasos que su función de preprocesamiento personalizada. Como ya ha entrenado un vocabulario, puede usar TextVectorization.set_vocabulary, en vez de TextVectorization.adapt que entrena a un vocabulario nuevo.

preprocess_layer = TextVectorization( max_tokens=vocab_size, standardize=tf_text.case_fold_utf8, split=tokenizer.tokenize, output_mode='int', output_sequence_length=MAX_SEQUENCE_LENGTH) preprocess_layer.set_vocabulary(vocab)
export_model = tf.keras.Sequential( [preprocess_layer, model, layers.Activation('sigmoid')]) export_model.compile( loss=losses.SparseCategoricalCrossentropy(from_logits=False), optimizer='adam', metrics=['accuracy'])
# Create a test dataset of raw strings. test_ds = all_labeled_data.take(VALIDATION_SIZE).batch(BATCH_SIZE) test_ds = configure_dataset(test_ds) loss, accuracy = export_model.evaluate(test_ds) print("Loss: ", loss) print("Accuracy: {:2.2%}".format(accuracy))

La pérdida y la exactitud del modelo en el conjunto de validación codificado y en el modelo exportado en el conjunto de validación sin procesar son iguales, tal como se espera.

Ejecución de la inferencia en datos nuevos

inputs = [ "Join'd to th' Ionians with their flowing robes,", # Label: 1 "the allies, and his armour flashed about him so that he seemed to all", # Label: 2 "And with loud clangor of his arms he fell.", # Label: 0 ] predicted_scores = export_model.predict(inputs) predicted_labels = tf.math.argmax(predicted_scores, axis=1) for input, label in zip(inputs, predicted_labels): print("Question: ", input) print("Predicted label: ", label.numpy())

Descarga de más conjuntos de datos con TensorFlow Datasets (TFDS)

Puede descargar muchos más conjuntos de datos con los Datasets de TensorFlow.

Para este ejemplo, usará conjuntos de datos para revisión de películas largas de IMDB para entrenar un modelo de clasificación de sentimientos:

# Training set. train_ds = tfds.load( 'imdb_reviews', split='train[:80%]', batch_size=BATCH_SIZE, shuffle_files=True, as_supervised=True)
# Validation set. val_ds = tfds.load( 'imdb_reviews', split='train[80%:]', batch_size=BATCH_SIZE, shuffle_files=True, as_supervised=True)

Imprima algunos ejemplos:

for review_batch, label_batch in val_ds.take(1): for i in range(5): print("Review: ", review_batch[i].numpy()) print("Label: ", label_batch[i].numpy())

Ahora puede preprocesar los datos y entrenar un modelo como antes.

Nota: Deberá usar tf.keras.losses.BinaryCrossentropy en vez de tf.keras.losses.SparseCategoricalCrossentropy para su modelo, ya que se trata de un problema de clasificación binaria.

Preparación del conjunto de datos para entrenamiento

vectorize_layer = TextVectorization( max_tokens=VOCAB_SIZE, output_mode='int', output_sequence_length=MAX_SEQUENCE_LENGTH) # Make a text-only dataset (without labels), then call `TextVectorization.adapt`. train_text = train_ds.map(lambda text, labels: text) vectorize_layer.adapt(train_text)
def vectorize_text(text, label): text = tf.expand_dims(text, -1) return vectorize_layer(text), label
train_ds = train_ds.map(vectorize_text) val_ds = val_ds.map(vectorize_text)
# Configure datasets for performance as before. train_ds = configure_dataset(train_ds) val_ds = configure_dataset(val_ds)

Creación, configuración y entrenamiento del modelo

model = create_model(vocab_size=VOCAB_SIZE + 1, num_labels=1) model.summary()
model.compile( loss=losses.BinaryCrossentropy(from_logits=True), optimizer='adam', metrics=['accuracy'])
history = model.fit(train_ds, validation_data=val_ds, epochs=3)
loss, accuracy = model.evaluate(val_ds) print("Loss: ", loss) print("Accuracy: {:2.2%}".format(accuracy))

Exportación del modelo

export_model = tf.keras.Sequential( [vectorize_layer, model, layers.Activation('sigmoid')]) export_model.compile( loss=losses.SparseCategoricalCrossentropy(from_logits=False), optimizer='adam', metrics=['accuracy'])
# 0 --> negative review # 1 --> positive review inputs = [ "This is a fantastic movie.", "This is a bad movie.", "This movie was so bad that it was good.", "I will never say yes to watching this movie.", ] predicted_scores = export_model.predict(inputs) predicted_labels = [int(round(x[0])) for x in predicted_scores] for input, label in zip(inputs, predicted_labels): print("Question: ", input) print("Predicted label: ", label)

Conclusión

En este tutorial se demostraron varias formas de cargar y preprocesar texto. Para avanzar al paso siguiente, puede explorar otros tutoriales de TensorFlow Text sobre preprocesamiento de texto, tales como:

También puede buscar conjuntos nuevos de datos en TensorFlow Datasets. Y, para más información sobre tf.data, consulte la guía sobre cómo construir canalizaciones de entrada.