25. Transfer Learning en visión por computadora

25.1 Introducción

En muchos proyectos reales de visión por computadora aparece una limitación muy concreta: no tenemos millones de imágenes ni semanas de entrenamiento para construir un modelo grande desde cero. Sin embargo, eso no significa que estemos condenados a obtener resultados pobres. Aquí entra una de las ideas más poderosas del Deep Learning aplicado: el transfer learning.

El transfer learning consiste en reutilizar conocimiento aprendido previamente por un modelo entrenado en un problema grande para adaptarlo a un problema nuevo. En visión por computadora esto ha sido especialmente exitoso, porque muchas representaciones visuales aprendidas en datasets masivos resultan útiles también en tareas diferentes.

En este tema veremos qué significa transferir conocimiento en una CNN, por qué esta estrategia funciona tan bien y qué formas prácticas existen para aplicarla en PyTorch.

25.2 La idea central

Supongamos que un modelo fue entrenado sobre millones de imágenes de muchas categorías. Durante ese proceso, sus capas aprendieron a detectar bordes, texturas, formas, combinaciones de patrones y estructuras visuales de gran utilidad general.

Si luego queremos resolver un problema nuevo, por ejemplo clasificar tipos de hojas, frutas o piezas industriales, no siempre hace falta empezar desde cero. Podemos aprovechar parte de ese conocimiento previo y adaptar solo lo necesario.

El transfer learning no reutiliza “la respuesta final” del modelo original. Reutiliza representaciones visuales que ya aprendieron a describir imágenes de manera útil.

25.3 ¿Por qué funciona tan bien en visión por computadora?

Porque muchas características visuales básicas son compartidas entre muchísimos problemas. Bordes, curvas, texturas, contrastes, partes y composiciones aparecen una y otra vez, incluso en dominios distintos.

Las primeras capas de una CNN suelen aprender rasgos bastante generales. Las capas más profundas se vuelven más específicas del problema original. Esta jerarquía explica por qué resulta viable reutilizar parte del modelo y adaptar otra parte.

25.4 Entrenar desde cero versus reutilizar

Entrenar desde cero tiene sentido cuando:

  • Tenemos un dataset muy grande.
  • Disponemos de bastante cómputo.
  • El problema es muy específico o muy diferente de los datos habituales.

Pero en muchos casos prácticos ocurre lo contrario:

  • El dataset es pequeño o mediano.
  • El tiempo de entrenamiento es limitado.
  • Necesitamos un buen punto de partida rápido.

En ese contexto, el transfer learning suele ser muy superior como estrategia inicial.

25.5 Qué es un modelo preentrenado

Un modelo preentrenado es un modelo cuyos pesos ya fueron ajustados previamente sobre un dataset grande. En visión por computadora, muchos modelos clásicos fueron entrenados sobre ImageNet, un conjunto enorme con miles de categorías.

Esto significa que cuando cargamos una arquitectura preentrenada, no estamos empezando con pesos aleatorios, sino con una base visual ya muy rica.

25.6 ¿Qué se transfiere exactamente?

Lo que se transfiere son los parámetros aprendidos por la red, es decir, los pesos de sus capas. En particular, esos pesos codifican filtros y representaciones internas que capturan patrones visuales útiles.

En una CNN profunda, las primeras capas suelen transferirse muy bien porque detectan rasgos generales. Las capas finales, en cambio, suelen necesitar más adaptación al nuevo problema.

25.7 Dos estrategias clásicas

En la práctica, el transfer learning suele aplicarse de dos formas principales:

  • Usar el modelo como extractor de características.
  • Hacer fine tuning del modelo.

Ambas estrategias reutilizan conocimiento previo, pero con diferente nivel de ajuste sobre las capas originales.

25.8 Modelo como extractor de características

En este enfoque, se congelan las capas preentrenadas y solo se reemplaza y entrena la capa final de clasificación. La idea es usar la red ya aprendida como una máquina que extrae representaciones visuales útiles, mientras una nueva cabeza de clasificación aprende el problema específico.

Esta estrategia suele ser muy buena cuando el dataset nuevo es pequeño.

25.9 Fine tuning

El fine tuning consiste en no limitarse a entrenar solo la capa final, sino permitir que algunas o todas las capas del modelo preentrenado se ajusten al nuevo problema.

Esto puede producir mejores resultados cuando:

  • Tenemos más datos.
  • El nuevo dominio es suficientemente distinto.
  • Queremos adaptar más profundamente las representaciones.

25.10 Congelar capas

