es/1_instruction_tuning/notebooks/sft_finetuning_example.ipynb (280 lines of code) (raw):

{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Fine-Tuning Supervisado con SFTTrainer\n", "\n", "Este notebook demuestra cómo realizar fine-tuning del modelo `HuggingFaceTB/SmolLM2-135M` usando el `SFTTrainer` de la librería `trl`. Las celdas del notebook se ejecutan y harán el fine-tuning del modelo. Puedes seleccionar tu nivel de dificultad probando diferentes conjuntos de datos.\n", "\n", "<div style='background-color: lightblue; padding: 10px; border-radius: 5px; margin-bottom: 20px; color:black'>\n", " <h2 style='margin: 0;color:blue'>Ejercicio: Fine-Tuning de SmolLM2 con SFTTrainer</h2>\n", " <p>Toma un conjunto de datos desde el repositorio de Hugging Face y realiza un fine-tuning de un modelo con él.</p>\n", " <p><b>Niveles de dificultad</b></p>\n", " <p>🐢 Usa el conjunto de datos `HuggingFaceTB/smoltalk`</p>\n", " <p>🐕 Prueba el conjunto de datos `bigcode/the-stack-smol` y realiza un fine-tuning de un modelo de generación de código en un subconjunto específico `data/python`.</p>\n", " <p>🦁 Selecciona un conjunto de datos que esté relacionado con un caso de uso del mundo real que te interese.</p>\n", "</div>" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Instalar los requisitos en Google Colab\n", "# !pip install transformers datasets trl huggingface_hub\n", "\n", "\n", "# Autenticación en Hugging Face\n", "from huggingface_hub import login\n", "\n", "login()\n", "\n", "# Para mayor comodidad, puedes crear una variable de entorno con tu token de Hugging Face como HF_TOKEN en tu archivo .env" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Importa las bibliotecas necesarias\n", "from transformers import AutoModelForCausalLM, AutoTokenizer\n", "from datasets import load_dataset\n", "from trl import SFTConfig, SFTTrainer, setup_chat_format\n", "import torch\n", "\n", "# Establece dinámicamente el dispositivo de procesamiento.\n", "device = (\n", " \"cuda\"\n", " if torch.cuda.is_available()\n", " else \"mps\" if torch.backends.mps.is_available() else \"cpu\"\n", ")\n", "\n", "# Carga el modelo y el tokenizador\n", "model_name = \"HuggingFaceTB/SmolLM2-135M\"\n", "model = AutoModelForCausalLM.from_pretrained(\n", " pretrained_model_name_or_path=model_name\n", ").to(device)\n", "tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=model_name)\n", "\n", "# Configura el formato de chat\n", "model, tokenizer = setup_chat_format(model=model, tokenizer=tokenizer)\n", "\n", "# Establece nuestro nombre para guardar y/o subir el modelo finetuneado\n", "finetune_name = \"SmolLM2-FT-MyDataset\"\n", "finetune_tags = [\"smol-course\", \"module_1\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Generar con el modelo base\n", "\n", "Aquí probaremos el modelo base, que no tiene una plantilla de chat." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Probemos el modelo base antes de entrenar\n", "prompt = \"Write a haiku about programming\"\n", "\n", "# Formatea con la plantilla\n", "messages = [{\"role\": \"user\", \"content\": prompt}]\n", "formatted_prompt = tokenizer.apply_chat_template(messages, tokenize=False)\n", "\n", "# Genera la respuesta\n", "inputs = tokenizer(formatted_prompt, return_tensors=\"pt\").to(device)\n", "outputs = model.generate(**inputs, max_new_tokens=100)\n", "print(\"Before training:\")\n", "print(tokenizer.decode(outputs[0], skip_special_tokens=True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Preparación del Conjunto de Datos\n", "\n", "Cargaremos un conjunto de datos de ejemplo y lo formatearemos para el entrenamiento. El conjunto de datos debe estar estructurado con pares de entrada-salida, donde cada entrada es un prompt y la salida es la respuesta esperada del modelo.\n", "\n", "**TRL formateará los mensajes de entrada según las plantillas de chat del modelo.** Estos deben representarse como una lista de diccionarios con las claves: `role` y `content`.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Carga un conjunto de datos de ejemplo\n", "from datasets import load_dataset\n", "\n", "# TODO: define tu conjunto de datos y configuración usando los parámetros de ruta y nombre\n", "ds = load_dataset(path=\"HuggingFaceTB/smoltalk\", name=\"everyday-conversations\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# TODO: 🦁 Si tu conjunto de datos no está en un formato que TRL pueda convertir a la plantilla de chat, necesitarás procesarlo. Consulta el [módulo](../chat_templates.md)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Configuración del SFTTrainer\n", "\n", "El `SFTTrainer` se configura con varios parámetros que controlan el proceso de entrenamiento. Estos incluyen el número de pasos de entrenamiento, el tamaño del lote, la tasa de aprendizaje y la estrategia de evaluación. Ajusta estos parámetros según tus requisitos específicos y recursos computacionales." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Configura el SFTTrainer\n", "sft_config = SFTConfig(\n", " output_dir=\"./sft_output\", # Directorio de salida para los resultados del entrenamiento\n", " max_steps=1000, # Ajusta según el tamaño del conjunto de datos y la duración de entrenamiento deseada\n", " per_device_train_batch_size=4, # Ajusta según la capacidad de la memoria de tu GPU\n", " learning_rate=5e-5, # Punto de partida común para el fine-tuning\n", " logging_steps=10, # Frecuencia de registro de métricas de entrenamiento\n", " save_steps=100, # Frecuencia de guardado de puntos de control del modelo\n", " evaluation_strategy=\"steps\", # Evalua el modelo en intervalos regulares\n", " eval_steps=50, # Frecuencia de evaluación\n", " use_mps_device=(\n", " True if device == \"mps\" else False\n", " ), # Usa MPS para entrenamiento con precisión mixta\n", " hub_model_id=finetune_name, # Asigna un nombre único a tu modelo\n", ")\n", "\n", "# Inicializa el SFTTrainer\n", "trainer = SFTTrainer(\n", " model=model,\n", " args=sft_config,\n", " train_dataset=ds[\"train\"],\n", " tokenizer=tokenizer,\n", " eval_dataset=ds[\"test\"],\n", ")\n", "\n", "# TODO: 🦁 🐕 ajusta los parámetros del SFTTrainer a tu conjunto de datos elegido. Por ejemplo, si usas el conjunto de datos `bigcode/the-stack-smol`, necesitarás elegir la columna `content`.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Entrenamiento del Modelo\n", "\n", "Con el entrenador configurado, ahora podemos proceder a entrenar el modelo. El proceso de entrenamiento implicará iterar sobre el conjunto de datos, calcular la pérdida y actualizar los parámetros del modelo para minimizar esta pérdida." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Entrena el modelo\n", "trainer.train()\n", "\n", "# Guarda el modelo\n", "trainer.save_model(f\"./{finetune_name}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "trainer.push_to_hub(tags=finetune_tags)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<div style='background-color: lightblue; padding: 10px; border-radius: 5px; margin-bottom: 20px; color:black'>\n", " <h2 style='margin: 0;color:blue'>Ejercicio adicional: Generar con el modelo ajustado</h2>\n", " <p>🐕 Utiliza el modelo ajustado para generar una respuesta, de la misma forma que con el ejemplo base.</p>\n", "</div>\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Prueba el modelo ajustado con el mismo mensaje\n", "\n", "# Probemos el modelo base antes del entrenamiento\n", "prompt = \"Escribe un haiku sobre programación\"\n", "\n", "# Formatea con la plantilla\n", "messages = [{\"role\": \"user\", \"content\": prompt}]\n", "formatted_prompt = tokenizer.apply_chat_template(messages, tokenize=False)\n", "\n", "# Genera respuesta\n", "inputs = tokenizer(formatted_prompt, return_tensors=\"pt\").to(device)\n", "\n", "# TODO: usa el modelo ajustado para generar una respuesta, igual que en el ejemplo base." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 💐 ¡Has terminado!\n", "\n", "Este notebook proporcionó una guía paso a paso para realizar fine-tuning del modelo `HuggingFaceTB/SmolLM2-135M` utilizando el `SFTTrainer`. Siguiendo estos pasos, puedes adaptar el modelo para realizar tareas específicas de manera más efectiva. Si deseas continuar trabajando en este curso, aquí tienes algunas sugerencias que podrías intentar:\n", "\n", "- Intenta este notebook en un nivel de dificultad más alto.\n", "- Revisa el PR de un compañero.\n", "- Mejora el material del curso a través de un Issue o PR.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] } ], "metadata": { "kernelspec": { "display_name": "py310", "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.15" } }, "nbformat": 4, "nbformat_minor": 2 }