Fine-tuning

Fine-tuning: adaptación de modelos preentrenados

26/03/2025

El Fine-Tuning (ajuste fino) es una técnica avanzada en Machine Learning que permite adaptar modelos preentrenados a tareas específicas. En lugar de entrenar un modelo desde cero, lo que requiere grandes volúmenes de datos y potencia computacional, el Fine-Tuning reutiliza conocimientos previos y los ajusta a nuevos contextos.  

Hoy en día, este enfoque es ampliamente utilizado en aplicaciones como procesamiento de lenguaje natural (NLP), visión por computadora y más. Gracias a frameworks como TensorFlow, PyTorch y Hugging Face, el Fine-Tuning se ha convertido en una herramienta accesible para desarrolladores y científicos de datos.  

 

Qué es el Fine-Tuning en Machine Learning 

El Fine-Tuning es el proceso de ajustar un modelo preentrenado a una nueva tarea mediante un entrenamiento adicional con datos específicos del dominio.  

Diferencia entre Fine-Tuning y Transfer Learning 

El Fine-Tuning es una forma avanzada de Transfer Learning, pero tienen diferencias clave:  

Característica 

Transfer Learning 

Fine-Tuning 

Uso del modelo 

Se reutilizan capas preentrenadas y se añaden nuevas capas de salida. 

Se ajustan las capas preentrenadas para mejorar el desempeño en la nueva tarea. 

Ajuste de pesos 

Solo se entrenan las nuevas capas. 

Se permite que todas o algunas capas actualicen sus pesos. 

Coste computacional 

Menor, ya que solo se entrena una parte del modelo. 

Mayor, pues el modelo se entrena parcialmente de nuevo. 

Beneficios del Fine-Tuning

Algunas de sus ventajas clave son:  

  • Ahorro de tiempo y recursos: Se aprovechan modelos ya entrenados en grandes conjuntos de datos.  

  • Mejor desempeño en tareas específicas: Ideal para personalizar modelos en nichos concretos.  

  • Menor necesidad de datos etiquetados: Se requieren menos datos que en un entrenamiento desde cero.  

  • Mayor eficiencia computacional: Reduce el tiempo y la potencia de cálculo necesaria. 

Casos de uso comunes 

El Fine-Tuning se aplica en diversas áreas:  

  • Procesamiento de lenguaje natural (NLP): Ajuste de modelos como BERT o GPT para análisis de texto o traducción automática.  

  • Visión por computadora: Adaptación de ResNet o EfficientNet para clasificación de imágenes o detección de objetos.  

  • Reconocimiento de voz: Mejora de modelos preentrenados para identificar acentos o mejorar la precisión en idiomas específicos. 

Pasos clave para aplicar Fine-Tuning 

Para realizar Fine-Tuning correctamente, es importante seguir estos pasos para optimizar el proceso y evitar problemas como el sobreajuste.  

Seleccionar un modelo preentrenado adecuado 

Elige un modelo preentrenado adecuado según la tarea: ResNet, EfficientNet para imágenes o BERT, GPT para texto. Luego, cárgalo en TensorFlow o PyTorch y congela sus capas base para conservar el conocimiento previo. 

En TensorFlow (Keras), usamos la función MobileNetV2 de Keras Applications: 

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() 
  

En PyTorch, usamos la función models.resnet50 de torchvision.models: 

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) 
  

Congelar capas base del modelo 

Para evitar que el modelo pierda información de su entrenamiento original, primero se deben congelar sus capas base, es decir, evitar que sus pesos se actualicen durante las primeras etapas del Fine-Tuning 

En TensorFlow, iteramos sobre modelo_base.layers y desactivamos trainable: 

# Congelar todas las capas del modelo base 
for capa in modelo_base.layers: 
    capa.trainable = False 
  

En PyTorch, desactivamos requires_grad en los parámetros del modelo: 

# Congelar las capas del modelo 
for param in modelo_base.parameters(): 
    param.requires_grad = False 
  

