В рамках лабораторной работы были исследованы два подхода к решению задачи классификации изображений кошек и собак.
В первой части работы была разработана собственная сверточная нейронная сеть (CNN) для решения задач бинарной классификации («кошка или собака») и мультиклассовой классификации пород на датасете Pet Faces. Для повышения качества моделей был выполнен подбор гиперпараметров архитектуры и процесса обучения.
Во второй части работы был исследован подход Transfer Learning с использованием предобученных моделей VGG-16, VGG-19 и ResNet-50 на датасете Oxford Pets. Для выбора наилучшей конфигурации был реализован двухэтапный Grid Search, проведено сравнение архитектур, выполнен анализ качества классификации и интерпретация решений модели с помощью алгоритма Grad-CAM.
Для обеих задач были рассчитаны основные метрики качества, построены матрицы ошибок, выполнен анализ точности по отдельным классам и исследовано влияние различных гиперпараметров на качество классификации.
- Обучить свёрточную нейронную сеть для решения задачи определения кошки или собаки (бинарная классификация)
- Обучить свёрточную нейронную сеть для решения задачи определения породы кошки или собаки (мультиклассовая классификация)
- Посчитать точность классификаторов на тестовом датасете
- Построить confusion matrix и top-3 accuracy
- Выполнить оптимизацию гиперпараметров: архитектуры сети, learning rate, количества нейронов и размеров фильтров
- Количество изображений: 3211 (~15-30 изображений на каждый класс)
- Количество классов: 36 (13 пород кошек + 23 породы собак)
- Разделение данных на обучающий набор (80%) и тестовый набор (20%) методом Stratified Split (для сохоранения пропорции классов)
Для обоих наборов:
- Изменение размера до 128х128 пикселей
- Нормализация: ImageNet статистика (mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
Только для обучающего набора:
- Случайное горизонтальное отражение (вероятность 50%)
- Случайный поворот (±15 градусов)
- Случайное изменение яркости и контраста
- Случайное изменение оттенка и насыщенности
| Мультиклассовкая классификация | Бинарная классификация |
|---|---|
| Input: [batch_size, 3, 128, 128] ↓ [Сверточный блок 1] Conv → BatchNorm → ReLU → Conv → BatchNorm → ReLU → MaxPool → Dropout [64 фильтра] ↓ [Сверточный блок 2] Conv → BatchNorm → ReLU → → Conv → BatchNorm → ReLU → MaxPool → Dropout [128 фильтров] ↓ [Сверточный блок 3] Conv → BatchNorm → ReLU → → Conv → BatchNorm → ReLU → MaxPool → Dropout [256 фильтров] ↓ AdaptiveAvgPool2d(1, 1) → Flatten ↓ [Полносвязный слой 1] BatchNorm + ReLU + Dropout [512 нейрона] ↓ [Полносвязный слой 2] BatchNorm + ReLU + Dropout [256 нейрона] ↓ [Полносвязный слой 3] 32 нейрона (выходной слой) |
Input: [batch_size, 3, 128, 128] ↓ [Сверточный блок 1] Conv → BatchNorm → ReLU → Conv → BatchNorm → ReLU → MaxPool → Dropout [64 фильтра] ↓ [Сверточный блок 2] Conv → BatchNorm → ReLU → → Conv → BatchNorm → ReLU → MaxPool → Dropout [128 фильтров] ↓ [Сверточный блок 3] Conv → BatchNorm → ReLU → → Conv → BatchNorm → ReLU → MaxPool → Dropout [256 фильтров] ↓ AdaptiveAvgPool2d(1, 1) → Flatten ↓ [Полносвязный слой 1] BatchNorm + ReLU + Dropout [512 нейрона] ↓ [Полносвязный слой 2] BatchNorm + ReLU + Dropout [256 нейрона] ↓ [Полносвязный слой 3] 2 нейрона (выходной слой) |
Размер ядра свертки kernel size = 7 |
Размер ядра свертки kernel size = 7 |
| 6 507 363 параметра | 6 498 882 парамера |
- Прогрессивное увеличение количества фильтров
(32 → 64 → 128)позволяет модели извлекать всё более сложные визуальные признаки - Два сверточных слоя в каждом блоке повышают способность сети выделять устойчивые признаки изображения
Batch Normalizationстабилизирует обучение и позволяет использовать более высокие значенияlearning_rateReLUдобавляет нелинейность, благодаря чему модель может обучаться сложным зависимостям в данныхMaxPoolingуменьшает пространственный размер карт признаков и оставляет наиболее выраженные признакиDropoutслучайно отключает часть нейронов во время обучения, выполняя регуляризацию и снижая риск переобученияAdaptive Average Poolingпреобразует выход сверточных блоков к фиксированному размеру перед полносвязными слоями- Полносвязные слои выполняют финальную классификацию на основе извлечённых признаков
| Гиперпараметры | Мультиклассовая модель | Бинарная модель |
|---|---|---|
| Batch Size | 16 | 16 |
| Learning Rate | 0.0001 | 0.0003 |
| Optimizer | Adam weight decay = 0.001 |
Adam weight decay = 0 |
| Epochs | 100 | 75 |
| Early Stopping Rounds | 10 | 10 |
| Loss Function | CrossEntropyLoss | CrossEntropyLoss |
Optimizer Adam(адаптивное изменение learning rate для каждого параметра)Scheduler ReduceLROnPlateau(снижает learning rate в 0.5 раз, если test loss не улучшается 3 эпохи)- Early Stopping прерывает обучение при отсутствии улучшений на протяжении 10 эпох
- Процесс визуализируется с помощью динамического графика обучения и прогресс-бара
Ручной подбор гиперпараметров (а именно: количества фильтров в сверточных блоках (16, 32, 64) / (32, 64, 128), вероятности случайного отключения нейронов 0.2 / 0.5, размеров батча 16 / 32 / 64) позволил достичь точности моделям:
76.05%в задаче мультиклассовой классификации98.13%в задаче бинарной классификации
при использовании гиперпараметров num_filters_1, num_filters_2, num_filters_3 = (32, 64, 128), dropout_rate = 0.2, batch_size = 16
Для задачи мультиклассовой классификации было решено провести систематическую оптимизацию в двух этапах:
Протестировано 50 конфигурации с различными комбинациями:
| Гиперпараметр | Значения |
|---|---|
Размер батча batch size |
8, 16 |
| Архитектура | малая (16, 32, 64), базовая (32, 64, 128), большая (64, 128, 256) |
Размер ядера свертки kernel size |
3, 5, 7 |
Начальный коэффициент обучения learning rate |
0.0001, 0.0003, 0.0005 |
Вероятность случайного отключения нейронов dropout rate |
0.1, 0.2, 0.3 |
Коэффициент L2 регуляризации weight decay |
0, 1e-5, 1e-3 |
- Batch size 16 показал лучшие результаты
- Увеличенная архитектура (64, 128, 256) превосходит меньшие варианты
- Увеличение размера ядра (kernel size = 7) значительно улучшает качество
- Оптимальный learning rate: 0.0003-0.0005
- Dropout rate 0.1 - оптимален
- Weight decay 1e-3 дает лучшие результаты для batch size 16
Протестировано 46 конфигураций, сосредоточенные на лучших параметрах первого этапа.
- Фильтров в сверточных блоках: 64, 128, 256
- Нейронов в полносвязных слоях: 512 и 256
- Размер ядра свертки: 7
- Размер батча: 16
- Learning rate: 0.0001
- Dropout rate: 0.1
- Weight decay: 1e-3
Результат улучшенной мультиклассовой модели: 84.91% точность (улучшение на ~8% от исходной)
Результат улучшенной бинарной модели: 99.38 точность (улучшение на ~1% от исходной) с параметрами learning rate = 0.0003 weight decay = 0
| Метрика | Мультиклассовая классификация | Бинарная классификация |
|---|---|---|
| Точность (Accuracy) | 84.91% |
99.38 |
| Top-3 Accuracy | 92.42% |
- |
| Loss на тестовом наборе | 0.5421 | 0.0273 |
Средняя точность по классам: 83.93%
Только 3 ошибки на кошках (False Positive) и 1 ошибка на собаках (False Negative)
Весь проект реализован в одном Jupyter Notebook Faces.ipynb с полным пайплайном обучения и оценки моделей:
- Загружен датасета Pet Faces с 3211 изображениями разных пород
- Создан DataFrame с метаинформацией (путь к изображению, порода, тип животного) с помощью функции
create_breeds_df() - Проведен анализ распределения классов с помощью функции
plot_petfaces_distribution() - Создан класс датасета
PetFacesDataset, наследуемый отtorch.utils.data.Dataset - Созданы датасеты с обучающим (80% со случайными преобразованиями) и тестовым (20%) набором данных, пропорции классов при разделении сохранены
- Создан класс модели
PetCNNс трехблочной CNN (два сверточных слоя,Batch Normalization, активацияReLu,MaxPoolingиDropoutв каждом блоке), преобразованиемAdaptive Average Poolingи тремя полносвязными слоями - Реализована функция
train_model()- полный цикл обучения с ранней остановкой и прогресс-баром, использующая:- функцию
train_epoch()- обучение модели на одну эпоху с вычислением loss и accuracy - функцию
evaluate()- оценка модели на валидационном/тестовом наборе - функцию
calculate_top3_accuracy()- вычисление top-3 accuracy модели на тестовом наборе - функции
create_dynamic_fig()иupdate_dynamic_fig()- визуализация кривых loss и accuracy для каждой эпохи
- функцию
- Обучены предварительные модели с ручным подбором гиперпараметров:
- модель для мультиклассовой классификации с accuracy =
76.05%, top-3 accuracy =91.14% - модель для бинарной классификации с accuracy =
98.13%
- модель для мультиклассовой классификации с accuracy =
- Реализована функция
run_experiments()- подбор гиперпараметров из списка конфигураций - Подбор гиперпараметров проводился в две итерации, общее кол-во экспериментов -
96(>30 часов) - Обучены итоговые модели с лучшими выявленными гиперпараметрами:
- модель для мультиклассовой классификации с accuracy =
84.91%, top-3 accuracy =92.42% - модель для бинарной классификации с accuracy =
99.38
- модель для мультиклассовой классификации с accuracy =
- Реализованы функции визуализации:
plot_training_curves()- графики loss и accuracy во время обученияplot_confusion_matrix()- матрица ошибок классификации confusion matrixvisualize_predictions()- примеры предсказаний модели на тестовом набореplot_class_accuracies()- анализ точности по отдельным классам
- Результаты визуализированы и проанализированы
- Transfer Learning: - использование предобученных моделей (ResNet, EfficientNet, VGG-16/19)
- Более агрессивная аугментация: - использование техник MixUp, CutMix, AutoAugment
- Увеличение архитектуры: - более глубокие и широкие сети
- Балансировка классов: - увеличение штрафа за ошибки на редких или плохо распознаваемых классах с помощью весов в функции потерь
- Обучить три классификатора пород кошек и собак: на основе VGG-16/19 и на основе ResNet.
- Посчитать точность классификатора на тестовом датасете отдельно для каждого из классификаторов, для дальнейших действий выбрать сеть с лучшей точностью
- Посчитать точность двоичной классификации "кошки против собак" такой сетью на тестовом датасете
- Построить confusion matrix, top-3 и top-5 accuracy
- Выполнить визуализацию зон интереса, на которые "смотрит" нейросеть при определении тех или иных классов, с помощью алгоритма GradCam
- Количество изображений: ~7400 изображений (~5000 кошек, 2400 собак)
- Количество классов: 37 пород (12 пород кошек + 25 породы собак)
- Разделение данных: на обучающий набор (80%) и тестовый набор (20%) методом Stratified Split (для сохоранения пропорции классов)
- Изменение размера до 224×224 пикселей
- Нормализация: ImageNet статистика (mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
- Случайное горизонтальное отражение (вероятность 50%)
- Случайный поворот (±15 градусов)
- Случайное изменение яркости и контраста
- Случайное изменение оттенка и насыщенности
Использован подход Transfer Learning с предобученными моделями (ImageNet). Каждая модель обучалась в двух этапах:
- Сохранены веса сверточных слоев предобученной сети (ImageNet)
- Обучены только новые полносвязные слои для адаптации моделей к классификации 36 пород
- Разморожены последние слои сверточной сети в определенные эпохи
- Использован меньший learning rate (0.0001 vs 0.001)
| VGG-16 | VGG-19 | ResNet-50 | |
|---|---|---|---|
| Архитектура | 16 слоев (13 сверточных + 3 полносвязных) | 19 слоев (16 сверточных + 3 полносвязных) | 50 слоев с остаточными связями (residual connections) |
| Полносвязные слои | 4096 → 4096 → 1000 (ImageNet) → FC(37 классов) | 4096 → 4096 → 1000 (ImageNet) → FC(37 классов) | AdaptiveAvgPool → FC(256) + Dropout(0.5) → FC(128) + Dropout(0.5) → FC(37 классов) |
| Параметры | ~138 млн | ~144 млн | ~25 млн |
| Особенности | Малые фильтры 3×3, простая и интерпретируемая архитектура | Более глубокая версия VGG-16 | Остаточные блоки позволяют обучать глубокие сети без проблемы vanishing gradient |
Общий паттерн для новых классификационных голов:
Input: [batch_size, feature_dim]
↓
Linear(feature_dim → fc1_size)
BatchNorm + ReLU + Dropout(p)
↓
Linear(fc1_size → fc2_size)
BatchNorm + ReLU + Dropout(p)
↓
Linear(fc2_size → 37) [выход для 37 пород]
Проведена систематическая оптимизация гиперпараметров для всех трех моделей с использованием Grid Search в два этапа:
| Гиперпараметр | Значения |
|---|---|
| Модель | VGG-16, VGG-19, ResNet-50 |
| Размеры FC слоев | (256, 128), (512, 256) |
Dropout rate |
0.5 |
Dropout decay |
0.3, 0.5 |
Learning Rate |
0.0001 |
Размер батча batch size |
16 |
| Количество эпох | 15 |
| Стратегия разморозки | Различные эпохи и количество слоев для каждой архитектуры |
| Общее количество конфигураций | 36 комбинаций |
| Затраченное время на обучение | ~640 мин |
- Уменьшенная архитектура (256, 128) превосходит увеличенный вариант
- Оптимальные значения
Dropout rateиDropout decay- 0.5 - Для каждой модели удалось получить лучшую стратегию разморозки слоев
| Гиперпараметр | Значения |
|---|---|
| Модель | VGG-16, VGG-19, ResNet-50 |
| Размеры FC слоев | (256, 128) |
Dropout rate |
0.5 |
Dropout decay |
0.5 |
Learning Rate |
0.0001, 0.00005, 0.00001 |
Размер батча batch size |
16 |
| Количество эпох | 30 |
| Стратегия разморозки | Различные эпохи и количество слоев для каждой архитектуры |
| Общее количество конфигураций | 18 комбинаций |
| Затраченное время на обучение | ~580 мин |
- Модель ResNet50 показала наилучшие результаты по итогам обучения, вне зависимости от выбранного
learning rate - Для модели ResNet50 лучшее значение
learning rate- 0.0001 - Выбрана лучшая стратегия разморозки (2 слоя на 5 эпохе 4 слоя на 10 эпохе)
Гиперпараметры выбраны в соответствии с лучшей конфигурацией по итогам Grid Search
| Гиперпараметры | Значение |
|---|---|
| Размер Батча | 16 |
| Нейронов в полносвязных слоях | 256 и 128 |
| Optimizer | Adam |
| Loss Function | CrossEntropyLoss |
Learning Rate |
0.0001 |
Dropout rate и dropout decay |
0.5 |
| Количество эпох | 50 |
| Early Stopping Rounds | 7 |
| Стратегия разморозки | на эпохах 5 (2 слоя) и 10 (4 слоя) |
- Эпохи 1-5: Обучение только новых полносвязных слоев
- Эпохи 5-10: Разморозка 2 последних сверточных слоев
- Эпохи 10-30: Разморозка 4 последних сверточных слоев
- Early Stopping: Останавливает обучение если loss не улучшается 7 эпох
| Метрика | ResNet-50 |
|---|---|
| Accuracy | 93.23% |
| Top-3 Accuracy | 99.12% |
| Top-5 Accuracy | 99.59% |
| Loss на тестовом наборе | 0.2105 |
| Метрика | Значение |
|---|---|
| Accuracy | 99.46% |
| Precision (cats) | 98.6% |
| Recall (cats) | 99.8% |
| f1-score (cats) | 99.2% |
| Precision (dogs) | 99.9% |
| Recall (dogs) | 99.3% |
| f1-score (dogs) | 99.6% |
GradCAM (Gradient-weighted Class Activation Mapping) - это метод для интерпретации решений сверточных нейронных сетей, позволяющий визуализировать области входного изображения, которые оказали наибольшее влияние на предсказание модели для конкретного класса.
Принцип работы Grad-CAM основан на анализе активаций последнего сверточного слоя и соответствующих им градиентов. В процессе прямого прохода через сеть сохраняются карты признаков выбранного сверточного слоя. Затем выполняется обратное распространение ошибки для интересующего класса, что позволяет получить градиенты по отношению к этим признакам. Усредненные значения градиентов используются как веса важности отдельных каналов карты признаков.
После вычисления весов формируется итоговая карта активации путем взвешенного суммирования всех каналов признаков. К полученной карте применяется функция ReLU, позволяющая оставить только положительный вклад признаков в предсказание класса. Далее карта нормализуется и масштабируется до размеров исходного изображения.
Использование Grad-CAM позволяет решить две основные задачи:
- проверить, действительно ли модель опирается на содержательные объекты изображения, а не на случайные артефакты
- повысить интерпретируемость результатов работы нейронной сети
Весь проект реализован в одном Jupyter Notebook Pets.ipynb с полным пайплайном обучения и оценки моделей:
- Загружен датасета Oxford Pets с ~7400 изображениями разных пород
- Создан DataFrame с метаинформацией (путь к изображению, порода, тип животного)
- Проведен анализ распределения классов
- Создан класс датасета
PetFacesDataset, наследуемый отtorch.utils.data.Dataset - Созданы датасеты с обучающим (80% со случайными преобразованиями) и тестовым (20%) набором данных, пропорции классов при разделении сохранены
- Создан класс модели
TransferLearningModel, реализующий подход Transfer Learning:- использует предобученные сверточные сети (VGG, ResNet)
- заменяет классификационный блок на свой с гибкой конфигурацией
- поддерживает замораживание и постепенное размораживание слоев предобученной сети для выполнения fine-tuning
- Реализована функция
grid_search_hyperparameters()- перебор комбинаций гиперпараметров методом Grid Search с целью поиска наилучшей, использует модифицированную под Transfer Learning функциюtrain_model()и другие раннее реализованные функции для обучения моделей - Дополнительно реализована функция функция
calculate_top5_accuracy()- вычисление top-5 accuracy модели на тестовом наборе - Для подбора стратегии расморозки предобученных слоев реализована функция
analyze_model_architecture()- вывод структуры сети, количества параметров и информации о замороженных и обучаемых слоях - Реализована функция
plot_grid_search_curves()для дополнительного анализа результатов Grid Search - Для подбора оптимальных гиперпараметров был реализован двухэтапный Grid Search, в рамках которого протестировано 54 конфигурации моделей с тремя архитектурами (VGG-16, VGG-19, ResNet-50) с различными размерами полносвязных слоев, стратегиями разморозки сверточных слоев и значениями learning rate
- Обучена итоговая модель на архитектуре ResNet-50, продемонстрировавшая следующие результаты:
- Accuracy для классификации 37 пород:
93.23% - Top-3 Accuracy:
99.12% - Top-5 Accuracy:
99.59% - Loss на тестовом наборе:
0.2105
- Accuracy для классификации 37 пород:
- Для задачи бинарной классификации «cats vs dogs» получены следующие результаты:
- Accuracy:
99.46% - Precision для класса «cat»:
98.6% - Recall для класса «cat»:
99.8% - Precision для класса «dog»:
99.9% - Recall для класса «dog»:
99.3%
- Accuracy:
- Построены confusion matrix с помощью ранее реализованной функции
plot_confusion_matrix() - Произведен анализ точности по отдельным классам с помощью ранее реализованной функции
plot_class_accuracies() - Выведены примеры предсказаний модели с помощью ранее реализованной функции
visualize_predictions() - Для интерпретации решений нейронной сети реализован алгоритм Grad-CAM:
- создан класс
GradCAM, выполняющий сохранение активаций и градиентов выбранного сверточного слоя - реализована функция
generate_cam()- построение карт активации классов - реализована функция
visualize_gradcam()- визуализация областей изображения, оказывающих наибольшее влияние на предсказание модели
- создан класс
Использование Transfer Learning значительно ускорило обучение (по сравнению с обучением с нулевых весов) и позволило достичь высокой точности даже с относительно ограниченным набором данных.
Результаты анализа матрицы ошибок показали, что большинство ошибок возникает между визуально похожими породами животных, тогда как различие между кошками и собаками определяется моделью практически безошибочно.
Визуализация Grad-CAM подтвердила корректность работы модели. Наибольшее внимание сеть уделяет морде животного, области глаз, форме ушей и особенностям окраса шерсти, что соответствует признакам, используемым человеком при определении породы.
Полученные результаты демонстрируют высокую эффективность использования Transfer Learning для задач классификации изображений и подтверждают целесообразность применения предобученных моделей при ограниченном объеме обучающих данных.
- Более тонкая настройка разморозки предобученных сверточных слоев в процессе дообучения
- Ансамбли моделей - комбинирование предсказаний всех трех архитектур
- Более глубокие модели - EfficientNet, DenseNet, Vision Transformer
- Балансировка классов - учет дисбаланса в частоте пород с помощью weighted loss
- Увеличение датасета - сбор дополнительных данных или синтез новых изображений
Собственная сверточная нейронная сеть показала хорошие результаты на датасете Pet Faces, достигнув точности 84.91% в задаче классификации пород и 99.38% в задаче бинарной классификации.
Использование Transfer Learning позволило существенно повысить качество классификации. Лучшая модель ResNet-50 достигла точности 93.23% при определении пород и 99.46% в задаче бинарной классификации.
Полученные результаты подтверждают преимущество использования предобученных моделей при решении задач компьютерного зрения на относительно небольших наборах данных.
| Инструмент | Назначение в работе |
|---|---|
PyTorch |
Построение и обучение нейронных сетей Не смог использовать keras, т.к. не смог подключить GPU |
Torchvision |
Предобученные модели (VGG, ResNet) и трансформация изображений |
NumPy и Pandas |
Обработка данных и вычисления |
Scikit-learn |
Метрики (accuracy, confusion matrix) и stratified split |
Matplotlib и Seaborn |
Визуализация результатов |
Grid Search |
Систематическая оптимизация гиперпараметров |
Transfer Learning |
Использование предобученных моделей |
GradCAM |
Интерпретация решений нейросети |










