Meta-Learning for Visual Recognition with Limited Data
Module: Computer Vision | Difficulty: Premium
Prototypical Network
where .
MAML Update
Episodic Training
Each episode: sample -way -shot task from meta-train set.
| Method | 5-way 1-shot | 5-way 5-shot | Architecture | |--------|-------------|-------------|--------------| | MAML | 48.7% | 63.1% | Any | | ProtoNet | 49.4% | 68.2% | Embedding | | MatchingNet | 43.6% | 55.3% | Embedding | | FEAT | 64.2% | 79.2% | Transformer | | TIM | 66.5% | 81.8% | Transformer |
import torch
import torch.nn as nn
import torch.nn.functional as F
class PrototypicalNetwork(nn.Module):
def __init__(self, backbone, distance='cosine'):
super().__init__()
self.backbone = backbone
self.distance = distance
def forward(self, support_images, support_labels,
query_images, n_way):
z_support = self.backbone(support_images)
z_query = self.backbone(query_images)
prototypes = []
for k in range(n_way):
mask = support_labels == k
prototypes.append(z_support[mask].mean(dim=0))
prototypes = torch.stack(prototypes)
if self.distance == 'cosine':
z_query = F.normalize(z_query, dim=1)
prototypes = F.normalize(prototypes, dim=1)
dists = -torch.mm(z_query, prototypes.t())
else:
dists = torch.cdist(z_query, prototypes)
return F.log_softmax(-dists, dim=1)
class MAML:
def __init__(self, model, inner_lr=0.01,
outer_lr=0.001, inner_steps=5):
self.model = model
self.inner_lr = inner_lr
self.optimizer = torch.optim.Adam(
model.parameters(), lr=outer_lr)
self.inner_steps = inner_steps
def inner_loop(self, support_x, support_y):
fast_weights = dict(self.model.named_parameters())
for _ in range(self.inner_steps):
logits = self.model.functional_forward(
support_x, fast_weights)
loss = F.cross_entropy(logits, support_y)
grads = torch.autograd.grad(
loss, fast_weights.values(), create_graph=True)
fast_weights = {
k: v - self.inner_lr * g
for (k, v), g in zip(fast_weights.items(), grads)}
return fast_weights
def outer_step(self, tasks):
meta_loss = 0
for support_x, support_y, query_x, query_y in tasks:
fast_weights = self.inner_loop(support_x, support_y)
query_logits = self.model.functional_forward(
query_x, fast_weights)
meta_loss += F.cross_entropy(query_logits, query_y)
meta_loss /= len(tasks)
self.optimizer.zero_grad()
meta_loss.backward()
self.optimizer.step()
return meta_loss.item()
Research Insight: Few-shot learning has evolved from meta-learning approaches (MAML, Prototypical Networks) to prompt-based approaches using foundation models. With CLIP and DINOv2, simple prompt engineering or linear probing on frozen features often outperforms complex meta-learning algorithms. The key insight is that large-scale pretraining provides implicit meta-learning: the model has already learned to extract generalizable features from diverse data. Future few-shot learning will likely focus on efficient adaptation of these foundation models rather than training from scratch.