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

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.