Estrategias para Fine-Tuning

Estrategias para Fine-Tuning: Cómo evitar el sobreajuste en modelos AI

02/04/2025

El Fine-tuning se ha convertido en una de las estrategias más efectivas en el aprendizaje profundo para optimizar modelos preentrenados y adaptarlos a tareas específicas. En lugar de entrenar redes neuronales desde cero, esta técnica aprovecha modelos ya entrenados en grandes conjuntos de datos y los ajusta con información más específica, reduciendo el tiempo de entrenamiento y la necesidad de grandes volúmenes de datos.

Sin embargo, el sobreajuste sigue siendo un desafío importante. Si un modelo se adapta demasiado a los datos de entrenamiento, su capacidad de generalización en datos nuevos puede verse comprometida. Para evitar eso, se pueden aplicar técnicas como la regularización, el aumento de datos, el Early Stopping y la validación cruzada, entre otras.

Evitar el sobreajuste en Fine-Tuning 

Uno de los principales desafíos del Fine-Tuning es el sobreajuste. Si el modelo se adapta demasiado a los datos de entrenamiento, su rendimiento en datos nuevos puede verse afectado. Para evitarlo, se pueden aplicar varias estrategias clave.  

Regularización y Dropout 

La regularización evita que el modelo memorice los datos en lugar de aprender patrones generales. Algunas técnicas efectivas son:  

  • L2 Regularization (Weight Decay): Penaliza pesos grandes para mejorar la generalización.  

  • Dropout: Desactiva aleatoriamente ciertas conexiones para evitar la dependencia excesiva en neuronas específicas. 

from tensorflow.keras.models import Sequential 
from tensorflow.keras.layers import Dense 
from tensorflow.keras.regularizers import l2 
 
# Modelo con regularización L2 
modelo = Sequential([ 
    Dense(128, activation='relu', kernel_regularizer=l2(0.01)), 
    Dense(64, activation='relu', kernel_regularizer=l2(0.01)), 
    Dense(10, activation='softmax') 
]) 
import torch.nn as nn 
import torch.optim as optim 
 
# Definir modelo con regularización L2 
modelo = nn.Sequential( 
    nn.Linear(784, 128), 
    nn.ReLU(), 
    nn.Linear(128, 10) 
) 
 
# Optimizador con weight decay (L2 regularization) 
optimizer = optim.Adam(modelo.parameters(), lr=0.001, weight_decay=0.01) 
  

Data Augmentation 

Aumentar la diversidad del conjunto de datos ayuda a mejorar la capacidad de generalización del modelo.  

  • Imágenes: Transformaciones como rotaciones, volteos y cambios de brillo.  

  • Texto: Sinónimos, traducciones inversas o eliminación de palabras irrelevantes.  

  • Audio: Cambios en el tono, velocidad o ruido de fondo. 

from tensorflow.keras.preprocessing.image import ImageDataGenerator 
 
# Definir transformaciones de Data Augmentation 
datagen = ImageDataGenerator( 
    rotation_range=20, 
    width_shift_range=0.2, 
    height_shift_range=0.2, 
    horizontal_flip=True 
) 
from torchvision import transforms 
 
# Transformaciones de Data Augmentation 
transformaciones = transforms.Compose([ 
    transforms.RandomRotation(20), 
    transforms.RandomHorizontalFlip(), 
    transforms.ToTensor() 
]) 
  

Early Stopping 

El Early Stopping detiene el entrenamiento cuando la pérdida en validación deja de mejorar, evitando sobreajuste.  

from tensorflow.keras.callbacks import EarlyStopping 
 
# Definir Early Stopping 
early_stopping = EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True) 
class EarlyStopping: 
    def __init__(self, patience=5): 
        self.patience = patience 
        self.best_loss = float('inf') 
        self.counter = 0 
 
    def check_early_stop(self, val_loss): 
        if val_loss < self.best_loss: 
            self.best_loss = val_loss 
            self.counter = 0 
        else: 
            self.counter += 1 
            if self.counter >= self.patience: 
                return True 
        return False 
  

