Costará millones de dólares y meses de tiempo de computación para entrenar un gran modelo de lenguaje desde el principio.Probablemente nunca tendrá que hacerlo.Fine-tuning le permite adaptar modelos de lenguaje pre-entrenados a sus necesidades en horas o días, no meses, con una fracción de los recursos. Este tutorial te llevará : aprenderás las cuatro técnicas básicas de ajuste perfecto, codificarás un tubo de capacitación completo en Python y aprenderás las técnicas que separan los modelos listos para la producción de los experimentos costosos. from theory to practice ¿Qué es LLM Fine-Tuning? Fine-tuning trabaja un modelo de lenguaje existente en sus datos para mejorar su Los modelos pre-entrenados son generales poderosos, pero los exponen a puede convertirlos en especialistas para su caso de uso. performance on specific tasks focused examples En lugar de construir un modelo desde cero (que requiere una computación y datos masivos), está dando a un modelo ya capaz un curso de colisión en lo que le importa, ya sea diagnóstico médico, automatización del soporte al cliente, análisis de sentimientos o cualquier otra tarea particular. ¿Cómo funciona el LLM Fine-Tuning? Fine-tuning continúa el proceso de capacitación en modelos de idiomas pre-entrenados utilizando su conjunto de datos específico. El modelo procesa sus ejemplos proporcionados, compara sus propios resultados con los resultados esperados, y adaptarse y minimizar las pérdidas. updates internal weights Este método puede variar en función de su , de , y Algunos proyectos requieren un ajuste completo, donde se actualizan todos los parámetros del modelo, mientras que otros funcionan mejor con métodos eficientes de parámetros como Esto sólo modifica un pequeño subconjunto. goals available data computational resources Loira LLM Métodos Fine-Tuning Supervisado Fine-Tuning SFT enseña al modelo a aprender los patrones de los pares de preguntas-respuestas correctos y ajusta los pesos del modelo para coincidir con esas respuestas exactamente. Utilice esto cuando desee resultados consistentes, como hacer que el modelo siempre responda en formato JSON, siguiendo su script de servicio al cliente o escribiendo correos electrónicos en el tono de su empresa. (Prompt, Ideal Response) Fine-Tuning sin supervisión Alimenta el modelo con toneladas de texto crudo (no se necesitan preguntas ni datos etiquetados) para que aprenda el vocabulario y los patrones de un dominio en particular. Si bien esto es técnicamente un proceso de pre-entrenamiento conocido como Pre-entrenamiento continuo (CPT), esto se hace generalmente después de la fase inicial de pre-entrenamiento. Optimización de preferencias DPO enseña al modelo a preferir mejores respuestas mostrando ejemplos de buenas vs. malas respuestas a la misma pregunta y ajustándola para favorecer las buenas. Utilice DPO después del entrenamiento básico para corregir comportamientos molestos como detener al modelo de hacer las cosas, ser demasiado verbal o dar respuestas inseguras. (Prompt, Good Response, Bad Response) Reforzamiento Fine-Tuning En RLHF, primero entrenas un modelo de recompensa en prompts con múltiples respuestas clasificadas por humanos, enseñándole a predecir qué respuestas prefiere la gente. Luego, utilizas el aprendizaje de reforzamiento para optimizar y ajustar un modelo que genera respuestas, que el modelo de recompensa juzga. Esto ayuda al modelo a aprender a lo largo del tiempo para producir resultados de mayor puntuación. Este proceso requiere conjuntos de datos en este formato: Es mejor para tareas donde juzgar la calidad es más fácil que crear ejemplos perfectos, como diagnósticos médicos, investigación legal y otro razonamiento complejo específico del dominio. (Prompt, [Response A, Response B, ...], [Rankings]) Paso a paso Fine-Tuning LLMs Tutorial Te guiaremos a través de cada paso del ajuste perfecto de un pequeño modelo pre-entrenado para resolver problemas de matemáticas basados en palabras, algo con lo que lucha fuera de la caja. El enfoque : enseñando una terminología especializada de un modelo, mejorando el rendimiento del modelo en tareas específicas o adaptándolo a su dominio. works for virtually any use case of fine-tuning LLMs Precondiciones Instale algunos paquetes de Python que usaremos a lo largo de este tutorial.En una nueva carpeta de proyecto, crea y activa un entorno virtual de Python, y luego instala estas bibliotecas usando o su gestor de paquetes preferido: pip pip install requests datasets transformers 'transformers[torch]' Obtener y cargar el conjunto de datos El proceso de ajuste perfecto comienza con la elección del conjunto de datos, que es probablemente la decisión más importante. . reflect the task you want your model to perform Las tareas simples como el análisis de sentimientos requieren pares básicos de entrada y salida. Las tareas complejas como el seguimiento de instrucciones o la respuesta a preguntas requieren conjuntos de datos más ricos con contexto, ejemplos y formatos variados. El punto de partida más sencillo es el biblioteca de conjuntos de datos, que aloja miles de conjuntos de datos de código abierto para diferentes dominios y tareas. ¿Necesitas algo específico y de alta calidad? o datos disponibles públicamente. Hugging Face Purchase specialized datasets build your own by Escorpión Escorpión Por ejemplo, si desea construir un modelo de análisis de sentimientos para revisiones de productos de Amazon, es posible que desee recopilar datos de revisiones reales usando una herramienta de rascado web. : Web Scraper con API import json import requests # Web Scraper API parameters. payload = { "source": "amazon_product", # Query is the ASIN of a product. "query": "B0DZDBWM5B", "parse": True, } # Send a request to the API and get the response. response = requests.post( "https://realtime.oxylabs.io/v1/queries", # Visit https://dashboard.oxylabs.io to claim FREE API tokens. auth=("USERNAME", "PASSWORD"), json=payload, ) print(response.text) # Extract the reviews from the response. reviews = response.json()["results"][0]["content"]["reviews"] print(f"Found {len(reviews)} reviews") # Save the reviews to a JSON file. with open("reviews.json", "w") as f: json.dump(reviews, f, indent=2) For this tutorial, let’s keep it simple without building a custom data collection pipeline. Since we're teaching the base model to solve word-based math problems, we can use the openai/gsm8k dataset. It’s a collection of grade-school math problems with step-by-step solutions. Load it in your Python file: from datasets import load_dataset dataset = load_dataset("openai/gsm8k", "main") print(dataset["train"][0]) Tokeniza los datos para el procesamiento Los modelos no entienden el texto directamente; trabajan con La tokenización convierte tu texto en tokens (representaciones numéricas) que el modelo puede procesar. Cada modelo tiene su propio tokenizador entrenado junto a él, así que use el que coincida con tu modelo base: numbers from transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B") tokenizer.pad_token = tokenizer.eos_token Cómo tokenizamos nuestras formas de datos lo que el modelo aprende. Para los problemas matemáticos, queremos ajustar el modelo para aprender cómo Aquí está el truco: tokenize preguntas y respuestas por separado, luego use una técnica de mascarado. Respuesta Pregunta Token para El modelo sólo aprende de las respuestas, haciendo que la formación sea más enfocada y eficiente. -100 def tokenize_function(examples): input_ids_list = [] labels_list = [] for question, answer in zip(examples["question"], examples["answer"]): # Tokenize question and answer separately question_tokens = tokenizer(question, add_special_tokens=False)["input_ids"] answer_tokens = tokenizer(answer, add_special_tokens=False)["input_ids"] + [tokenizer.eos_token_id] # Combine question + answer for input input_ids = question_tokens + answer_tokens # Mask question tokens with -100 so loss is only computed on the answer labels = [-100] * len(question_tokens) + answer_tokens input_ids_list.append(input_ids) labels_list.append(labels) return { "input_ids": input_ids_list, "labels": labels_list, } Aplique esta función de tokenización tanto a los conjuntos de datos de entrenamiento como de pruebas. filtramos ejemplos más largos que 512 tokens para mantener el uso de la memoria gestionable y asegurar que el modelo procesa la información completa sin truncado. train_dataset = dataset["train"].map( tokenize_function, batched=True, remove_columns=dataset["train"].column_names, ).filter(lambda x: len(x["input_ids"]) <= 512) .shuffle(seed=42) eval_dataset = dataset["test"].map( tokenize_function, batched=True, remove_columns=dataset["test"].column_names, ).filter(lambda x: len(x["input_ids"]) <= 512) print(f"Samples: {len(dataset['train'])} → {len(train_dataset)} (after filtering)") print(f"Samples: {len(dataset['test'])} → {len(eval_dataset)} (after filtering)") Optional: ¿Quieres probar todo el tubo rápidamente antes de comprometerse a una carrera de entrenamiento completa? Puedes entrenar el modelo en un subconjunto de datos. Así que, en lugar de usar el conjunto de datos completo de 8.5K, puedes minimizarlo a 3K en total, haciendo que el proceso sea mucho más rápido: train_dataset = train_dataset.select(range(2000)) eval_dataset = eval_dataset.select(range(1000)) Los conjuntos de datos más pequeños aumentan el riesgo de overfitting, donde el modelo memoriza datos de entrenamiento en lugar de aprender patrones generales. Para la producción, busque al menos muestras de entrenamiento 5K+ y ajuste cuidadosamente sus hiperparámetros. Keep in mind: Iniciación al modelo de base A continuación, carga el modelo de base pre-entrenado para ajustarlo mejorando sus habilidades de resolución de problemas matemáticos: from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B") model.config.pad_token_id = tokenizer.pad_token_id Fine-Tune utilizando el método del entrenador Aquí es donde ocurre la magia. TrainingArguments controla cómo su modelo aprende (piensa en ello como la receta que determina la calidad de su resultado final).Estos ajustes y hiperparámetros pueden hacer o romper su ajuste, así que experimente con diferentes valores para encontrar lo que funciona para su caso de uso. Key parameters explained: · Más épocas equivalen a más oportunidades de aprendizaje, pero demasiados causan sobrecarga. Epochs: · Afecta el uso de la memoria y la velocidad de entrenamiento. Ajuste estos en función de su hardware. Batch size: · Controla la rapidez con la que el modelo se ajusta. demasiado alto y puede faltar la solución óptima, demasiado bajo y el entrenamiento dura para siempre. Learning rate: · Puede ayudar a prevenir el sobreajuste disuadiendo al modelo de inclinarse demasiado sobre cualquier patrón único.Si el desgaste de peso es demasiado grande, puede conducir a la subajuste al impedir que el modelo aprenda los patrones necesarios. Weight decay: La configuración óptima a continuación se especializa en el entrenamiento de la CPU (suprimir use_cpu=True si tienes una GPU): from transformers import TrainingArguments, Trainer, DataCollatorForSeq2Seq training_args = TrainingArguments( output_dir="./qwen-math", # Custom output directory for the fine-tuned model use_cpu=True, # Set to False or remove to use GPU if available # Training duration num_train_epochs=2, # 3 may improve reasoning at the expense of overfitting # Batch size and memory management per_device_train_batch_size=5, # Adjust depending on your PC capacity per_device_eval_batch_size=5, # Adjust depending on your PC capacity gradient_accumulation_steps=4, # Decreases memory usage, adjust if needed # Learning rate and regularization learning_rate=2e-5, # Affects learning speed and overfitting weight_decay=0.01, # Prevents overfitting by penalizing large weights max_grad_norm=1.0, # Prevents exploding gradients warmup_ratio=0.1, # Gradually increases learning rate to stabilize training lr_scheduler_type="cosine", # Smoother decay than linear # Evaluation and checkpointing eval_strategy="steps", eval_steps=100, save_strategy="steps", save_steps=100, save_total_limit=3, # Keep only the best 3 checkpoints load_best_model_at_end=True, # Load the best checkpoint at the end of training metric_for_best_model="eval_loss", greater_is_better=False, # Logging logging_steps=25, logging_first_step=True, ) # Data collator handles padding and batching data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=model) # Initialize trainer trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, data_collator=data_collator, ) # Fine-tune the base model print("Fine-tuning started...") trainer.train() Once training completes, save your fine-tuned model: trainer.save_model("./qwen-math/final") tokenizer.save_pretrained("./qwen-math/final") Evaluar el modelo Después del ajuste, mide lo bien que su modelo realiza usando dos métricas comunes: · Mide cuán lejos están las predicciones del modelo de los resultados de meta, donde los valores más bajos indican un mejor rendimiento. Loss: · Muestra la misma información en una escala más intuitiva, donde los valores más bajos significan que el modelo es más confiado en sus predicciones. Perplexity (the exponential of loss): Para los entornos de producción, considere agregar métricas como o para medir la aproximación de las respuestas generadas a las respuestas de referencia. BLEU ROUGE import math eval_results = trainer.evaluate() print(f"Final Evaluation Loss: {eval_results['eval_loss']:.4f}") print(f"Perplexity: {math.exp(eval_results['eval_loss']):.2f}") También puede incluir otras métricas como F1, que mide cuán bueno es su modelo en capturar lo que importa mientras se mantiene exacto. es un buen punto de partida para aprender las esencias de usar la biblioteca de transformadores. Lecturas de cara a cara Ejemplo de código de ajuste perfecto Después de estos cinco pasos, debe tener el siguiente código combinado en un solo archivo de Python: import math from datasets import load_dataset from transformers import ( AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer, DataCollatorForSeq2Seq, ) dataset = load_dataset("openai/gsm8k", "main") tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B") tokenizer.pad_token = tokenizer.eos_token # Tokenization function adjusted for the specific dataset format def tokenize_function(examples): input_ids_list = [] labels_list = [] for question, answer in zip(examples["question"], examples["answer"]): question_tokens = tokenizer(question, add_special_tokens=False)["input_ids"] answer_tokens = tokenizer(answer, add_special_tokens=False)["input_ids"] + [tokenizer.eos_token_id] input_ids = question_tokens + answer_tokens labels = [-100] * len(question_tokens) + answer_tokens input_ids_list.append(input_ids) labels_list.append(labels) return { "input_ids": input_ids_list, "labels": labels_list, } # Tokenize the data train_dataset = dataset["train"].map( tokenize_function, batched=True, remove_columns=dataset["train"].column_names, ).filter(lambda x: len(x["input_ids"]) <= 512) .shuffle(seed=42) eval_dataset = dataset["test"].map( tokenize_function, batched=True, remove_columns=dataset["test"].column_names, ).filter(lambda x: len(x["input_ids"]) <= 512) print(f"Samples: {len(dataset['train'])} → {len(train_dataset)} (after filtering)") print(f"Samples: {len(dataset['test'])} → {len(eval_dataset)} (after filtering)") # Optional: Use a smaller subset for faster testing # train_dataset = train_dataset.select(range(2000)) # eval_dataset = eval_dataset.select(range(1000)) model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B") model.config.pad_token_id = tokenizer.pad_token_id # Configuration settings and hyperparameters for fine-tuning training_args = TrainingArguments( output_dir="./qwen-math", use_cpu=True, # Training duration num_train_epochs=2, # Batch size and memory management per_device_train_batch_size=5, per_device_eval_batch_size=5, gradient_accumulation_steps=4, # Learning rate and regularization learning_rate=2e-5, weight_decay=0.01, max_grad_norm=1.0, warmup_ratio=0.1, lr_scheduler_type="cosine", # Evaluation and checkpointing eval_strategy="steps", eval_steps=100, save_strategy="steps", save_steps=100, save_total_limit=3, load_best_model_at_end=True, metric_for_best_model="eval_loss", greater_is_better=False, # Logging logging_steps=25, logging_first_step=True, ) data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=model) trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, data_collator=data_collator, ) # Fine-tune the base model print("Fine-tuning started...") trainer.train() # Save the final model trainer.save_model("./qwen-math/final") tokenizer.save_pretrained("./qwen-math/final") # Evaluate after fine-tuning eval_results = trainer.evaluate() print(f"Final Evaluation Loss: {eval_results['eval_loss']:.4f}") print(f"Perplexity: {math.exp(eval_results['eval_loss']):.2f}") Antes de ejecutar, tome un momento para ajustar la configuración de su entrenador y los hiperparámetros en función de lo que su máquina realmente puede manejar. Para darle una referencia en el mundo real, aquí está lo que funcionó sin problemas para nosotros en un MacBook Air con el chip M4 y 16 GB de RAM. · : 7 Batch size for training · 7 Batch size for eval: · 5 Gradient accumulation: A medida que vuestro modelo trabaja, mantenga un ojo en el Si aumenta mientras la pérdida de entrenamiento disminuye, el modelo está sobrecogiendo. En ese caso, ajuste las épocas, disminuya la tasa de aprendizaje, modifique la pérdida de peso y otros hiperparámetros. En el ejemplo siguiente, vemos resultados saludables con pérdida de eval disminuyendo de Dos Una perplejidad final de . evaluation loss 0.496 0.469 1.60 Prueba del modelo Fine-Tuned Ahora, por el momento de la verdad, ¿fue nuestro ajuste realmente exitoso?Puedes probar manualmente el modelo ajustado con este código de Python: from transformers import pipeline generator = pipeline( "text-generation", # Use `Qwen/Qwen2.5-0.5B` for testing the base model model="./qwen-math/final" ) output = generator( "James has 5 apples. He buys 3 times as many. Then gives half away. How many does he have?", return_full_text=False ) print(output[0]["generated_text"]) En esta comparación, se puede ver cómo los modelos antes y después responden a la misma pregunta (la respuesta correcta es 10): Con el muestreo habilitado, ambos modelos ocasionalmente lo hacen bien o mal debido a la aleatoriedad. La función revela su verdadera confianza: el modelo siempre elige su respuesta de mayor probabilidad. Confianza en la salida (en el ), mientras que el Confianza en la salida (en el Eso es el fine-tuning en el trabajo. do_sample=False in the generator() base model -2 equivocados fine-tuned model 10 correcta Fine-Tuning de las mejores prácticas Modelo Selección · Los modelos específicos de dominio y las ventanas de contexto adecuadas te ahorran de luchar contra el conocimiento existente del modelo. Choose the right base model: · Los modelos de codificadores únicos (como BERT) excelen en tareas de clasificación, los modelos de decodificadores únicos (como GPT) en la generación de texto y los modelos de codificadores decodificadores (como T5) en tareas de transformación como la traducción o la resumida. Understand the model architecture: · Si su modelo de base fue entrenado con plantillas de prompt específicas, use el mismo formato en el ajuste. Match your model's input format: Preparación de datos · Ejemplos limpios y precisos vencen conjuntos de datos masivos y ruidosos cada vez. Prioritize data quality over quantity: · Nunca dejes que tu modelo vea los datos de evaluación durante el entrenamiento.Esto te permite capturar la overfitting antes de que arruine tu modelo. Split training and evaluation samples: · Las métricas automatizadas como la perplejidad no te dicen si el modelo sigue realmente las instrucciones o sólo predice las palabras estadísticamente. Establish a "golden set" for evaluation: Estrategia de entrenamiento · Estás haciendo ajustes menores, no enseñándolo desde cero, por lo que las tasas agresivas pueden borrar lo que aprendió durante el entrenamiento previo. Start with a lower learning rate: · Entrena sólo el 1% de los parámetros para obtener un rendimiento del 90% + mientras utiliza menos memoria y tiempo. Use parameter-efficient fine-tuning (LoRA/PEFT): · Todos los elementos de la tabla ( etc.) produce modelos que razonan significativamente mejor, no sólo imitan el estilo. Target all linear layers in LoRA: q_proj, k_proj, v_proj, o_proj, · El ruido aleatorio en las incorporaciones actúa como regularización, lo que puede prevenir la memorización y aumentar la calidad de la conversación en 35 puntos porcentuales. Use NEFTune ( ): Siguiente Entrada siguiente: Fine-tuning Siguiente Entrada siguiente: Fine-tuning · SFT enseña cómo hablar; DPO enseña lo que es bueno aprendiendo de los pares de preferencias. After SFT, Run DPO: ¿Cuáles Son Las Limitaciones De LLM Fine-Tuning? · El ajuste fino sobreescribe los patrones neuronales existentes, lo que puede borrar valiosos conocimientos generales aprendidos durante el modelo de pre-entrenamiento. Aprendizaje de tareas múltiples, donde se capacita en su tarea especializada junto con ejemplos generales, puede ayudar a preservar capacidades más amplias. Catastrophic forgetting: · El modelo puede memorizar sus ejemplos de entrenamiento en lugar de patrones de aprendizaje, lo que lo hace fallar en entradas ligeramente diferentes. Overfitting on small datasets: · El ajuste preciso de miles de millones de parámetros requiere GPUs caras, memoria significativa y horas a días o semanas de tiempo de entrenamiento. High computational cost: · Los modelos pre-entrenados ya llevan prejuicios de sus datos de entrenamiento, y el ajuste fino puede intensificar estos prejuicios si su conjunto de datos no está cuidadosamente curado. Bias amplification: · Los conocimientos nuevos y externos pueden requerir un entrenamiento completo del modelo o la implementación de la generación aumentada de recuperación (RAG), mientras que el ajuste repetido a menudo degrada el rendimiento. Manual knowledge update: Conclusión Fine-tuning funciona, pero sólo si sus datos son limpios y sus hiperparámetros se conectan. Combina con la ingeniería rápida para obtener los mejores resultados, donde el ajuste fino maneja la especialización de tareas mientras que la ingeniería rápida guía el comportamiento del modelo en el tiempo de inferencia. Siga tomando un modelo de Hugging Face que se ajuste a su caso de uso para ajustes finos específicos de dominio, rascar o construir un conjunto de datos de calidad para su tarea, y ejecutar su primera sesión de ajustes finos en un subconjunto pequeño. Una vez que vea resultados prometedores, escala y experimente con LoRA, DPO o NEFTune para comprimir un mejor rendimiento.