{ "cells": [ { "cell_type": "markdown", "id": "65c9fdf3", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Hugging Face: IA Colaborativa\n", "=========================" ] }, { "cell_type": "markdown", "id": "32a802c2", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "¿Quién soy?\n", "------------------\n", "\n", "
\n", "

Cristian Cardellino

\n", "
Profesor de FAMAFyC (UNC) - Investigador en Mercado Libre
\n", "
\n", " \n", "
\n", "
\n", " @crscardellino -\n", " @crscardellino@mastodon.social -\n", " https://crscardellino.ar\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "bb685a55", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Esquema de la charla\n", "\n", "1. [¿Qué hay detrás de ChatGPT?](#¿Qué-hay-detrás-de-ChatGPT?)\n", "2. [Hugging Face](#Hugging-Face)\n", "3. [Utilizando un modelo de Hugging Face](#Utilizando-un-modelo-de-Hugging-Face)\n", "4. [Personalizando un modelo de Hugging Face](#Personalizando-un-modelo-de-Hugging-Face)" ] }, { "cell_type": "markdown", "id": "eb7f3997", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# ¿Qué hay detrás de ChatGPT?" ] }, { "cell_type": "markdown", "id": "87d1ca59", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Cómo continúa esta frase?\n", "\n", "

You ...

" ] }, { "cell_type": "markdown", "id": "1e5a5c6b", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "

You shall ...

" ] }, { "cell_type": "markdown", "id": "f71da59e", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "

You shall not ...

" ] }, { "cell_type": "markdown", "id": "2910e985", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "
\n", "

You shall not pass!

\n", "
\n", " \n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "283ca08c", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Qué son los \"modelos de lenguaje\"? (Language Models)\n", "\n", "- Modelos de aprendizaje automático.\n", "- Dado un contexto (e.g. una lista de palabras previas), predicen la palabra siguiente.\n", "- Se entrenan con texto libre." ] }, { "cell_type": "markdown", "id": "778b5e91", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "### ¿Qué son los \"LLMs\"? (Large Language Models)\n", "\n", "- Modelos de lenguajes entrenados con una gran cantidad de datos y de parámetros:\n", " - Suelen entrenarse con corpus del orden de $10^{10}$ palabras.\n", " - Suelen tener de $10^8$ o $10^9$ parámetros en adelante.\n", "- El término se asocia generalmente a aquellos modelos basados en la arquitectura neuronal del **Transformer**." ] }, { "cell_type": "markdown", "id": "cfc710ea", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Qué es un \"Transformer\"?\n", "\n", "- Es una arquitectura de red neuronal basada en el concepto de \"Atención\" que se presentó en el paper [\"Attention is All You Need\"](https://arxiv.org/abs/1706.03762).\n", "- Originalmente se planteó como un esquema para hacer traducción automática.\n", " - Consta de dos partes: Un codificador y un decodificador.\n", " - A partir de este surgieron dos variantes\n", " - Los modelos basados en el codificador (e.g. [BERT](https://arxiv.org/abs/1810.04805)). Sirven para buscar representaciones vectoriales (embeddings) del texto.\n", " - Los modelos basados en el decodificador (e.g. [GPT](https://arxiv.org/abs/2005.14165)). Sirven para generación de texto.\n", "- La idea del transformer es \"definir\" una palabra de acuerdo a la relación que tiene con las palabras de su vecindario, en una operación de multiplicación matricial con pesos.\n", " - Para una explicación más sencilla pero más detallada sugiero los posts de la serie \"The Illustrated...\" de [Jay Alammar](http://jalammar.github.io/):\n", " - [The Illustrated Transformer](http://jalammar.github.io/illustrated-transformer/)\n", " - [The Illustrated BERT](http://jalammar.github.io/illustrated-bert/)\n", " - [The Illustrated GPT-2](http://jalammar.github.io/illustrated-gpt2/) / [How GPT-3 Works](http://jalammar.github.io/how-gpt3-works-visualizations-animations/)" ] }, { "cell_type": "markdown", "id": "8958cf42", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Hugging Face" ] }, { "cell_type": "markdown", "id": "6038bd78", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Qué es Hugging Face?\n", "\n", "- Una [comunidad colaborativa](https://huggingface.co/) para hacer Inteligencia Artificial (IA).\n", "- Cuenta con repositorios para subir [modelos](https://huggingface.co/models), [datasets](https://huggingface.co/datasets) y [demos](https://huggingface.co/spaces).\n", "- Además, ofrecen varias librerías orientadas a la IA, particularmente al Aprendizaje Profundo (Deep Learning), entre las que destacan:\n", " - [`transformers`](https://huggingface.co/docs/transformers): La que veremos en esta charla, para todo lo relacionado a NLP con LLMs.\n", " - [`datasets`](https://huggingface.co/docs/datasets): Una librería especializada en el tratamiento de los conjuntos de datos a utilizar para entrenar/ajustar los LLMs.\n", " - [`tokenizers`](https://huggingface.co/docs/tokenizers): Para el proceso de \"tokenización\", i.e. la división de texto de manera discreta en palabras o subpalabras.\n", "- Hugging Face no sólo ofrece soluciones sobre NLP, sino que también lo hace con imágenes, con librerías como [`diffusers`](https://huggingface.co/docs/diffusers), para la generación de imágenes:\n", " - Lectura recomendada: [The Illustrated Stable Diffusion](http://jalammar.github.io/illustrated-stable-diffusion/)" ] }, { "cell_type": "markdown", "id": "25ad7d45", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Cómo empezar con Hugging Face?\n", "\n", "- Primero se [crea una cuenta en la página](https://huggingface.co/join).\n", "- Luego podemos [crear modelos](https://huggingface.co/new) a través del menú que se despliega de nuestro avatar.\n", "- Una vez creado el modelo, este es un repositorio de git que puede accederse clonándolo localmente.\n", " - Requiere de [`git-lfs`](https://git-lfs.com/)." ] }, { "cell_type": "markdown", "id": "3c6f89c3", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Utilizando un modelo de Hugging Face" ] }, { "cell_type": "markdown", "id": "d06c7318", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Cargando los modelos\n", "\n", "- Hugging Face ofrece muchísimos modelos en su [repositorio](https://huggingface.co/models), para este caso elegimos el modelo [`bigscience/bloom-3b`](https://huggingface.co/bigscience/bloom-3b) de la organización [Big Science](https://bigscience.huggingface.co/blog/bloom).\n", " - Esta organización ha estado [creando modelos](https://huggingface.co/bigscience) bajo una [licencia abierta](https://bigscience.huggingface.co/blog/the-bigscience-rail-license) (con ciertas limitaciones de uso para evitar abuso).\n", " - Son responsables del [LLM abierto más grande actualmente disponible](https://huggingface.co/bigscience/bloom).\n", "- El modelo elegido es un modelo de 3 mil millones (3 billion) de parámetros." ] }, { "cell_type": "code", "execution_count": null, "id": "0e0d53be", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "import torch\n", "\n", "from IPython.display import display, HTML\n", "from transformers import AutoModelForCausalLM, AutoTokenizer\n", "\n", "BASE_MODEL = 'bigscience/bloom-3b' # More models at https://huggingface.co/models\n", "\n", "tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)\n", "model = AutoModelForCausalLM.from_pretrained(\n", " BASE_MODEL,\n", " low_cpu_mem_usage=True,\n", " torch_dtype='auto'\n", ")" ] }, { "cell_type": "markdown", "id": "022de9b5", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Generando Texto a Partir de un PROMPT\n", "\n", "- Los modelos de lenguaje necesitan una semilla, denominada comúnmente **prompt**, para iniciar su conversación.\n", "- A partir de dicha semilla, los modelos pueden empezar a predecir las palabras siguiente.\n", "- La coherencia de la frase depende de varios aspectos:\n", " - El tamaño y [entrenamiento](https://github.com/huggingface/notebooks/blob/main/examples/language_modeling_from_scratch.ipynb) o [ajuste](https://github.com/huggingface/notebooks/blob/main/examples/language_modeling.ipynb) (fine-tuning) del modelo.\n", " - Modelos más grandes suelen ser mejor en escenarios \"open end\", aunque pueden desvariar (o \"alucinar\").\n", " - El tipo de datos con el que se entrenó/ajustó el modelo.\n", " - La [estrategia](https://github.com/huggingface/blog/blob/main/notebooks/02_how_to_generate.ipynb) a la hora de generar texto.\n", " - La [documentación de Hugging Face](https://huggingface.co/docs/transformers/notebooks) tiene más ejemplos que pueden reproducirse." ] }, { "cell_type": "markdown", "id": "6e6b4464", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Estableciendo un PROMPT\n", "\n", "- El **prompt** inicial es el que \"ayudará\" al modelo a devolver resultados más o menos coherentes.\n", "- Actualmente es más un arte que una ciencia.\n", " - **No existe el \"prompt engineering\" porque los modelos no son determinísticos.**\n", "- Depende muchísimo del modelo, la inicialización aleatoria (i.e. la suerte), la tarea que se busca resolver, entre otros factores.\n", "- Siguiendo los ejemplos de [esta publicación](https://medium.com/@fractal.ai/create-conversational-agents-using-bloom-part-1-63a66e6321c0), y en vistas de armar un chatbot, buscaré definir 3 cosas:\n", " - La \"identidad\", i.e. ¿Qué es?\n", " - La \"intención\", i.e. ¿Qué hace?\n", " - El \"comportamiento\", i.e. ¿Cómo lo hace?\n", "- Además, se le pueden dar ejemplos concretos de cómo se espera que interactúe. Estos sirven a los LLMs para hacer lo que se conoce como \"Few Shot Learning\" (aunque no están \"aprendiendo\", los ejemplos sólo ayudan a mejorar el contexto." ] }, { "cell_type": "code", "execution_count": null, "id": "c1227c49", "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "PROMPT = \"\"\"\n", "La siguiente es una conversación entre un HUMANO y un bot EXPERTO en software libre.\n", "El EXPERTO le ayuda al HUMANO con preguntas acerca de software libre.\n", "El EXPERTO es conversacional, optimista, flexible, creativo y genera respuestas parecidas a un humano.\n", "\n", "HUMANO: Hola, ¿Cómo estás?\n", "EXPERTO: Hola, pmuy bien. Estoy acá para ayudarte con preguntas respecto al software libre.\n", "\n", "HUMANO: ¿Qué es el software libre?\n", "EXPERTO:\"\"\".strip()" ] }, { "cell_type": "markdown", "id": "82988db2", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Generando texto de manera \"Greedy\"\n", "\n", "- La estrategia para generar texto puede variar. La opción más directa es **greedy**, i.e. devolver la palabra que es más probable después de la secuencia.\n", " - La principal ventaja de esta alternativa, es que es determinística, i.e. ante la misma entrada debería devolver la misma salida.\n", " - La principal desventaja es que tiende a repetir y quedar limitada a ciertas frases o palabras." ] }, { "cell_type": "code", "execution_count": null, "id": "11bec6de", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "MAX_TOKENS = 50\n", "input_ids = tokenizer.encode(PROMPT, return_tensors='pt')\n", "greedy_output = model.generate(input_ids, max_length=input_ids.shape[1] + MAX_TOKENS)\n", "output = tokenizer.decode(greedy_output[0], skip_special_tokens=True)\n", "\n", "print(output)" ] }, { "cell_type": "markdown", "id": "ba05a269", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Generando texto usando aleatoriedad\n", "\n", "- Si bien hay [varias estrategias para generar texto libre](https://github.com/huggingface/blog/blob/main/notebooks/02_how_to_generate.ipynb) una que resulta muy interesante es mediante el sampleo estadístico.\n", "- La idea es que la manera de seleccionar la siguiente palabra es con cierta probabilidad estadística (i.e. no siempre la más probable).\n", " - La principal ventaja es que hace el texto más \"creativo\" y más \"humano\".\n", " - La principal desventaja es que no es determinístico y es suceptible de \"alucinar\".\n", " - En este caso se samplea de las `top_k` palabras más probable que a su vez son la menor cantidad de palabras cuya probabilidad conjunta es mayor que `top_p`." ] }, { "cell_type": "code", "execution_count": null, "id": "dc66f288", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "torch.manual_seed(42) # To ensure determinism\n", "\n", "sampling_output = model.generate(\n", " input_ids,\n", " do_sample=True,\n", " max_length=input_ids.shape[1] + MAX_TOKENS,\n", " top_k=50,\n", " top_p=0.95,\n", ")\n", "output = tokenizer.decode(sampling_output[0], skip_special_tokens=True)\n", "\n", "print(output)" ] }, { "cell_type": "markdown", "id": "98bdd38e", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Un Chatbot Sencillo\n", "\n", "- El modelo de lenguaje no tiene noción de cuando parar, porque está entrenado para continuar el mensaje dado en el **prompt**.\n", " - Seguirá generando texto hasta alcanzar el valor del parámetro `max_length`.\n", " - El texto generado inluirá las palabras que marcan la conversación (i.e. \"HUMANO\" y \"EXPERTO\").\n", "- Para poder utilizar un modelo para hacer un **chatbot** requerimos de un poco de ingeniería de software clásica.\n", " - Una opción es utilizar precisamente las palabras que definen la conversación como puntos de inicio y final, y descartar el resto.\n", "- En [`chatbot.py`](./chatbot.py) hay un ejemplo sencillo de cómo puede realizarse esto.\n", " - Consiste de una clase `ChatBot` que sirve como *wrapper* de los modelos de Hugging Face.\n", " - Posee un CLI sencillo que mantiene un loop continuo para chatear." ] }, { "cell_type": "code", "execution_count": null, "id": "a3e12232", "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "from chatbot import ChatBot # local module in the repository\n", "\n", "PROMPT = \"\"\"\n", "La siguiente es una conversación entre un HUMANO y un bot EXPERTO en software libre.\n", "El EXPERTO le ayuda al HUMANO con preguntas acerca de software libre.\n", "El EXPERTO es conversacional, optimista, flexible, creativo y genera respuestas parecidas a un humano.\n", "\n", "HUMANO: Hola, ¿Cómo estás?\n", "EXPERTO: Hola, muy bien. Estoy acá para ayudarte con preguntas respecto al software libre.\n", "\"\"\".strip()\n", "\n", "chatbot = ChatBot(\n", " base_model=model,\n", " tokenizer=tokenizer,\n", " initial_prompt=PROMPT,\n", " keep_context=True,\n", " creative=True,\n", " human_identifier='HUMAN',\n", " bot_identifier='EXPERTO'\n", ")\n", "\n", "while True:\n", " input_text = input('> ')\n", " if input_text == 'exit' or input_text == 'quit':\n", " break\n", " print(chatbot.chat(input_text))" ] }, { "cell_type": "markdown", "id": "6e570fc3", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Personalizando un modelo de Hugging Face" ] }, { "cell_type": "markdown", "id": "adb09645", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Cómo se entrenan los LLMs?\n", "\n", "- Para entrenar LLMs se requiere de muchos datos y mucho cómputo.\n", "- El modelo de GPT-3 se estima que tuvo un costo de entrenamiento cercano a los U$D4.6 Millones\n", " - Requirió de varias semanas de entrenamiento\n", " - El corpus reportado es de aproximadamente 500 mil millones (billions) de palabras.\n", " - Varios GPUS para entrenarlo y hardware especializado\n", " - No son modelos que entren en la memoria de una sola GPU." ] }, { "cell_type": "markdown", "id": "16a26206", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "### ¿Y entonces qué puedo hacer?\n", "\n", "- Una ventaja de los LLMs es que el entrenamiento es sobre texto libre, pero se puede **especializar**.\n", "- Uno puede entrenar modelos para diversas tareas especializados en corpus más chico.\n", "- El hecho de que no sea \"desde cero\" ayuda a evitar sobreajuste (overfit) y tiene buen desempeño.\n", "- El procedimiento de **especialización** se conoce como **fine-tuning**." ] }, { "cell_type": "markdown", "id": "649e2ef4", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Cómo personalizar un modelo de Hugging Face?\n", "\n", "- Se inicia por algún modelo pre-entrenado para la tarea específica que uno busca (e.g. clasificación, generación, etc).\n", "- Se toma un corpus especializado (anotado, revisado, etc.) y se entrena utilizando dicho corpus.\n", "- Intentaremos [entrenar que un modelo genere texto](https://github.com/huggingface/notebooks/blob/main/examples/language_modeling.ipynb) con el estilo del **Martín Fierro**.\n", "- Para hacerlo menos pesado, utilizaremos un modelo más chico `DeepESP/gpt2-spanish` como base.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "17f2884d", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "import torch\n", "from transformers import AutoModelForCausalLM, AutoTokenizer\n", "\n", "BASE_MODEL = \"DeepESP/gpt2-spanish\" # We play with a smaller model\n", "tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)\n", "model = AutoModelForCausalLM.from_pretrained(BASE_MODEL)" ] }, { "cell_type": "markdown", "id": "16690597", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Probando el Modelo Base\n", "\n", "- Antes de ajustar el modelo vemos cómo se desenvuelve si le damos como entrada el primer verso del \"Martín Fierro\"." ] }, { "cell_type": "code", "execution_count": null, "id": "322a4a9b", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "torch.manual_seed(42) # To ensure determinism\n", "\n", "input_ids = tokenizer.encode(\"Aquí me pongo a cantar\", return_tensors='pt')\n", "sampling_output = model.generate(input_ids, do_sample=True, max_length=50, top_k=50, top_p=0.95)\n", "output = tokenizer.decode(sampling_output[0], skip_special_tokens=True)\n", "\n", "print(output)" ] }, { "cell_type": "markdown", "id": "ec722e81", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Cargando el Dataset\n", "\n", "- Utilizamos la librería [datasets](https://huggingface.co/docs/datasets/index) de Hugging Face para cargar el corpus.\n", "- En el directorio [`./data`] tenemos dos archivos: [`martin-fierro_train.txt`](./data/martin-fierro_train.txt) y [`martin-fierro_validation.txt`](./data/martin-fierro_validation.txt).\n", " - El archivo de entrenamiento es sobre las 12 primeras partes.\n", " - El archivo de validación es sobre la última parte." ] }, { "cell_type": "code", "execution_count": null, "id": "5a27197e", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from datasets import load_dataset\n", "\n", "datasets = load_dataset(\"text\", data_files={\"train\": './data/martin-fierro_train.txt',\n", " \"validation\": './data/martin-fierro_validation.txt'})\n", "print('\\n'.join(datasets[\"train\"][:9]['text']))" ] }, { "cell_type": "markdown", "id": "9504707f", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Tokenizando los datos\n", "\n", "- La función auxiliar `tokenize` del módulo [`utils`](./utils.py) sirve para tokenizar y codificar el conjunto de datos de manera eficiente mediante el [método `map`](https://huggingface.co/docs/datasets/about_map_batch).\n", "- Lo que devuelve es un nuevo dataset cuyos tokens están convertidos en índices del vocabulario y [máscaras de atención](https://huggingface.co/docs/transformers/glossary#attention-mask)" ] }, { "cell_type": "code", "execution_count": null, "id": "33059c5f", "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from utils import tokenize # local module in the repository\n", "\n", "tokenized_datasets = datasets.map(tokenize(tokenizer), batched=True, num_proc=4, remove_columns=[\"text\"])" ] }, { "cell_type": "markdown", "id": "81d67b22", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Agrupando los textos\n", "\n", "- Para entrenar de manera más eficiente es común utilizar lo que se conoce como **mini-batch gradient descent**.\n", "- La idea es tomar los textos de a bloques de un valor máximo.\n", " - El valor máximo estará limitado por la memoria de la unidad de procesamiento (e.g. GPU).\n", "- Utilizamos la función auxiliar `group_texts` del módulo [`utils`](./utils.py).\n", " - La función además establece las etiquetas que utilizará Hugging Face para entrenar.\n", " - En este caso las etiquetas son las mismas palabras, porque busca predecir la palabra siguiente." ] }, { "cell_type": "code", "execution_count": null, "id": "3100e195", "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from functools import partial\n", "from utils import group_texts # local module in the repository\n", "\n", "lm_datasets = tokenized_datasets.map(\n", " partial(group_texts, block_size=128),\n", " batched=True,\n", " batch_size=1024,\n", " num_proc=4,\n", ")" ] }, { "cell_type": "markdown", "id": "d64a23ec", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Decodificando\n", "\n", "- Podemos ver que los textos pasan a estar agrupados en bloques de 128 tokens.\n", "- Además, vemos que el texto fue reemplazado por números (índices en el vocabulario).\n", "- Por último, si decodificamos estos números, obtenemos el texto original." ] }, { "cell_type": "code", "execution_count": null, "id": "b9d33b7b", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "print(len(lm_datasets['train'][0]['input_ids']))\n", "print(lm_datasets['train'][0]['input_ids'][:10])" ] }, { "cell_type": "code", "execution_count": null, "id": "7dfb316d", "metadata": { "scrolled": false, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "print(tokenizer.decode(lm_datasets[\"train\"][0][\"input_ids\"]))" ] }, { "cell_type": "markdown", "id": "d7e2032f", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Compartir Modelo en Hugging Face\n", "\n", "- Una opción a la hora de entrenar un modelo es subirlo a Hugging Face para compartirlo con la comunidad.\n", "- Para eso, una vez que tengan la cuenta de Hugging Face, y creado el modelo, hay que hacer login mediante un [token](https://huggingface.co/settings/tokens)." ] }, { "cell_type": "code", "execution_count": null, "id": "a8b90ba2", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from huggingface_hub import notebook_login\n", "\n", "notebook_login()" ] }, { "cell_type": "markdown", "id": "a6b775d3", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Entrenamiento\n", "\n", "- Una vez definido el conjunto de datos, pasamos a la parte más intensa computacionalmente, el entrenamiento.\n", "- Podemos decidir guardar el modelo localmente o hacer un backup de cada época del modelo en Hugging Face.\n", "- Definimos las propiedades del entrenamiento mediante [`TrainingArguments`](https://huggingface.co/docs/transformers/v4.28.1/en/main_classes/trainer#transformers.TrainingArguments).\n", "- Definimos el entrenamiento del modelo mediante [`Trainer`](https://huggingface.co/docs/transformers/v4.28.1/en/main_classes/trainer#transformers.Trainer).\n", " - El entrenamiento tardará desde unos segundos hasta varios minutos dependiendo el poder de cómputo." ] }, { "cell_type": "code", "execution_count": null, "id": "d43c5555", "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "from transformers import Trainer, TrainingArguments\n", "\n", "training_args = TrainingArguments(\n", " \"flisol-cba-martinfierro\",\n", " evaluation_strategy=\"epoch\",\n", " num_train_epochs=15,\n", " learning_rate=2e-5,\n", " weight_decay=0.01,\n", " logging_steps=5\n", ")\n", "\n", "trainer = Trainer(\n", " model=model,\n", " args=training_args,\n", " train_dataset=lm_datasets[\"train\"],\n", " eval_dataset=lm_datasets[\"validation\"]\n", ")\n", "\n", "trainer.train()\n", "trainer.push_to_hub() # This pushes the trained model to Hugging Face model repository" ] }, { "cell_type": "markdown", "id": "db2099f4", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Probando el Nuevo Modelo\n", "\n", "- Ahora que tenemos el modelo entrenado, la pregunta es, ¿Cómo se comportará?\n", "- Para ello volvemos a hacer la prueba anterior, quizás esta vez con mejores resultados.\n", " - Para evitar tener que entrenar el modelo nuevamente directamente tomo el [modelo compartido en Hugging Face](https://huggingface.co/crscardellino/flisol-cba-martin-fierro)." ] }, { "cell_type": "code", "execution_count": null, "id": "6a35e80f", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "import torch\n", "from transformers import AutoModelForCausalLM, AutoTokenizer\n", "\n", "BASE_MODEL = \"crscardellino/flisol-cba-martin-fierro\"\n", "tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)\n", "model = AutoModelForCausalLM.from_pretrained(BASE_MODEL)\n", "\n", "torch.manual_seed(42) # To ensure determinism\n", "\n", "input_ids = tokenizer.encode(\"Aquí me pongo a cantar\", return_tensors='pt')\n", "sampling_output = model.generate(input_ids, do_sample=True, max_length=50, top_k=50, top_p=0.95)\n", "output = tokenizer.decode(sampling_output[0], skip_special_tokens=True)\n", "\n", "print(output)" ] }, { "cell_type": "markdown", "id": "f4e33157", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# ¡Muchas Gracias!" ] }, { "cell_type": "markdown", "id": "f04a4e4a", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## ¿Preguntas?\n", "\n", "* Twitter: https://twitter.com/crscardellino\n", "* Mastodon: https://mastodon.social/@crscardellino\n", "* LinkedIn: https://www.linkedin.com/in/crscardellino\n", "* Página Personal: https://crscardellino.ar / https://crscardellino.github.io\n", "* GitHub: https://github.com/crscardellino/\n", "* Código y modelo de la presentación: https://huggingface.co/crscardellino/flisol-cba-martin-fierro/" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.8" }, "rise": { "scroll": true } }, "nbformat": 4, "nbformat_minor": 5 }