Validación cruzada 

En lugar de depender de un único conjunto de validación, la validación cruzada divide los datos en múltiples subconjuntos para evaluar el modelo en distintos escenarios.  

from sklearn.model_selection import cross_val_score 
from sklearn.ensemble import RandomForestClassifier 
from sklearn.datasets import load_iris 
 
# Cargar datos 
datos = load_iris() 
X, y = datos.data, datos.target 
 
# Definir modelo 
modelo = RandomForestClassifier() 
 
# Aplicar validación cruzada 
scores = cross_val_score(modelo, X, y, cv=5) 
print("Precisión media:", scores.mean()) 
  

Aplicando estas estrategias, podemos reducir el riesgo de sobreajuste y mejorar el rendimiento del modelo en datos nuevos.  

Evaluación del modelo después del Fine-Tuning 

Una vez ajustado un modelo con Fine-Tuning, es crucial evaluar su rendimiento para asegurarnos de que ha mejorado sin perder capacidad de generalización.  

Uso de un conjunto de prueba separado 

Para medir el rendimiento real del modelo, es fundamental evaluarlo con un conjunto de prueba que no haya sido utilizado en el entrenamiento ni en la validación.  

import tensorflow as tf 
from tensorflow.keras.applications import MobileNetV2 
 
# Cargar el modelo preentrenado sin la capa de clasificación 
modelo_base = MobileNetV2(weights="imagenet", include_top=False, input_shape=(224, 224, 3)) 
 
# Ver la estructura del modelo 
modelo_base.summary() 
import torch 
import torchvision.models as models 
 
# Cargar un modelo preentrenado 
modelo_base = models.resnet50(pretrained=True) 
 
# Ver la estructura del modelo 
print(modelo_base) 
  

Métricas clave para evaluar modelos ajustados 

Más allá de la precisión, otras métricas ofrecen una evaluación más completa del modelo:  

  • Matriz de confusión: Analiza los errores del modelo en cada clase.  

  • F1-Score: Equilibra precisión y recall, útil en datasets desbalanceados.  

  • Curva ROC-AUC: Evalúa la capacidad del modelo para distinguir entre clases. 

# Congelar todas las capas del modelo base 
for capa in modelo_base.layers: 
    capa.trainable = False 
# Congelar las capas del modelo 
for param in modelo_base.parameters(): 
    param.requires_grad = False 
from tensorflow.keras import layers, models 
 
# Crear un nuevo modelo con las capas personalizadas 
modelo = models.Sequential([ 
    modelo_base, 
    layers.GlobalAveragePooling2D(), 
    layers.Dense(128, activation="relu"), 
    layers.Dropout(0.5), 
    layers.Dense(10, activation="softmax")  # 10 clases de salida 
]) 
 
# Ver la estructura del nuevo modelo 
modelo.summary() 
  

Comparación con el modelo base 

Para confirmar que el Fine-Tuning ha sido efectivo, es recomendable comparar el nuevo modelo con el modelo preentrenado original. Si el ajuste no mejora los resultados o incluso los empeora, podría haber sobreajuste o una mala configuración de hiperparámetros 

Con estas estrategias, podemos evaluar con precisión el impacto del Fine-Tuning y asegurarnos de que el modelo generaliza correctamente.  

Entrenamiento del modelo con Fine-Tuning 

Una vez que el modelo ha sido modificado con nuevas capas, el siguiente paso es el entrenamiento. Para evitar el sobreajuste y mejorar la eficiencia del ajuste fino, es importante seguir algunas estrategias clave: 

  • Entrenar en dos fases: Primero, entrenar solo las nuevas capas, manteniendo congelado el modelo base. Luego, descongelar progresivamente capas profundas y entrenar con una tasa de aprendizaje baja. 

  • Usar técnicas de regularización: Métodos como el Dropout o la Regularización L2 ayudan a mejorar la generalización del modelo. 

  • Aplicar un learning rate diferenciado: Usar un learning rate alto para las capas nuevas y uno bajo para las capas preentrenadas evita perder información importante. 

