Transfer Learning — Pretrained Models & Fine-tuning
Modelos preentrenados, congelamiento de capas y fine-tuning
Transfer learning es la práctica de reutilizar un modelo entrenado en una tarea grande (ImageNet, corpus de texto masivo) como punto de partida para una tarea específica. En lugar de aprender desde cero, heredas las representaciones ya construidas. Es el equivalente a contratar a alguien con 10 años de experiencia en lugar de enseñarle todo desde cero.
Hay dos estrategias principales. En feature extraction congelás todas las capas del modelo base (sus pesos no se actualizan) y solo entrenás una cabeza nueva conectada al final. En fine-tuning descongelás algunas o todas las capas y ajustás el modelo completo con un learning rate muy bajo. Feature extraction es más rápido; fine-tuning produce mejores resultados cuando tienes suficientes datos.
Congelar capas significa poner requires_grad=False en sus parámetros. Si no lo hacés, el optimizador actualizará los pesos preentrenados junto con los nuevos, arruinando las representaciones aprendidas durante el preentrenamiento en pocas iteraciones.
El learning rate es crítico en fine-tuning. Las capas preentrenadas necesitan un LR muy bajo (1e-5 a 1e-4) para ajustarse suavemente sin olvidar lo que saben. La cabeza nueva puede usar un LR más alto (1e-3). Los optimizadores modernos permiten definir grupos de parámetros con distintos LR, técnica conocida como discriminative fine-tuning.
Los modelos de Hugging Face (BERT, ResNet, ViT, GPT-2) están disponibles con una API unificada. Cargar un modelo preentrenado, reemplazar la capa de clasificación y fine-tunear es el flujo estándar en NLP y visión computacional modernas.
El riesgo principal del transfer learning es el catastrophic forgetting: si el LR es demasiado alto o se entrenan demasiadas capas con pocos datos, el modelo olvida sus representaciones originales y performa peor que si se hubiera entrenado desde cero. El learning rate scheduling y el early stopping son la defensa habitual.
FEATURE EXTRACTION (all layers frozen)
model = models.resnet50(weights='IMAGENET1K_V2')
for param in model.parameters():
param.requires_grad = False # freeze all
model.fc = nn.Linear(model.fc.in_features, num_classes) # new head
optimizer = torch.optim.Adam(model.fc.parameters(), lr=1e-3)
FINE-TUNING (partial unfreeze)
model = models.resnet50(weights='IMAGENET1K_V2')
for param in model.parameters():
param.requires_grad = False # freeze all first
for param in model.layer4.parameters():
param.requires_grad = True # unfreeze last block
model.fc = nn.Linear(model.fc.in_features, num_classes)
optimizer = torch.optim.Adam([
{'params': model.layer4.parameters(), 'lr': 1e-4},
{'params': model.fc.parameters(), 'lr': 1e-3},
])
HUGGING FACE (NLP)
from transformers import AutoModel, AutoTokenizer
model = AutoModel.from_pretrained('bert-base-uncased')
tokenizer = AutoTokenizer.from_pretrained('bert-base-uncased')
# freeze encoder, train classification head only:
for param in model.parameters():
param.requires_grad = FalseDebugging lab
Detecta y corrige el error en el código.
- 3.4.5.1
model = models.resnet50(weights='IMAGENET1K_V2') model.fc = nn.Linear(model.fc.in_features, 10) optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
- 3.4.5.2
for param in model.parameters(): param.requires_grad = False model.fc = nn.Linear(512, 10) optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
- 3.4.5.3
# fine-tuning with same lr for all layers optimizer = torch.optim.Adam([ {'params': model.backbone.parameters(), 'lr': 1e-3}, {'params': model.head.parameters(), 'lr': 1e-3}, ])
- 3.4.5.4
model = AutoModel.from_pretrained('bert-base-uncased') for param in model.encoder.layer[:6].parameters(): param.requires_grad = True # want to freeze first 6 layers
- 3.4.5.5
# verifying trainable parameters trainable = sum(p.numel() for p in model.parameters()) print(f'Trainable params: {trainable}')