Añadir nuevas capas personalizadas 

Después de congelar las capas preentrenadas, se agregan nuevas capas para adaptar el modelo a la nueva tarea.  

En TensorFlow, usamos Sequential para agregar capas personalizadas: 

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() 
  

En PyTorch, modificamos la última capa del modelo base para adaptarlo a la nueva tarea: 

import torch.nn as nn 
 
# Modificar la última capa de ResNet para una clasificación personalizada 
modelo_base.fc = nn.Sequential( 
    nn.Linear(modelo_base.fc.in_features, 128), 
    nn.ReLU(), 
    nn.Dropout(0.5), 
    nn.Linear(128, 10)  # 10 clases de salida 
) 
 
# Ver la estructura del modelo modificado 
print(modelo_base) 
  

Entrenar el modelo con tasas de aprendizaje diferenciadas 

El entrenamiento debe realizarse con diferentes tasas de aprendizaje 

  • Capas base preentrenadasLearning rate bajo, para preservar conocimientos previos.  

  • Capas nuevasLearning rate alto, para permitir una mejor adaptación a los nuevos datos. 

En TensorFlow, configuramos el optimizer con un learning_rate bajo para el modelo base: 

from tensorflow.keras.optimizers import Adam 
 
# Configurar diferentes tasas de aprendizaje 
modelo_base.trainable = True  # Descongelar modelo base 
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"]) 
  

En PyTorch, asignamos distintas tasas de aprendizaje para las capas nuevas y el modelo base: 

import torch.optim as optim 
 
# Definir tasas de aprendizaje diferentes 
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 
]) 
  

Evaluar y ajustar el modelo 

Después del entrenamiento, se evalúa el modelo en un conjunto de datos de validación. Si el rendimiento no es óptimo, se pueden hacer ajustes en hiperparámetros o utilizar técnicas como Early Stopping 

En TensorFlow, utilizamos EarlyStopping para detener el entrenamiento cuando la pérdida no mejora: 

from tensorflow.keras.callbacks import EarlyStopping 
 
# Aplicar Early Stopping para evitar 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]) 
  

En PyTorch, evaluamos la precisión en el conjunto de validación manualmente: 

from torch.utils.data import DataLoader 
import torch.nn.functional as F 
 
# Función de evaluación 
def evaluar_modelo(modelo, dataloader, dispositivo): 
    modelo.eval()  # Modo evaluación 
    correctos = 0 
    total = 0 
    with torch.no_grad(): 
        for datos, etiquetas in dataloader: 
            datos, etiquetas = datos.to(dispositivo), etiquetas.to(dispositivo) 
            salidas = modelo(datos) 
            _, predicciones = torch.max(salidas, 1) 
            correctos += (predicciones == etiquetas).sum().item() 
            total += etiquetas.size(0) 
    return correctos / total 
 
# Evaluar el modelo en el conjunto de validación 
precision = evaluar_modelo(modelo_base, DataLoader(val_dataset, batch_size=32), dispositivo="cuda") 
print(f"Precisión en validación: {precision:.2f}") 
  

Aplicando estos pasos, se puede hacer un Fine-Tuning efectivo en distintos modelos. En la siguiente sección, exploraremos técnicas avanzadas para mejorar aún más el rendimiento.  

Consideraciones avanzadas en Fine-Tuning 

Una vez comprendidos los pasos básicos, es importante aplicar técnicas avanzadas que mejoren el rendimiento y eficiencia del Fine-Tuning 

Estrategia de descongelamiento progresivo 

En lugar de descongelar todas las capas del modelo base de una vez, una estrategia más efectiva es descongelar progresivamente las capas superiores y entrenarlas en diferentes etapas.  

Esto permite que el modelo aprenda de manera más controlada, evitando ajustes bruscos que puedan afectar negativamente su desempeño.  

Ejemplo en TensorFlow: Descongelar capas por bloques  

