
Fine-tuning: adaptación de modelos preentrenados
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 preentrenadas → Learning rate bajo, para preservar conocimientos previos.
Capas nuevas → Learning 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: el nuevo buscador de inteligencia artificial de OpenAI
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

¿Cómo funcionan los árboles de decisión en machine learning?
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

Aplicaciones de la inteligencia artificial en los deportes
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.