{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# **NOTEBOOK 19**\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# **Text-To-Text Transfer Transformer (T5)**\n", "\n", "El modelo T5, o **Text-To-Text Transfer Transformer**, es un modelo de lenguaje muy versátil desarrollado por Google Research. Fue introducido en un artículo titulado \"Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer\" por Colin Raffel y otros en 2019. El modelo se basa en la arquitectura Transformer, que se ha convertido en un estándar de facto para muchas tareas de procesamiento de lenguaje natural (NLP).\n", "\n", "### **Diseño y Filosofía**\n", "\n", "El modelo T5 adopta un enfoque unificado hacia el procesamiento del lenguaje natural: trata todas las tareas de NLP como una tarea de \"texto a texto\". Esto significa que cada tarea, ya sea traducción de idiomas, resumen de texto, clasificación de sentimientos, o cualquier otra, se formula de manera que el input y el output son siempre secuencias de texto. Por ejemplo:\n", "- **Traducción**: El input es texto en un idioma, y el output es texto en otro idioma.\n", "- **Resumen**: El input es un documento largo, y el output es su resumen.\n", "- **Clasificación de sentimiento**: El input es una reseña, y el output es una etiqueta de sentimiento como \"positivo\" o \"negativo\".\n", "\n", "

\n", " \n", "
\n", "\n", "### **Arquitectura**\n", "\n", "T5 es un modelo basado en la arquitectura Transformer, que utiliza bloques de encoder y decoder:\n", "- **Encoder**: Convierte el texto de entrada en una serie de representaciones intermedias o embeddings que capturan el contexto y el significado del texto.\n", "- **Decoder**: Utiliza las representaciones del encoder, junto con la salida generada previamente, para producir el texto de salida.\n", "\n", "### **Preentrenamiento**\n", "\n", "T5 fue preentrenado en un dataset diverso llamado \"Colossal Clean Crawled Corpus\" (C4), que es un subset limpio y filtrado del Common Crawl.\n", "\n", "### **Fases de entrenamiento**\n", "\n", "T5 se entrena en dos fases:\n", "1. **Preentrenamiento**: El modelo aprende a entender y generar texto en general a partir de grandes cantidades de texto no etiquetado.\n", "2. **Fine-tuning**: El modelo se ajusta a tareas específicas de NLP usando datasets etiquetados más pequeños. Aquí es donde el enfoque de \"texto a texto\" del modelo se adapta fácilmente a una variedad de tareas simplemente cambiando los formatos de los datos de entrada y salida.\n", "\n", "### **Variantes**\n", "\n", "En la biblioteca Hugging Face Transformers, el modelo T5 está disponible en varios tamaños que se adaptan a diferentes requisitos de rendimiento y capacidades de procesamiento. Cada tamaño del modelo ofrece un equilibrio entre velocidad, uso de memoria y precisión. Estas son las variantes disponibles:\n", "\n", "1. **T5 Small**\n", " - **Parámetros**: Aproximadamente 60 millones.\n", " - **Uso**: Ideal para aplicaciones con restricciones de recursos y para pruebas rápidas de conceptos.\n", "\n", "2. **T5 Base**\n", " - **Parámetros**: Aproximadamente 220 millones.\n", " - **Uso**: Un buen equilibrio entre rendimiento y tamaño, adecuado para muchas aplicaciones de producción.\n", "\n", "3. **T5 Large**\n", " - **Parámetros**: Aproximadamente 770 millones.\n", " - **Uso**: Para cuando se necesita una mayor precisión en las tareas y se dispone de más recursos de computación.\n", "\n", "4. **T5 3B**\n", " - **Parámetros**: Aproximadamente 3 mil millones.\n", " - **Uso**: Usado en escenarios donde la precisión es crítica y se dispone de infraestructura para manejar modelos grandes.\n", "\n", "5. **T5 11B**\n", " - **Parámetros**: Aproximadamente 11 mil millones.\n", " - **Uso**: Este tamaño es extremadamente grande, utilizado principalmente en investigación y situaciones donde se necesitan las capacidades máximas del modelo.\n", "\n", "#### **Cómo elegir el tamaño adecuado**\n", "\n", "La elección del tamaño del modelo depende de varios factores:\n", "- **Recursos disponibles**: Más parámetros generalmente requieren más memoria y poder de procesamiento.\n", "- **Requisitos de la tarea**: Tareas más complejas pueden beneficiarse de modelos más grandes.\n", "- **Latencia**: Modelos más pequeños ofrecen respuestas más rápidas, lo cual es crucial para aplicaciones en tiempo real.\n", "- **Costo**: El entrenamiento y la inferencia en modelos más grandes pueden ser más costosos en términos de computación y tiempo.\n", "\n", "Puedes acceder a estos modelos directamente a través de la interfaz de Hugging Face Transformers, lo cual facilita su uso y experimentación en una amplia gama de tareas de procesamiento del lenguaje natural.\n", "\n", "### **Ejemplos de uso mediante Hugging Face Transformers**\n", "\n", "Aquí tienes un ejemplo de cómo cargar y usar el modelo T5 en Hugging Face Transformers para hacer resúmenes de texto:\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/cayetano/Propio/Notebooks/Machine Learning/RL/env/lib/python3.10/site-packages/transformers/models/t5/tokenization_t5.py:240: FutureWarning: This tokenizer was incorrectly instantiated with a model max length of 512 which will be corrected in Transformers v5.\n", "For now, this behavior is kept to avoid breaking backwards compatibility when padding/encoding with `truncation is True`.\n", "- Be aware that you SHOULD NOT rely on t5-base automatically truncating your input to 512 when padding/encoding.\n", "- If you want to encode/pad to sequences longer than 512 you can either instantiate this tokenizer with `model_max_length` or pass `max_length` when encoding/padding.\n", "- To avoid this warning, please instantiate this tokenizer with `model_max_length` set to your preferred value.\n", " warnings.warn(\n", "You are using the default legacy behaviour of the . This is expected, and simply means that the `legacy` (previous) behavior will be used so nothing changes for you. If you want to use the new behaviour, set `legacy=False`. This should only be set if you understand what it means, and thoroughly read the reason why this was added as explained in https://github.com/huggingface/transformers/pull/24565\n", "Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Resumen: the Beatles were an english rock band formed in 1960. they are regarded as the most influential band of all time. they were integral to the development of 1960s counterculture.\n" ] } ], "source": [ "from transformers import T5ForConditionalGeneration, T5Tokenizer\n", "\n", "def sumarize(text, model_name=\"t5-base\", task=\"summarize\"):\n", " # Cargamos el tokenizador y el modelo\n", " tokenizer = T5Tokenizer.from_pretrained(model_name)\n", " model = T5ForConditionalGeneration.from_pretrained(model_name)\n", "\n", " # Preparamos la entrada\n", " input_text = f\"{task}: {text}\"\n", " input_ids = tokenizer.encode(input_text, return_tensors=\"pt\")\n", "\n", " # Generamos la salida\n", " outputs = model.generate(input_ids, max_length=100)\n", " summarized_text = tokenizer.decode(outputs[0], skip_special_tokens=True)\n", "\n", " return summarized_text\n", "\n", "# Ejemplo de resumen\n", "text = \"\"\"\n", "\"The Beatles were an English rock band formed in Liverpool in 1960, comprising John Lennon, Paul McCartney, George Harrison and Ringo Starr. They are regarded as the most influential band of all time and were integral to the development of 1960s counterculture and the recognition of popular music as an art form.\n", "\"\"\"\n", "print(\"Resumen:\", sumarize(text, task=\"summarize\")) # <-- Fíjate en el argumento task. En función de este argumento, el modelo realizará una tarea u otra" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vamos a ver cómo traducir de inglés a francés utilizando el modelo T5:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Inglés a Francés: Les Beatles sont un groupe rock anglais formé à Liverpool en 1960, composé de John Lennon, Paul McCartney, George Harrison et Ringo Starr.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Inglés a Francés: Ils sont considérés comme le groupe le plus influent de tous les temps et ont joué un rôle essentiel dans le développement de la contreculture des années 1960 et la reconnaissance de la musique populaire comme forme d'art.\n" ] } ], "source": [ "from transformers import T5ForConditionalGeneration, T5Tokenizer\n", "\n", "def translate(text, model_name=\"t5-base\", task=\"translate English to French\"):\n", " # Cargamos el tokenizador y el modelo\n", " tokenizer = T5Tokenizer.from_pretrained(model_name)\n", " model = T5ForConditionalGeneration.from_pretrained(model_name)\n", "\n", " # Preparamos la entrada\n", " input_text = f\"{task}: {text}\"\n", " input_ids = tokenizer.encode(input_text, return_tensors=\"pt\")\n", "\n", " # Generamos la salida\n", " outputs = model.generate(input_ids, max_length=100)\n", " translated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)\n", "\n", " return translated_text\n", "\n", "# Ejemplo de traducción del inglés al francés\n", "text_en_to_es = \"The Beatles were an English rock band formed in Liverpool in 1960, comprising John Lennon, Paul McCartney, George Harrison and Ringo Starr.\"\n", "print(\"Inglés a Francés:\", translate(text_en_to_es, task=\"translate English to French\"))\n", "text_en_to_es = \"They are regarded as the most influential band of all time and were integral to the development of 1960s counterculture and the recognition of popular music as an art form.\"\n", "print(\"Inglés a Francés:\", translate(text_en_to_es, task=\"translate English to French\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **Ejemplo: Transcripción de números a textos**\n", "\n", "T5 puede ser utilizado directamente a través de la biblioteca `transformers` de Hugging Face, que proporciona APIs de alto nivel para cargar el modelo, tokenizar textos, y generar predicciones. Esto hace que sea relativamente sencillo implementar soluciones de NLP avanzadas utilizando T5.\n", "\n", "Vamos, por tanto, a implementar un ejemplo que nos permita entender cómo funciona T5 y cómo podemos utilizarlo para tareas de procesamiento de lenguaje natural propias. En este caso, utilizaremos el modelo T5 Base para realizar la transcripción de un número representado con sus dígitos a sus palabras en inglés. Por ejemplo, si el número es \"123\", la transcripción sería \"one hundred twenty-three\". Lo haremos en inglés en lugar de español para aprovechar la capacidad de T5 de trabajar con texto en inglés y porque, en tareas de traducción, el modelo solo ha sido entrenado en alemán, francés y rumando, además del inglés." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Importamos las librerías necesarias para crear el dataset." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "40cac93e69ae4c4fab939352fa7f6721", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Downloading data files: 0%| | 0/1 [00:00. This is expected, and simply means that the `legacy` (previous) behavior will be used so nothing changes for you. If you want to use the new behaviour, set `legacy=False`. This should only be set if you understand what it means, and thoroughly read the reason why this was added as explained in https://github.com/huggingface/transformers/pull/24565\n", "Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.\n" ] } ], "source": [ "from transformers import T5Tokenizer\n", "\n", "tokenizer = T5Tokenizer.from_pretrained('t5-base')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Recuerdas que antes vimos que el input del dataset estaba en formato entero. Para poder utilizarlo con el modelo T5, necesitamos convertirlo a texto. Además, queremos añadir a cada ejemplo la tarea específica que queremos que el modelo realice. En este caso, la tarea es \"number to text\". Para todo esto vamos a crear la función `add_task`. Fíjate que numbers puede ser tanto un número entero como una lista de números enteros." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def add_task(numbers):\n", " if isinstance(numbers, int):\n", " return \"number to text: \" + str(numbers)\n", " else:\n", " res = []\n", " for number in numbers:\n", " text = str(number)\n", " text = \"number to text: \" + text\n", " res.append(text)\n", " return res" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Veamos qué aspecto tiene un ejemplo después de aplicar la función `add_task`." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['number to text: 123456789',\n", " 'number to text: 111111111',\n", " 'number to text: 987654321']" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "add_task([123456789, 111111111, 987654321])" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def preprocess_function(examples):\n", " number_ids = add_task(examples['input_text'])\n", " text_input = tokenizer(number_ids, truncation=True, padding=\"max_length\", max_length=15)\n", " labels = tokenizer(examples['output_text'], truncation=True, padding=\"max_length\", max_length=32)\n", "\n", " return {\n", " 'input_ids': text_input['input_ids'],\n", " 'labels': labels['input_ids']\n", " }\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Veamos qué aspecto tiene un conjunto de ejemplos antes y después de aplicar la función `preprocess_function`." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'input_text': [330237353, 517569757, 313407361], 'output_text': ['three hundred thirty million two hundred thirty seven thousand three hundred fifty three', 'five hundred seventeen million five hundred sixty nine thousand seven hundred fifty seven', 'three hundred thirteen million four hundred seven thousand three hundred sixty one']}\n", "------------------------------\n", "{'input_ids': [[381, 12, 1499, 10, 3, 17225, 2773, 4552, 4867, 1, 0, 0, 0, 0, 0], [381, 12, 1499, 10, 305, 2517, 4834, 4327, 3436, 1, 0, 0, 0, 0, 0], [381, 12, 1499, 10, 2664, 21129, 4552, 4241, 1, 0, 0, 0, 0, 0, 0]], 'labels': [[386, 6189, 12010, 770, 192, 6189, 12010, 2391, 7863, 386, 6189, 18358, 386, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [874, 6189, 30552, 770, 874, 6189, 27757, 4169, 7863, 2391, 6189, 18358, 2391, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [386, 6189, 27255, 770, 662, 6189, 2391, 7863, 386, 6189, 27757, 80, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]}\n" ] } ], "source": [ "print(dataset['train'][:3])\n", "print(\"------------------------------\")\n", "print(preprocess_function(dataset['train'][:3]))" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "eight\n", "e\n", "en\n", "seventeen\n", "sixteen\n", "\n" ] } ], "source": [ "a = tokenizer(\"eighteen seventeen sixteen\")\n", "\n", "\n", "for i in a['input_ids']:\n", " print(tokenizer.decode([i]))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ahora cargamos el modelo T5 Base preentrenado y lo afinamos para realizar la tarea de transcripción de números a texto." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "wandb: Network error (ConnectionError), entering retry loop.\n", "\u001b[34m\u001b[1mwandb\u001b[0m: Network error resolved after 0:11:26.707014, resuming normal operation.\n", "wandb: Network error (ConnectionError), entering retry loop.\n" ] } ], "source": [ "from transformers import T5ForConditionalGeneration, TrainingArguments, Trainer\n", "\n", "model = T5ForConditionalGeneration.from_pretrained('t5-base')\n", "\n", "training_args = TrainingArguments(\n", " output_dir='./results', # output directory\n", " num_train_epochs=3, # total number of training epochs\n", " per_device_train_batch_size=16, # batch size per device during training\n", " per_device_eval_batch_size=64, # batch size for evaluation\n", " warmup_steps=500, # number of warmup steps for learning rate scheduler\n", " weight_decay=0.01, # strength of weight decay\n", " logging_dir='./logs', # directory for storing logs\n", " logging_steps=10,\n", ")\n", "\n", "trainer = Trainer(\n", " model=model, # the instantiated 🤗 Transformers model to be trained\n", " args=training_args, # training arguments, defined above\n", " train_dataset=dataset['train'].map(preprocess_function, batched=True), # training dataset\n", " eval_dataset=dataset['test'].map(preprocess_function, batched=True), # evaluation dataset\n", ")\n", "\n", "trainer.train()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Una vez completado el entrenamiento, vamos a hacer alguna prueba." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "one hundred one million\n" ] } ], "source": [ "input_ids = tokenizer(\"number to text: 1000\", return_tensors=\"pt\").input_ids.to('mps')\n", "outputs = model.generate(input_ids, max_length=50, num_beams=1)\n", "output_text = tokenizer.decode(outputs[0], skip_special_tokens=True)\n", "\n", "print(output_text)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **Tamaño del modelo y recursos**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "El modelo T5 (Text-to-Text Transfer Transformer), incluido el T5-base, generalmente maneja secuencias de entrada cuya longitud máxima predeterminada es de 512 tokens. Este límite está configurado así en los modelos preentrenados disponibles en la biblioteca Hugging Face Transformers.\n", "\n", "Veamos cuántos tokens de entrada y salida tiene el modelo T5 Base." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tamaño máximo de la entrada: 512 tokens\n", "Memoria ocupada por el modelo: 850.31 MB\n", "Número de parámetros del modelo: 222.9 millones\n" ] } ], "source": [ "print(f\"Tamaño máximo de la entrada: {tokenizer.model_max_length} tokens\") # Generalmente será 512\n", "\n", "# Memoria ocupada por el modelo en MB\n", "model_size = sum(p.numel() for p in model.parameters())\n", "print(f\"Memoria ocupada por el modelo: {round(model_size * 4 / 1024**2, 2)} MB\")\n", "\n", "# Número de parámetros del modelo en millones\n", "print(f\"Número de parámetros del modelo: {round(model_size/10**6,2)} millones\")" ] } ], "metadata": { "kernelspec": { "display_name": "env", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.7" } }, "nbformat": 4, "nbformat_minor": 2 }