import tensorflow as tf 
from tensorflow import keras 
 
# Cargar modelo preentrenado (Ej: ResNet50) 
base_model = keras.applications.ResNet50(weights="imagenet", include_top=False) 
 
# Congelar todas las capas inicialmente 
base_model.trainable = False 
 
# Añadir capas personalizadas 
inputs = keras.Input(shape=(224, 224, 3)) 
x = base_model(inputs, training=False) 
x = keras.layers.GlobalAveragePooling2D()(x) 
outputs = keras.layers.Dense(10, activation="softmax")(x) 
modelo = keras.Model(inputs, outputs) 
 
# Descongelar las últimas 50 capas del modelo base 
for capa in base_model.layers[-50:]: 
    capa.trainable = True 
 
# Compilar y entrenar el modelo 
modelo.compile(optimizer=keras.optimizers.Adam(1e-5), loss="categorical_crossentropy", metrics=["accuracy"]) 
modelo.fit(train_data, epochs=5) 
  

Ejemplo en PyTorch: Ajuste progresivo de requires_grad  

import torch 
import torchvision.models as models 
 
# Cargar modelo preentrenado 
modelo = models.resnet50(pretrained=True) 
 
# Congelar todas las capas 
for param in modelo.parameters(): 
    param.requires_grad = False 
 
# Descongelar progresivamente las últimas capas 
for param in list(modelo.layer4.parameters()): 
    param.requires_grad = True 
 
# Definir optimizador solo para capas descongeladas 
import torch.optim as optim 
optimizador = optim.Adam(filter(lambda p: p.requires_grad, modelo.parameters()), lr=1e-5) 
  

Uso de tasas de aprendizaje diferenciadas 

El Discriminative Learning Rate consiste en asignar distintos + a las capas del modelo:  

  • Capas cercanas a la salida: Mayor learning rate, ya que deben adaptarse más rápido a la nueva tarea.  

  • Capas profundas: Menor learning rate, para preservar los conocimientos previos. 

Ejemplo en TensorFlow: Configurar distintos learning rates  

from tensorflow.keras.optimizers import Adam 
 
# Definir tasa de aprendizaje por capas 
lr_schedule = [ 
    (base_model.layers[:100], 1e-6),  # Capas profundas con menor learning rate 
    (base_model.layers[100:], 1e-4)   # Capas superiores con mayor learning rate 
] 
 
# Aplicar learning rate a cada capa 
for capas, lr in lr_schedule: 
    for capa in capas: 
        capa.trainable = True 
        capa.add_weight(name="lr", shape=(), initializer=tf.constant_initializer(lr)) 
 
# Compilar y entrenar 
modelo.compile(optimizer=Adam(learning_rate=1e-4), loss="categorical_crossentropy", metrics=["accuracy"]) 
modelo.fit(train_data, epochs=5) 
  

Ejemplo en PyTorch: Configuración de optimizador con múltiples learning rates  

import torch.optim as optim 
 
# Definir optimizador con distintos learning rates 
optimizador = optim.Adam([ 
    {"params": modelo.layer1.parameters(), "lr": 1e-6}, 
    {"params": modelo.layer2.parameters(), "lr": 1e-5}, 
    {"params": modelo.layer3.parameters(), "lr": 1e-4}, 
], lr=1e-4) 
  

Data Augmentation adaptado a Fine-Tuning 

El Data Augmentation ayuda a mejorar la capacidad de generalización del modelo cuando hay pocos datos.  

  • Para imágenes: Rotaciones, volteos, cambios de brillo.  

  • Para texto: Sustitución de palabras con sinónimos, back translation 

  • Para audio: Perturbaciones en el sonido, cambios de tono o ruido de fondo. 

Ejemplo en TensorFlow: Augmentación de imágenes con ImageDataGenerator  

from tensorflow.keras.preprocessing.image import ImageDataGenerator 
 