Congelar una capa significa impedir que sus parámetros se actualicen durante el entrenamiento. En PyTorch esto se hace ajustando requires_grad a False.

for param in model.parameters():
    param.requires_grad = False

Una vez hecho esto, el optimizador no modificará esos pesos.

25.11 Reemplazar la cabeza de clasificación

La parte final del modelo original suele estar diseñada para el número de clases del dataset con que fue entrenado originalmente. Por eso, al reutilizarlo, normalmente se reemplaza la última capa para que coincida con nuestro nuevo problema.

Por ejemplo, si un modelo termina en 1000 clases y nuestro problema tiene 3 clases, debemos adaptar esa salida.

25.12 Intuición práctica

Podemos pensar el modelo preentrenado como una red que ya sabe “mirar” imágenes. Lo que hacemos al adaptarlo es enseñarle a tomar esa manera de mirar y dirigirla hacia una tarea nueva.

Cuanto más parecido sea el nuevo problema al dominio original, más útil suele ser la transferencia directa. Cuanto más diferente sea, más probable es que necesitemos un fine tuning más profundo.

25.13 Ventajas del transfer learning

Entre sus ventajas más importantes están:

  • Mejor punto de partida que pesos aleatorios.
  • Menor tiempo de entrenamiento.
  • Buen desempeño incluso con menos datos.
  • Mayor estabilidad inicial del aprendizaje.

Por eso es una técnica extremadamente común en problemas reales de visión.

25.14 Cuándo puede no ser suficiente

Aunque muy útil, el transfer learning no es una solución mágica universal. Puede ser menos efectivo cuando:

  • El dominio nuevo es muy distinto al del preentrenamiento.
  • Las imágenes tienen una naturaleza especial, por ejemplo médica o científica.
  • La tarea requiere representaciones muy específicas que el modelo original no aprendió bien.

Aun así, incluso en esos casos suele ser un excelente punto de partida para experimentar.

25.15 Modelos muy usados para transfer learning

En visión por computadora, algunos modelos preentrenados muy utilizados son:

  • ResNet
  • VGG
  • DenseNet
  • MobileNet
  • EfficientNet

Todos ellos tienen versiones accesibles desde torchvision.models.

25.16 Cargar un modelo preentrenado en PyTorch

Con torchvision, cargar un modelo preentrenado suele ser directo. Por ejemplo, con ResNet18:

from torchvision import models

model = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)

Esto descarga o reutiliza los pesos preentrenados y deja listo el modelo para adaptarlo.

25.17 Congelar y reemplazar la última capa

Una estrategia muy habitual es:

  1. Cargar el modelo preentrenado.
  2. Congelar sus capas.
  3. Reemplazar la capa final.
  4. Entrenar solo esa nueva cabeza.

Por ejemplo:

for param in model.parameters():
    param.requires_grad = False

num_features = model.fc.in_features
model.fc = nn.Linear(num_features, 3)

Aquí suponemos un problema de 3 clases.

25.18 ¿Qué parámetros debe optimizar el optimizador?

Si congelamos casi toda la red y solo queremos entrenar la nueva capa final, conviene pasar al optimizador únicamente los parámetros que siguen siendo entrenables.

optimizer = torch.optim.Adam(model.fc.parameters(), lr=0.001)

Esto deja muy claro qué parte del modelo estamos adaptando realmente.

25.19 Fine tuning parcial

Otra posibilidad es congelar casi todo el modelo y descongelar solo las últimas capas o bloques. Esto permite adaptar representaciones profundas sin perder completamente la base aprendida.

Es una estrategia intermedia muy útil cuando el problema nuevo no es idéntico al original, pero tampoco completamente diferente.

25.20 Fine tuning completo

También es posible entrenar todo el modelo preentrenado, es decir, dejar todas las capas actualizables. En ese caso, suele usarse una tasa de aprendizaje relativamente pequeña, porque no queremos destruir demasiado rápido el conocimiento ya aprendido.

Esto puede dar muy buenos resultados si contamos con suficientes datos y si el dominio lo justifica.

25.21 Riesgo de sobreajuste

Justamente porque el transfer learning se usa mucho con datasets pequeños, el riesgo de overfitting sigue presente. Un modelo potente adaptado a pocos datos puede memorizar con facilidad si no se lo controla bien.

Por eso siguen siendo importantes:

  • Un buen split train/validation/test.
  • Data augmentation razonable.
  • Regularización.
  • Monitoreo de validación.

25.22 Por qué no siempre conviene entrenar desde cero

