0.78 при 50к сэмплов на 12 классов и ResNet50 - скорее всего проблема в данных, а не в архитектуре.
По порядку:
Аугментации. Если используешь только стандартные flip/rotate, попробуй agressive pipeline. albumentations с CutOut, MixUp, CutMix. MixUp один давал мне +3-5% на похожих задачах. Код примерно такой:
def mixup_data(x, y, alpha=0.2):
lam = np.random.beta(alpha, alpha)
batch_size = x.size(0)
index = torch.randperm(batch_size).to(x.device)
mixed_x = lam * x + (1 - lam) * x[index]
y_a, y_b = y, y[index]
return mixed_x, y_a, y_b, lam
Learning rate. 1e-4 для файнтюна нормально, но попробуй дифференцированный lr. Первые слои (feature extractor) заморозь или дай им lr=1e-6, а classifier head - lr=1e-3. В PyTorch это делается через param_groups в оптимизаторе.
Label smoothing. Вместо hard targets (0 и 1) сглаживай до 0.05-0.1. CrossEntropyLoss в PyTorch поддерживает это из коробки: nn.CrossEntropyLoss(label_smoothing=0.1). Дешевый способ регуляризации, почти всегда помогает.
Разбалансировка классов. 50к на 12 классов, но сколько в каждом? Если есть перекос 10:1, weighted sampling или focal loss могут дать заметный буст.
Архитектура. ResNet50 для 50к изображений может быть избыточна. Попробуй EfficientNet-B2 или ConvNeXt-Tiny, они дают сравнимое качество при меньшем количестве параметров, что снижает склонность к переобучению.
Если после всех манипуляций потолок не сдвинется, значит проблема в самих данных. Шумные метки, дубликаты между train/val, неконсистентная разметка.
Попробовал MixUp + label smoothing 0.1 + дифференцированный lr. Val accuracy скакнула до 0.84 за 30 эпох. Огромное спасибо, буду дальше ковырять аугментации