# Crear generador de datos con Data Augmentation 
datagen = ImageDataGenerator( 
    rotation_range=20, 
    width_shift_range=0.2, 
    height_shift_range=0.2, 
    horizontal_flip=True, 
    brightness_range=[0.8, 1.2] 
) 
 
# Aplicar Data Augmentation a imágenes 
train_generator = datagen.flow_from_directory("dataset/", target_size=(224, 224), batch_size=32) 
  

Ejemplo en PyTorch: Transformaciones con torchvision.transforms  

import torchvision.transforms as transforms 
 
# Definir transformaciones para Data Augmentation 
transformacion = transforms.Compose([ 
    transforms.RandomRotation(20), 
    transforms.RandomHorizontalFlip(), 
    transforms.ColorJitter(brightness=0.2, contrast=0.2), 
    transforms.ToTensor() 
]) 
  

Fine-Tuning en dominios distintos al original 

El Fine-Tuning es útil cuando se usa un modelo entrenado en un dominio y se adapta a otro diferente (ejemplo: usar un modelo de imágenes naturales para imágenes médicas).  

En estos casos, se recomienda:  

  • Congelar la mayoría de las capas y entrenar solo las últimas.  

  • Aplicar Data Augmentation especializado.  

  • Hacer un ajuste fino en hiperparámetros. 

Ejemplo en TensorFlow: Transferencia de aprendizaje en dominios distintos  

# Cargar modelo base 
base_model = keras.applications.VGG16(weights="imagenet", include_top=False) 
 
# Congelar la mayoría de capas y modificar la salida 
for capa in base_model.layers[:-5]:  # Descongelar solo las últimas 5 capas 
    capa.trainable = False 
 
# Construir nuevo modelo para otra tarea 
inputs = keras.Input(shape=(224, 224, 3)) 
x = base_model(inputs, training=False) 
x = keras.layers.GlobalAveragePooling2D()(x) 
outputs = keras.layers.Dense(2, activation="sigmoid")(x)  # Para clasificación binaria 
modelo = keras.Model(inputs, outputs) 
 
# Compilar y entrenar 
modelo.compile(optimizer=Adam(learning_rate=1e-4), loss="binary_crossentropy", metrics=["accuracy"]) 
modelo.fit(train_data, epochs=10) 
  

Ejemplo en PyTorch: Modificar capas de salida para otra tarea  

import torch.nn as nn 
 
# Modificar la última capa de un modelo ResNet50 para una nueva tarea 
modelo.fc = nn.Linear(modelo.fc.in_features, 2)  # Cambio para clasificación binaria 
  

Con estas técnicas avanzadas, se puede lograr un Fine-Tuning más eficiente y adaptado a cada tipo de problema. En la siguiente sección, exploraremos estrategias para evitar el sobreajuste durante el entrenamiento.  

Artículos relacionados

SearchGPT es un nuevo prototipo creado en el seno de OpenAI que pretende potenciar las búsquedas al uso con el poder de la inteligencia artificial.
pablo.blanco

SearchGPT: el nuevo buscador de inteligencia artificial de OpenAI

06/08/2024

SearchGPT es un nuevo prototipo creado en el seno de OpenAI que combina las características de la inteligencia artificial propia de los grandes modelos de lenguaje con información actuali

Se trata de una técnica muy común para entrenar modelos de machine learning. ¡Te contamos cómo funciona y más detalles!
pablo.blanco

¿Cómo funcionan los árboles de decisión en machine learning?

22/02/2024

Los árboles de decisión son un tipo de aprendizaje automático supervisado destinado a realizar predicciones en función de un conjunto de preguntas a las que el siste

El mundo del deporte está evolucionando a grandes pasos gracias a la IA. ¡Descubre cómo se está usando en el deporte!
pablo.blanco

Aplicaciones de la inteligencia artificial en los deportes

19/03/2024

Vemos como el mundo del deporte está evolucionando a pasos agigantados de la mano de la tecnología, aunque a simple vista no lo parezca para muchos aficionados.