Entrenar desde cero puede sonar más “puro”, pero muchas veces es una mala decisión práctica. Si un modelo preentrenado ya aprendió representaciones robustas y nuestro dataset es limitado, empezar desde cero puede desperdiciar tiempo y rendimiento.

En la práctica profesional, reutilizar conocimiento previo suele ser una decisión muy sensata.

25.23 Ejemplo conceptual completo

Este ejemplo muestra la estructura general de un pipeline de transfer learning con ResNet18 para un problema de 3 clases:

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms, models


device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor()
])

train_dataset = datasets.FakeData(
    size=300,
    image_size=(3, 224, 224),
    num_classes=3,
    transform=transform
)

val_dataset = datasets.FakeData(
    size=100,
    image_size=(3, 224, 224),
    num_classes=3,
    transform=transform
)

train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=16, shuffle=False)

model = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)

for param in model.parameters():
    param.requires_grad = False

num_features = model.fc.in_features
model.fc = nn.Linear(num_features, 3)
model = model.to(device)

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.fc.parameters(), lr=0.001)

for epoch in range(3):
    model.train()
    train_loss = 0.0

    for images, labels in train_loader:
        images = images.to(device)
        labels = labels.to(device)

        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        train_loss += loss.item() * images.size(0)

    avg_train_loss = train_loss / len(train_dataset)

    model.eval()
    correct = 0
    total = 0

    with torch.no_grad():
        for images, labels in val_loader:
            images = images.to(device)
            labels = labels.to(device)

            outputs = model(images)
            preds = outputs.argmax(dim=1)

            correct += (preds == labels).sum().item()
            total += labels.size(0)

    val_acc = correct / total
    print(f"Epoca {epoch+1}: train_loss={avg_train_loss:.4f}, val_acc={val_acc:.4f}")

Este ejemplo no pretende resolver un problema real, pero muestra con claridad la lógica de cargar, congelar, reemplazar y entrenar una cabeza de clasificación sobre un modelo preentrenado.

25.24 Qué está ocurriendo en ese código

Vale la pena leer el ejemplo en bloques:

  • Se cargan datos y dataloaders.
  • Se obtiene una ResNet18 con pesos preentrenados.
  • Se congelan todas sus capas.
  • Se reemplaza la capa final por una nueva salida de 3 clases.
  • Se entrena solo esa capa nueva.
  • Se mide validación después de cada época.

Esta es una de las recetas más clásicas y más útiles para empezar con transfer learning.

25.25 Cuándo pasar de extractor de características a fine tuning

Una estrategia práctica frecuente es empezar entrenando solo la cabeza final. Si el resultado no alcanza o si el dataset lo permite, luego se puede descongelar parte del backbone y hacer fine tuning adicional.

Eso da un proceso más controlado y reduce el riesgo de desestabilizar el entrenamiento desde el principio.

25.26 Errores comunes en transfer learning

Algunos errores frecuentes son:

  • Olvidar reemplazar la capa final para el nuevo número de clases.
  • Congelar capas pero seguir pasando todos los parámetros al optimizador sin criterio.
  • No usar el tamaño de imagen esperado por el modelo.
  • Aplicar una tasa de aprendizaje demasiado alta al hacer fine tuning.
  • Suponer que todo modelo preentrenado funciona igual de bien en cualquier dominio.

25.27 Qué debes recordar de este tema

  • El transfer learning reutiliza conocimiento aprendido por modelos entrenados previamente.
  • En visión por computadora funciona muy bien porque muchas características visuales son transferibles.
  • Las estrategias principales son usar el modelo como extractor de características o hacer fine tuning.
  • Congelar capas evita modificar pesos del backbone preentrenado.
  • La capa final suele reemplazarse para adaptarla al nuevo número de clases.
  • Con datasets pequeños, el transfer learning suele ser una estrategia mucho más práctica que entrenar desde cero.

25.28 Conclusión

El transfer learning es una de las herramientas más valiosas en visión por computadora moderna porque permite aprovechar el enorme trabajo ya invertido en entrenar modelos sobre grandes colecciones de imágenes. En lugar de empezar siempre desde cero, podemos construir sobre representaciones ya aprendidas y adaptarlas a nuestros problemas concretos.

Su importancia es enorme no solo por eficiencia computacional, sino también porque hace posible obtener buenos resultados en escenarios donde los datos son limitados. Aprender a usarlo bien es una habilidad central para cualquier proyecto real de clasificación visual.

En el próximo tema profundizaremos justamente en el uso de modelos preentrenados, viendo con más detalle cómo cargarlos, adaptarlos y trabajar con ellos en PyTorch de forma práctica.