Почему ResNet18 переобучается: точность 97% на обучении против 77% на валидации
При обучении нейросети ResNet18 для классификации 6 видов животных по следам вы столкнулись с типичной проблемой глубокого обучения: отличные показатели на тренировочной выборке (97% accuracy) и скромные 77% на валидации. Разрыв в 20% говорит о переобучении - модель запомнила шумы и детали обучающих фото, вместо того чтобы выделять общие признаки следа. Рассмотрим причины и способы решения.
Почему возникает переобучение на ResNet18?
Исходная архитектура ResNet18 предобучена на ImageNet (1,2 млн изображений), а ваш датасет - всего 3000 снимков следов. Модель слишком мощная для такого объёма данных: полносвязный слой из 256 нейронов добавляет более 2 млн параметров, которые легко запоминают выборку. Оптимизатор Adam с lr=1e-3 и 20 эпох усиливает эффект - градиенты быстро сходятся к локальному минимуму на обучающих данных, не обобщаясь на новые примеры.
5 шагов для уменьшения переобучения и повышения macro F1
1. Усилите аугментацию данных
Текущие аугментации (RandomResizedCrop, HorizontalFlip, Rotation, ColorJitter) - хороший старт, но для следов животных этого мало. Добавьте:
- RandomGrayscale(0.1) - имитация разной освещённости
- GaussianBlur(kernel_size=(3,3), sigma=(0.1, 1.0)) - смазывание от движения
- RandomPerspective(distortion_scale=0.2, p=0.3) - искажение перспективы
Это заставит сеть учиться по форме и текстуре следа, а не по цвету или чёткости краёв.
2. Уменьшите сложность головы модели
Замените два полносвязных слоя (256 → 6) на один слой с Dropout. Пример:
model_ft.fc = nn.Sequential(
nn.Dropout(0.5),
nn.Linear(num_ftrs, num_classes)
)Dropout 0.5 отключает половину нейронов случайным образом - это один из самых эффективных методов борьбы с переобучением.
3. Используте L2-регуляризацию (weight decay)
В оптимизатор Adam добавьте weight_decay=1e-4 или 1e-5. Это штрафует большие веса и не даёт модели подстраиваться под шум:
optimizer = torch.optim.Adam(model_ft.parameters(), lr=1e-3, weight_decay=1e-4)4. Настройте learning rate и early stopping
Уменьшите learning rate до 1e-4 и добавьте планировщик ReduceLROnPlateau - он снижает lr в 2 раза, если валидационная loss перестаёт падать. Также используйте EarlyStopping (терпение 3-5 эпох) - обучение остановится, когда метрики на валидации не улучшаются.
5. Примените fine-tuning с заморозкой первых слоёв
Заморозьте первые 6-7 блоков ResNet18 (слои, отвечающие за базовые признаки вроде краёв и текстур) и дообучайте только последние 3-4 блока + голову. Это уменьшит количество обучаемых параметров и сохранит общие представления из ImageNet. Пример:
for name, param in model_ft.named_parameters():
if 'layer4' not in name and 'fc' not in name:
param.requires_grad = FalseДополнительные советы для классификации следов
Попробуйте более лёгкую архитектуру - например, MobileNetV3-Small или EfficientNet-B0. Они имеют меньше параметров и менее склонны к переобучению на маленьких датасетах. Также проверьте разметку: возможно, в валидации есть классы с малым числом примеров (дисбаланс), из-за чего macro F1 занижен. Используйте weighted sampler для балансировки батчей.
После внедрения этих методов ожидайте повышение macro F1 до 85-88% при сохранении accuracy на обучении на уровне 90-92% - здоровый разрыв в 5-10% считается нормальным для задач с 3000 изображений.