Entrenamiento en TensorFlow 

A continuación, se muestra cómo entrenar un modelo ajustado en TensorFlow: 

from tensorflow.keras.optimizers import Adam 
from tensorflow.keras.callbacks import EarlyStopping 
 
# Descongelar parcialmente el modelo base para entrenar con Fine-Tuning 
modelo_base.trainable = True 
for capa in modelo_base.layers[:-20]:  # Mantener congeladas las primeras capas 
    capa.trainable = False 
 
# Compilar el modelo con una tasa de aprendizaje diferenciada 
modelo.compile(optimizer=Adam(learning_rate=1e-4), loss="categorical_crossentropy", metrics=["accuracy"]) 
 
# Aplicar Early Stopping para evitar el sobreajuste 
early_stopping = EarlyStopping(monitor="val_loss", patience=5, restore_best_weights=True) 
 
# Entrenar el modelo 
modelo.fit(X_train, y_train, epochs=20, validation_data=(X_val, y_val), callbacks=[early_stopping]) 
  

Entrenamiento en PyTorch 

En PyTorch, el entrenamiento sigue una estructura similar: 

import torch.optim as optim 
from torch.utils.data import DataLoader 
 
# Definir diferentes tasas de aprendizaje 
optimizador = optim.Adam([ 
    {"params": modelo_base.fc.parameters(), "lr": 1e-3},  # Capas nuevas con mayor LR 
    {"params": modelo_base.parameters(), "lr": 1e-5}  # Modelo base con menor LR 
]) 
 
# Configurar DataLoader 
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) 
 
# Entrenar el modelo 
modelo_base.train() 
for epoch in range(10):  # Número de épocas 
    for datos, etiquetas in train_loader: 
        datos, etiquetas = datos.to("cuda"), etiquetas.to("cuda")  # Enviar a GPU si está disponible 
 
        # Forward pass 
        salida = modelo_base(datos) 
        perdida = torch.nn.functional.cross_entropy(salida, etiquetas) 
 
        # Backpropagation 
        optimizador.zero_grad() 
        perdida.backward() 
        optimizador.step() 
 
    print(f"Época {epoch+1}: Pérdida = {perdida.item():.4f}") 
  

Después de entrenar, se debe evaluar el modelo en un conjunto de validación para verificar su desempeño. En la siguiente sección, veremos cómo hacer esta evaluación correctamente. 

Evaluación del modelo después del Fine-Tuning 

Una vez que el modelo ha sido ajustado con Fine-Tuning, es esencial evaluar su rendimiento para asegurarnos de que ha mejorado sin perder capacidad de generalización.  

Uso de un conjunto de prueba separado 

Para obtener una medición realista del rendimiento del modelo, se debe evaluar con un conjunto de prueba que no haya sido utilizado en el entrenamiento ni en la validación.  

from tensorflow.keras.models import load_model 
 
# Cargar modelo ajustado 
modelo = load_model("modelo_finetuned.h5") 
 
# Evaluar en conjunto de prueba 
loss, accuracy = modelo.evaluate(X_test, y_test) 
print(f"Precisión en prueba: {accuracy:.2f}") 
import torch 
 
# Definir función de evaluación 
def evaluar_modelo(modelo, dataloader): 
    modelo.eval() 
    correctos = 0 
    total = 0 
    with torch.no_grad(): 
        for datos, etiquetas in dataloader: 
            salida = modelo(datos) 
            _, predicciones = torch.max(salida, 1) 
            correctos += (predicciones == etiquetas).sum().item() 
            total += etiquetas.size(0) 
    print(f"Precisión en prueba: {correctos / total:.2f}") 
 
# Evaluar modelo ajustado 
evaluar_modelo(modelo_base, test_loader) 
  

Métricas clave para evaluar modelos ajustados 

Más allá de la precisión, es recomendable utilizar métricas adicionales que ofrezcan una evaluación más completa del modelo:  

  • Matriz de confusión: Permite analizar los errores del modelo en cada clase.  

  • F1-Score: Equilibra precisión y recall, útil en datasets desbalanceados.  

  • Curva ROC-AUC: Evalúa la capacidad del modelo para distinguir entre clases. 

from sklearn.metrics import confusion_matrix 
import seaborn as sns 
import matplotlib.pyplot as plt 
 
# Obtener predicciones del modelo 
y_pred = modelo.predict(X_test) 
y_pred_classes = y_pred.argmax(axis=1) 
 
# Calcular matriz de confusión 
matriz = confusion_matrix(y_test, y_pred_classes) 
 
# Graficar matriz de confusión 
sns.heatmap(matriz, annot=True, fmt='d', cmap='Blues') 
plt.xlabel("Predicción") 
plt.ylabel("Real") 
plt.title("Matriz de Confusión") 
plt.show() 
from sklearn.metrics import f1_score 
 
# Calcular F1-Score 
f1 = f1_score(y_test, y_pred_classes, average="weighted") 
print(f"F1-Score: {f1:.2f}") 
from sklearn.metrics import roc_auc_score 
 
# Calcular ROC-AUC 
roc_auc = roc_auc_score(y_test, y_pred, multi_class="ovr") 
print(f"ROC-AUC: {roc_auc:.2f}") 
  

Comparación con el modelo base 

Para confirmar que el Fine-Tuning ha sido efectivo, se debe comparar el nuevo modelo con el modelo preentrenado original. Si el ajuste no mejora los resultados o incluso los empeora, es posible que haya ocurrido sobreajuste o que los hiperparámetros no sean óptimos.  

Con estas estrategias, podemos evaluar con mayor precisión el impacto del Fine-Tuning en el modelo.  

Fine-Tuning en modelos de lenguaje natural (NLP) 

El Fine-Tuning en modelos de procesamiento de lenguaje natural (NLP) permite adaptar modelos preentrenados a tareas específicas como clasificación de texto, generación de lenguaje o análisis de sentimientos.  

Modelos de lenguaje preentrenados más utilizados 

Algunos de los modelos de NLP más populares para Fine-Tuning incluyen:  

  • BERT (Bidirectional Encoder Representations from Transformers): Ideal para tareas de clasificación y respuesta a preguntas.  

  • GPT (Generative Pre-trained Transformer): Excelente para generación de texto y chatbots 

  • T5 (Text-to-Text Transfer Transformer): Versátil para tareas de NLP donde la entrada y salida son texto. 

Fine-Tuning de BERT con Hugging Face 

La biblioteca Hugging Face Transformers facilita el ajuste de modelos de NLP preentrenados. Un ejemplo común es ajustar BERT para la clasificación de texto.  

from transformers import BertForSequenceClassification, Trainer, TrainingArguments 
from datasets import load_dataset 
 
# Cargar dataset de ejemplo 
dataset = load_dataset("imdb") 
 
# Cargar modelo preentrenado BERT 
modelo = BertForSequenceClassification.from_pretrained("bert-base-uncased", num_labels=2) 
 
# Definir argumentos de entrenamiento 
argumentos = TrainingArguments( 
    output_dir="./resultados", 
    evaluation_strategy="epoch", 
    per_device_train_batch_size=8, 
    per_device_eval_batch_size=8, 
    num_train_epochs=3, 
    save_total_limit=2 
) 
 
# Crear el Trainer y entrenar el modelo 
trainer = Trainer( 
    model=modelo, 
    args=argumentos, 
    train_dataset=dataset["train"], 
    eval_dataset=dataset["test"] 
) 
 
trainer.train() 
  

Evaluación del modelo ajustado 

Después del entrenamiento, es importante evaluar el rendimiento del modelo en datos de prueba.  

from transformers import pipeline 
 
# Cargar modelo ajustado para clasificación de texto 
clasificador = pipeline("text-classification", model="./resultados") 
 
# Evaluar en ejemplos de prueba 
textos_prueba = ["Este producto es excelente, me encantó.", "No me gustó la calidad, esperaba más."] 
predicciones = clasificador(textos_prueba) 
 
print(predicciones) 
  

Consideraciones al aplicar Fine-Tuning en NLP 

Para obtener los mejores resultados al ajustar modelos de NLP, es recomendable:  

  • Utilizar datasets bien etiquetados: La calidad de los datos es clave para un ajuste efectivo.  

  • Controlar el sobreajuste: Ajustar el número de épocas y usar técnicas de regularización.  

  • Aprovechar técnicas como el aprendizaje por transferencia: Congelar capas iniciales del modelo puede mejorar la eficiencia. 

Estos pasos permiten adaptar modelos de lenguaje preentrenados a tareas específicas, mejorando su precisión sin necesidad de entrenar desde cero.  

Fine-Tuning en modelos de visión por computadora 

El Fine-Tuning también se aplica en modelos de visión por computadora para mejorar el rendimiento en tareas como clasificación de imágenes, detección de objetos y segmentación semántica.  

Modelos de visión por computadora más utilizados 

Entre los modelos más populares para Fine-Tuning en visión artificial se encuentran:  

  • ResNet (Residual Networks): Útil para clasificación de imágenes con alta precisión.  

  • EfficientNet: Optimizado para obtener buenos resultados con menor costo computacional.  

  • YOLO (You Only Look Once): Especializado en detección de objetos en tiempo real. 

Fine-Tuning de ResNet con PyTorch 

PyTorch es una de las bibliotecas más utilizadas para el ajuste de modelos de visión por computadora. Un ejemplo común es utilizar ResNet preentrenado para clasificar nuevas imágenes.  

import torch 
import torch.nn as nn 
import torchvision.models as models 
import torchvision.transforms as transforms 
from torchvision import datasets 
from torch.utils.data import DataLoader 
 
# Cargar modelo ResNet preentrenado 
modelo = models.resnet50(pretrained=True) 
 
# Reemplazar la última capa para ajustar el número de clases 
num_features = modelo.fc.in_features 
modelo.fc = nn.Linear(num_features, 10)  # Suponiendo 10 clases 
 
# Congelar capas iniciales 
for param in modelo.parameters(): 
    param.requires_grad = False 
 
# Permitir que solo la última capa se entrene 
for param in modelo.fc.parameters(): 
    param.requires_grad = True 
 
# Definir transformaciones de datos 
transformaciones = transforms.Compose([ 
    transforms.Resize((224, 224)), 
    transforms.ToTensor() 
]) 
 
# Cargar dataset de ejemplo 
dataset = datasets.FakeData(transform=transformaciones) 
loader = DataLoader(dataset, batch_size=8, shuffle=True) 
 
# Definir función de pérdida y optimizador 
criterio = nn.CrossEntropyLoss() 
optimizador = torch.optim.Adam(modelo.fc.parameters(), lr=0.001) 
 
# Entrenar modelo por algunas épocas 
modelo.train() 
for epoch in range(3): 
    for imagenes, etiquetas in loader: 
        salida = modelo(imagenes) 
        perdida = criterio(salida, etiquetas) 
 
        optimizador.zero_grad() 
        perdida.backward() 
        optimizador.step() 
  

Evaluación del modelo ajustado 

Después del ajuste del modelo, se evalúa su precisión utilizando imágenes de prueba.  

# Evaluar el modelo ajustado 
modelo.eval() 
imagenes_prueba, etiquetas_prueba = next(iter(loader)) 
with torch.no_grad(): 
    predicciones = modelo(imagenes_prueba) 
 
# Mostrar las primeras predicciones 
print(predicciones.argmax(dim=1)) 
  

Consideraciones al aplicar Fine-Tuning en visión por computadora 

Para lograr un Fine-Tuning exitoso en modelos de visión artificial, se recomienda:  

  • Congelar capas iniciales: Permite aprovechar características generales aprendidas en modelos preentrenados 

  • Usar aumentación de datos: Técnicas como rotaciones y espejados mejoran la capacidad del modelo para generalizar.  

  • Ajustar la tasa de aprendizaje: Valores muy altos pueden destruir las representaciones preaprendidas, mientras que valores bajos pueden hacer el entrenamiento demasiado lento. 

Siguiendo estas recomendaciones, se puede adaptar un modelo de visión artificial preentrenado a nuevos conjuntos de datos con gran eficiencia.  

Conclusiones sobre las estrategias para Fine-tuning

El Fine-Tuning es una técnica clave en Machine Learning para mejorar modelos preentrenados y adaptarlos a tareas específicas. Su aplicación permite ahorrar tiempo y recursos computacionales en comparación con entrenar modelos desde cero.  

En este artículo hemos visto cómo funciona el Fine-Tuning, desde la selección del modelo adecuado hasta su implementación en visión por computadora y procesamiento de lenguaje natural. Aplicar buenas prácticas, como ajustar la tasa de aprendizaje y manejar conjuntos de datos equilibrados, es esencial para obtener modelos eficientes y precisos.  

Para cerrar, repasemos algunos puntos clave:  

  • El Fine-Tuning permite reutilizar modelos preentrenados y ajustarlos a tareas específicas con menos datos y menos entrenamiento.  

  • Congelar y descongelar capas progresivamente ayuda a mejorar el rendimiento sin destruir el conocimiento previo del modelo.  

  • El uso de tasas de aprendizaje diferenciadas facilita el ajuste adecuado de las capas nuevas y preentrenadas 

  • Técnicas como Data Augmentation, regularización y Early Stopping ayudan a prevenir el sobreajuste.  

  • El Fine-Tuning es aplicable en NLP, visión por computadora y más, permitiendo mejorar modelos como BERT, ResNet o GPT. 

En resumen, el Fine-Tuning es una herramienta poderosa para desarrolladores y científicos de datos que buscan mejorar modelos existentes sin necesidad de costosos entrenamientos desde cero. Con las herramientas adecuadas, cualquiera puede optimizar modelos de Machine Learning para obtener mejores resultados en distintas aplicaciones. 

Artículos relacionados

En los últimos años, ha habido avances significativos en el campo de la inteligencia artificial aplicables a la robótica cognitiva. ¡Lee en qué consiste!
pablo.blanco

Robótica cognitiva: una gran oportunidad para la inteligencia artificial

17/11/2023

La robótica cognitiva busca comprender los modelos cognitivos que rigen la inteligencia humana y plasmarlos en robots. Su objetivo es hacer posible

El avance de la tecnología es imparable e impredecible. En EducaOpen no tenemos videntes, pero sí especialistas que prevén estos adelantos tecnológicos.
pablo.blanco

Tecnologías futuristas que están a la vuelta de la esquina

17/11/2023

En el habla cotidiana, entendemos que lo futurista es una visión orientada al futuro en lo referente a todo el conjunto de dispositivos tecnológicos p

En EducaOpen sabemos de primera mano que el avance de las tecnologías es imparable. Aquí te esbozamos nuestras predicciones sobre el futuro de la IA.
pablo.blanco

El futuro de la IA: posibles avances y retos

17/11/2023

En EducaOpen sabemos de primera mano que el avance de las tecnologías es imparable.