КурсоваяМашинное обучениеГод: 2025ВИВТ: Воронежский институт высоких технологий
👁 16💼 0

Готовая курсовая: Разработка CNN для распознавания MNIST

Загружена: 19.02.2026 09:05

Распознавание рукописных цифр с использованием сверточной нейросети на наборе MNIST. Описаны предобработка (нормализация, стратифицированная разбивка), архитектура CNN (Conv2D, MaxPooling, Dense), обучение и сравнение экспериментов (Dropout, аугментация). Полезно для освоения практических навыков в CV и быстрого развёртывания базовых моделей.

Содержание

Введение	3
Обзор предметной области искусственного интеллекта	3
Цель работы и постановка задачи	3
1.	Аналитический раздел	5
1.1.	Анализ исходных данных	5
1.1.1.	Сбор и предварительная обработка данных	5
1.1.2.	Разбиение данных на обучающую и тестовую выборки	6
1.1.3.	Анализ характеристик исходных данных	8
1.2.	Выбор алгоритмов и моделей машинного обучения	9
1.2.1.	Обзор основных алгоритмов	9
1.2.2.	Обоснование выбора модели	12
2.	Проектирование и реализация программного решения	13
2.1.	Описание архитектуры программного решения	13
2.2.	Реализация выбранных алгоритмов и моделей в выбранном программном окружении	14
3.	Эксперименты и результаты	16
3.1.	Описание проведенных экспериментов	16
3.2.	Анализ и интерпретация полученных результатов	19
3.3.	Оценка и сравнение методов	19
Заключение	21
Подведение итогов	21
Выводы и рекомендации по улучшению результатов исследования	21
Список использованных источников	23
Приложения	24
Приложение 1	24

Введение

Обзор предметной области искусственного интеллекта
Искусственный интеллект (ИИ) – обширная область информатики, которая направлена на создание систем, выполняющих сложные задачи, для решения которых требуется человеческий интеллект. Этими задачами являются:
Распознавание речи и изображений;
Принятие решений;
Прогнозирование;
Обучение на основе данных.
Современные системы ИИ используют алгоритмы машинного обучения и нейронные сети.
Одной из самых распространенных демонстраций возможностей ИИ является решение задач по распознаванию образов (например, рукописных символов). Для этого применяются специализированные нейронные сети. Они обеспечивают высокую точность и надежность распознавания.
Цель работы и постановка задачи
Целью текущей курсовой работы является разработка и реализация решения для распознавания рукописных цифр на основе нейронной сети. Задача решается с применением языка программирования Python и современных библиотек машинного обучения.
Необходимо обучить нейросеть на наборе данных MNIST и оценить ее эффективность, решив в ходе выполнения работы следующие задачи:
Постановка задачи: формулировка, параметризация, требования к исходным данным и результату работы алгоритма;
Выбор модели нейросети. Архитектурное моделирование, проектирование, математическое описание;
Подготовка исходных данных;
Разработка;
Обучение, верификация, контрольный пример работы модели.
Аналитический раздел
Анализ исходных данных
Сбор и предварительная обработка данных
В рамках исследования будет использоваться классический набор данных MNIST, в котором собраны изображения рукописных цифр от 0 до 9. В нем каждый элемент набора – это изображение размером 28 × 28 пикселей в градациях серого.
Обучающая выборка набора содержит 60 000 изображений (рисунок 1), а тестовая выборка – 10 000 изображений.
Рисунок 1 – Пример изображений из набора MNIST
Для загрузки данных воспользуемся кодом ниже.
from tensorflow.keras.datasets import mnist
# Загрузка данных
(x_train, y_train), (x_test, y_test) = mnist.load_data()
Разбиение данных на обучающую и тестовую выборки
Поскольку набор данных MNIST уже разделен на обучающую и тестовую выборки, необходимости выполнять разделение нет.
Однако, мы можем выделить валидационную выборку из обучающей выборки, которая нужна для подбора гиперпараметров разрабатываемой нейросети (число слоев, скорость обучения, количество нейронов в слое и т.п.) и оценки качества на «невидимых» данных до выполнения финального теста модели.
Код для выделения валидационной выборки:
from sklearn.model_selection import train_test_split
# Дополнительная разбивка: 10% от train → validation
x_train, x_val, y_train, y_val = train_test_split(
x_train, y_train,
test_size=0.1,
random_state=42,
stratify=y_train)
Для того, чтобы во всех выборках распределение цифр (классов) было приблизительно одинаковым (параметр stratify=y_train). Это особенно важно при неравномерных классах.
Также мы фиксируем параметр random_state=42, чтобы при повторении экспериментов получать детерминированные результаты.
На рисунке 2 представлены гистограммы количества примеров каждого класса в выборках.
Рисунок 2 – Количество примеров в выборках
Анализ характеристик исходных данных
Как было указано ранее, элементы выборки представляют собой изображения 28 × 28 пикселей в градациях серого. Метки (т.е. цифры 0-9) заданы целыми числами. Это поможет выяснить код, приведенный ниже.
# Проверяем форму массивов и тип данных
print("x_train shape:", x_train.shape)
print("y_train shape:", y_train.shape)
print("x_test  shape:", x_test.shape)
print("y_test  shape:", y_test.shape)
print("x_train dtype:", x_train.dtype)
print("y_train dtype:", y_train.dtype)
Проверим наличие пропусков в данных:
import numpy as np
print("Пропуски в x_train:", np.isnan(x_train).sum())
print("Пропуски в y_train:", np.isnan(y_train).sum())
Для того, чтобы картинка стала понятным, структурированным массивом численных признаков, подаваемый на вход нейросети, проанализируем распределение пиксельных значений:
# Срезаем первые 1000 изображений для ускорения вычислений
sample = x_train[:1000].reshape(-1)
print("Мин. значение пикселя:", sample.min())    # 0
print("Макс. значение пикселя:", sample.max())    # 255
print("Среднее до нормализации:", sample.mean())  # ≈33.5
print("Std до нормализации:", sample.std())       # ≈78.6
Перед проведением нормализации (следующий шаг подготовки данных) диапазон пикселей – [0, 255], а среднее значение ≈ 33,5 и стандартное отклонение ≈ 78,6. Это позволяет оценить эффективность проведения нормализации путем простого деления на 255.
Полученное значение среднего говорит нам, что большинство пикселей элементов набора – темные (фон) и только небольшая часть (чернила) – светлые (более яркие). В таком случае, можем нормализовать данные делением на 255 для получения «близко» распределенных данных и ускорения сходимости обучения. Высокое стандартное отклонение (≈ 78,6) показывает, что яркие пиксели сильно отличаются от темных. Для нас это значит, что изображения высоко контрастные и будет несложно определить написанную цифру.
Нормализуем данные, приведя пиксели к диапазону [0, 1]:
x_train = x_train.astype('float32') / 255.0
x_test  = x_test.astype('float32')  / 255.0
Выбор алгоритмов и моделей машинного обучения
Обзор основных алгоритмов
При решении задач распознавания изображений применяются различные варианты машинного обучения, но наиболее эффективными считаются нейросети. Они могут быть следующих типов (основных):
Полносвязные нейронные сети (FCNN). Состоят из последовательности слоев, где каждый нейрон текущего слоя соединен со всеми нейронами следующего слоя. Линейное преобразование входных данных происходит в каждом нейроне. Применяется нелинейная функция активации (ReLU, сигмоида).
В таких нейросетях изображение представляется вектором признаков. В нашем случае это будет вектор из 784 элементов (28 × 28 пикселей).
Такие сети просты в реализации и имеют понятную архитектуру.
Недостатками полносвязных сетей считается высокая размерность весов (каждый входной признак требует отдельный вес и это приводит к очень большому числу параметров, и, как следствие, переобучению). Эти сети плохо масштабируются поскольку увеличение размера изображения резко увеличит число параметров сети. Также, свертывание изображения в вектор уничтожает информацию о расположении пикселей относительно друг друга.
Таким образом, полносвязные сети могут применяться для очень простых и маленьких изображений, но при работе с реальными изображениями они сильно уступают специализированным архитектурам.
Сверточные нейронные сети (CNN). Разработаны специально для обработки двумерных данных (изображений). В них используются сверточные и подвыборочные слои, которые эффективно извлекают локальные признаки.
Здесь каждый нейрон связан с небольшой областью предыдущего слоя (рецептивное поле). Это дает возможность учитывать локальные особенности изображения (текстуры, края, углы).
Используются общие веса, называемые сверточными фильтрами. Один фильтр используется для разных частей изображения. Это сильно снижает число параметров по сравнению с FCNN.
Первые слои сети выявляют простые признаки (линии, границы), последующие слои – сложные структуры (части объектов, формы). Т.е. реализуется иерархия признаков.
Происходит снижение размерности признаков в слоях подвыборки, что повышает эффективность вычислений и снижает переобучение сети.
Стандартно в CNN применяются следующие компоненты:
Сверточные слои (Conv2D). Применяют набор фильтров к изображению;
Функции активации. Обычно ReLU;
Слои подвыборки (MaxPooling2D). Уменьшают размер карты признаков;
Полносвязные слои (Dense). Для классификации (на последних этапах);
Sftmax-функция на выходе. Для многоклассовой классификации.
Преимуществами CNN является сохранение пространственных зависимостей между пикселями, меньшее количество параметров, высокая точность в задачах компьютерного зрения (CV), способность к обобщению на новых данных.
Фактически CNN – стандарт для задач распознавания изображений благодаря своей высокой эффективности, способности к извлечению сложных признаков и низкому риску переобучения.
На рисунке 3 продемонстрирована структура FCNN и CNN.
Рисунок 3 – Структура FCNN и CNN
Обоснование выбора модели
В таблице 1 приведено сравнение описанных нейросетей.
Таблица 1
Сравнение FCNN и CNN
Исходя из таблицы 1 выбрана сверточная нейронная сеть (CNN), т.к. она лучше обрабатывает изображения благодаря выделению пространственных признаков.
Проектирование и реализация программного решения
Описание архитектуры программного решения
Реализуем архитектуру (рисунок 4) с помощью фреймворка TensorFlow/Keras. Она будет включать следующие элементы:
Входной слой. Форма входа (28, 28, 1) - 28×28 пикселей, 1 канал (градации серого). Изображения предварительно нормализованы и приведены к нужной размерности;
Первый сверточный слой – 32 фильтра размерностью (3, 3), ReLU. Извлекает базовые признаки изображения за счет применения 32 различных сверточных фильтров;
Первый слой подвыборки с размерностью окна (2, 2). Снижает размерность карт признаков выбором максимального значения из каждой области 2 × 2 для уменьшения вычислительной нагрузки и обеспечения чувствительности модели к небольшим сдвигам изображения;
Второй сверточный слой;
Уплощение признаков (Flatten). Преобразует выходной тензор из двумерной формы в одномерный вектор для подачи в полносвязный слой;
Полносвязный слой (Dense) – 128 нейронов, ReLU. Объединяет признаки и выявляет сложные зависимости между ними для последующей классификации;
Выходной слой (Dense) – 10 нейронов (по 1 на каждуй цифру от 0 до 9), Softmax. Генерирует вероятностное распределение по классам.
Рисунок 4 – Архитектура сети
Реализация выбранных алгоритмов и моделей в выбранном программном окружении
Реализация архитектуры в коде:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
model = Sequential([
Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
MaxPooling2D(pool_size=(2, 2)),
Flatten(),
Dense(128, activation='relu'),
Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
Здесь импортируются модули:
Sequential – реализует базовый способ создания нейронной сети, где слои идут последовательно друг за другом;
Conv2D – сверточный слой для выделения локальных признаков изображения;
MaxPooling2D – слой подвыборки, уменьшает размерность признаков;
Flatten – слой преобразования многомерного массива признаков в одномерный вектор;
Dense – полносвязный слой.
После построения модели компилируем ее. При этом используется оптимизатор Adam (эффективный алгоритм оптимизации), функция потерь для задачи многоклассовой классификации (для оценки расхождения между предсказанными вероятностями и истинными метками), для отслеживания указана метрика accuracy, по которой будет оцениваться качество обучения модели (показывает долю правильных предсказаний).
Эксперименты и результаты
Описание проведенных экспериментов
Эксперименты проводились на инфраструктуре Google Colab, который предоставляет вычислительные мощности для разработки моделей машинного обучения.
Общие параметры модели при запуске экспериментов:
batch_size  = 128
epochs      = 15
optimizer   = 'adam'            # learning_rate по умолчанию 0.001
loss        = 'sparse_categorical_crossentropy'
metrics     = ['accuracy']
validation_split = 0.1          # 10% обучающей выборки на валидацию
shuffle     = True
random_state= 42
Колбэки:
EarlyStopping(
monitor='val_loss',        # метрика, за которой следим
patience=3,                # число эпох без улучшения, после которого останавливаемся
restore_best_weights=True  # после остановки вернуть веса из лучшей эпохи
)
ModelCheckpoint(
'best_model.h5',           # файл для сохранения
monitor='val_accuracy',    # метрика, за которой следим
save_best_only=True        # сохранять только если метрика улучшилась
)
Колбэки в Keras – специальные объекты, вызываемые во время обучения. Позволяют подключаться к процессу обучения на разных этапах и помогают управлять обучением и сохранять лучшие версии модели.
Они позволяют экономить время и ресурсы – обучение не будет длиться все 50 эпох, например, а остановится, когда обучение станет бесполезным. Это, также, позволяет избежать переобучения.
Благодаря параметрам restore_best_weights=True и save_best_only=True мы получаем веса модели, при которых было достигнуто оптимальное качество модели.
Проведены следующие эксперименты:
Получение эталонного качества на базовой CNN без регуляции и аугументации. Код:
history_base = model.fit(
x_train, y_train,
batch_size=batch_size,
epochs=epochs,
validation_split=validation_split,
shuffle=shuffle,
callbacks=[early_stopping, model_checkpoint]
)
Добавление Dropout. Проверяем, улучшает ли регуляризация (Dropout) обобщающую способность.
Модифицируем модель:
from tensorflow.keras.layers import Dropout
model_dropout = Sequential([
Conv2D(32, (3,3), activation='relu', input_shape=(28,28,1)),
MaxPooling2D((2,2)),
Flatten(),
Dense(128, activation='relu'),
Dropout(0.5),               # новый слой
Dense(10, activation='softmax')
])
model_dropout.compile(optimizer=optimizer, loss=loss, metrics=metrics)
Код:
history_do = model_dropout.fit(
x_train, y_train,
batch_size=batch_size,
epochs=epochs,
validation_split=validation_split,
callbacks=[early_stopping, model_checkpoint]
)
Аугументация данных. Оцениваем влияние на качество обучения случайных трансформаций изображений.
Изменения в модели:
from tensorflow.keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
rotation_range=10,     # поворот ±10°
width_shift_range=0.1, # сдвиг по ширине ±10%
height_shift_range=0.1,# сдвиг по высоте ±10%
zoom_range=0.1         # масштабирование ±10%
)
datagen.fit(x_train)
Код:
history_aug = model.fit(
datagen.flow(x_train, y_train, batch_size=batch_size),
epochs=epochs,
validation_data=(x_test, y_test),
callbacks=[early_stopping, model_checkpoint]
)
Анализ и интерпретация полученных результатов
В таблице 2 представлен разбор поведения модели в каждом эксперименте на этапах обучения и на тестовой выборке.
Таблица 2
Разбор поведения модели в экспериментах
Из таблицы 2 видно, что у базовой CNN очень быстрая сходимость, которая уже ко 2-й эпохе достигла ≈97,8% train-accuracy, а к 4-й и вовсе ≈99,0%. Эта модель быстро переобучается, т.к. train-accuracy поднялась до ≈99,7% а val-accuracy достигает ≈98,4% и val-loss растет к 5-7 эпохам, из-за чего срабатывает остановка по колбэку EarlyStopping.
Хотя эта модель имеет вполне хорошее качество, однако небольшой разрыв между train и val говорит о переобучении.
Модель CNN + Dropout показывает более плавную сходимость – первые две эпохи train-accuracy ≈80-96%, а потом наблюдается устойчивый рост. Регуляризация помогла снизить переобучение – разрыв вместо ≈1,3% у базовой CNN стал ≈0,3%. Виден прирост качества модели благодаря регуляризации – ≈98,69%.
И, наконец, модель CNN + Augmentation показала медленную сходимость – лишь к 6-7 эпохе train-accuracy достигает ≈97-98%. Здесь, благодаря аугментации val_loss val_accuracy более ровные. Модель показала лучший результат test_accuracy ≈ 98.85%.
Оценка и сравнение методов
Гистограмма сравнения точности моделей приведена на рисунке 5.
Рисунок 5 – Сравнение точности моделей
Из анализа результатов экспериментов и представленной гистограммы видим, что применение аугментации дает наилучшую точность модели нейросети для распознавания изображений.

Заключение

Подведение итогов
Проведенная разработка системы искусственного интеллекта для распознавания рукописных цифр на базе классического набора данных MNIST завершилась успехом. Были выполнены следующие этапы:
Поставлена задача и выполнена предобработка данных. Загружен и проанализирован датасет MNIST. Проверены типы и распределения признаков, нормализованы входные данные и выполнена стратифицированная разбивка на обучающую, валидационную и тестовую выборки для обеспечения равномерного распределения цифр.
Аналитический выбор и обоснование модели. Изучены основные подходы и выбрана архитектура модели.
Проектирование и реализация. Создана простая, но эффективная модель сверточной нейронной сети. Модель скомпилирована с применением оптимизатора Adam.
Проведение экспериментов производилось с контролем обучения и сохранения лучших весов. В ходе работы определено качество моделей – базовой CNN, CNN с регуляризацией и CNN с аугментацией.
Анализ результатов экспериментов показал, что модели последовательно улучшали свое качество.
Выводы и рекомендации по улучшению результатов исследования
Скорее всего, добавление второго или третьего сверточного блока с одновременным увеличением количества фильтров позволит повысить точность модели.
Применение более заметных геометрических трансформаций данных может повысить способность модели различать вариации рукописного ввода.
Использование библиотек автоматизированного подбора гиперпараметров позволит найти лучшее сочетание гиперпараметров и повысит ее качество.
Проделанная работа показала, что выбранные подходы к распознаванию изображений рукописных цифр эффективны. На основе этих методов и полученных результатов можно организовать более масштабные и сложные проекты в области компьютерного зрения.

Список литературы

Элбон К. Машинное обучение с использованием Python: сборник рецептов / К. Элбон; пер. с англ. –  СПб.: БХВ-Петербург, 2019. –  384 с.
Руководства  |  TensorFlow Core [Электрон. ресурс] // TensorFlow (официальный сайт). –  URL: https://www.tensorflow.org/tutorials?hl=ru (дата обращения: 22.04.2025).
Keras – Developer guides [Электрон. ресурс] // Keras (официальный сайт). –  URL: https://keras.io/guides/ (дата обращения: 22.04.2025).
Приложения
Приложение 1
Код реализации решения
"""
1) Базовая CNN
2) CNN + Dropout
3) CNN + Data Augmentation
"""
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential, clone_model
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from sklearn.model_selection import train_test_split
# --------------------------------------------------------------------------------------------------
# 1. Функции-помощники
# --------------------------------------------------------------------------------------------------
def plot_class_dist(y, title):
"""Построить гистограмму распределения классов."""
counts = np.bincount(y, minlength=10)
plt.figure(figsize=(6,3))
plt.bar(range(10), counts)
plt.title(title)
plt.xlabel("Цифра")
plt.ylabel("Количество примеров")
plt.show()
def build_base_cnn(input_shape=(28,28,1), n_classes=10):
"""
Собрать базовую CNN:
- Conv2D → MaxPool → Flatten → Dense(128) → Dense(n_classes)
"""
model = Sequential([
Conv2D(32, (3,3), activation='relu', input_shape=input_shape),
MaxPooling2D((2,2)),
Flatten(),
Dense(128, activation='relu'),
Dense(n_classes, activation='softmax')
])
return model
# --------------------------------------------------------------------------------------------------
# 2. Загрузка и предобработка данных
# --------------------------------------------------------------------------------------------------
# Загружаем MNIST
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# Нормализуем изображения в [0,1] и приводим к float32
x_train = x_train.astype('float32') / 255.0
x_test  = x_test.astype('float32') / 255.0
# Добавляем ось канала (1 канал: оттенки серого)
x_train = np.expand_dims(x_train, -1)  # (60000, 28, 28, 1)
x_test  = np.expand_dims(x_test,  -1)  # (10000, 28, 28, 1)
# Показываем распределение классов
plot_class_dist(y_train, "Распределение классов (Train)")
plot_class_dist(y_test,  "Распределение классов (Test)")
# Разбиваем train → train/val (stratify для равномерного распределения)
x_train, x_val, y_train, y_val = train_test_split(
x_train, y_train,
test_size=0.1,
random_state=42,
stratify=y_train
)
plot_class_dist(y_val, "Распределение классов (Validation)")
# --------------------------------------------------------------------------------------------------
# 3. Общие колбэки и параметры обучения
# --------------------------------------------------------------------------------------------------
BATCH_SIZE = 128
EPOCHS     = 15
OPTIMIZER  = 'adam'
LOSS       = 'sparse_categorical_crossentropy'
METRICS    = ['accuracy']
early_stopping   = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)
# Будем сохранять лучшие веса для каждого эксперимента под разными именами
def make_checkpoint(fname):
return ModelCheckpoint(fname, monitor='val_accuracy', save_best_only=True)
# --------------------------------------------------------------------------------------------------
# 4. Эксперимент 1: базовая CNN
# --------------------------------------------------------------------------------------------------
# Строим и компилируем модель
model_base = build_base_cnn()
model_base.compile(optimizer=OPTIMIZER, loss=LOSS, metrics=METRICS)
print("\n=== Эксперимент 1: базовая CNN ===")
model_base.summary()
# Обучаем
history_base = model_base.fit(
x_train, y_train,
batch_size=BATCH_SIZE,
epochs=EPOCHS,
validation_data=(x_val, y_val),
callbacks=[early_stopping, make_checkpoint('base_cnn.h5')],
shuffle=True
)
# Оцениваем на тесте
loss_b, acc_b = model_base.evaluate(x_test, y_test, verbose=0)
print(f"[Base CNN] Test accuracy: {acc_b * 100:.2f}%")
# --------------------------------------------------------------------------------------------------
# 5. Эксперимент 2: CNN + Dropout
# --------------------------------------------------------------------------------------------------
# Создаём клон архитектуры и добавляем Dropout перед выходным Dense(128)
model_do = Sequential([
Conv2D(32, (3,3), activation='relu', input_shape=(28,28,1)),
MaxPooling2D((2,2)),
Flatten(),
Dense(128, activation='relu'),
Dropout(0.5),                    # Добавлен слой Dropout(50%)
Dense(10, activation='softmax')
])
model_do.compile(optimizer=OPTIMIZER, loss=LOSS, metrics=METRICS)
print("\n=== Эксперимент 2: CNN + Dropout ===")
model_do.summary()
history_do = model_do.fit(
x_train, y_train,
batch_size=BATCH_SIZE,
epochs=EPOCHS,
validation_data=(x_val, y_val),
callbacks=[early_stopping, make_checkpoint('cnn_dropout.h5')],
shuffle=True
)
loss_do, acc_do = model_do.evaluate(x_test, y_test, verbose=0)
print(f"[CNN+Dropout] Test accuracy: {acc_do * 100:.2f}%")
# --------------------------------------------------------------------------------------------------
# 6. Эксперимент 3: CNN + Data Augmentation
# --------------------------------------------------------------------------------------------------
# Определяем генератор аугментации
datagen = ImageDataGenerator(
rotation_range=10,
width_shift_range=0.1,
height_shift_range=0.1,
zoom_range=0.1
)
datagen.fit(x_train)
# Для fair comparison используем базовую архитектуру
model_aug = build_base_cnn()
model_aug.compile(optimizer=OPTIMIZER, loss=LOSS, metrics=METRICS)
print("\n=== Эксперимент 3: CNN + Data Augmentation ===")
model_aug.summary()
history_aug = model_aug.fit(
datagen.flow(x_train, y_train, batch_size=BATCH_SIZE),
epochs=EPOCHS,
validation_data=(x_val, y_val),
callbacks=[early_stopping, make_checkpoint('cnn_aug.h5')],
shuffle=True
)
loss_aug, acc_aug = model_aug.evaluate(x_test, y_test, verbose=0)
print(f"[CNN+Augmentation] Test accuracy: {acc_aug * 100:.2f}%")
# --------------------------------------------------------------------------------------------------
# 7. Сравнительный анализ результатов
# --------------------------------------------------------------------------------------------------
# Собираем метрики в словарь
results = {
'Base CNN':            acc_b,
'CNN + Dropout':       acc_do,
'CNN + Augmentation':  acc_aug
}
print("\n=== Итоговые точности на тестовой выборке ===")
for name, acc in results.items():
print(f"{name:20s}: {acc * 100:.2f}%")
# Визуализируем сравнительную точность
plt.figure(figsize=(6,4))
plt.bar(results.keys(), [v*100 for v in results.values()], color=['skyblue','salmon','lightgreen'])
plt.ylabel("Test Accuracy (%)")
plt.title("Сравнение точностей моделей")
plt.ylim(90, 100)
plt.grid(axis='y', linestyle='--', alpha=0.5)
plt.show()

Подробное описание

📘 О чем эта работа

В курсовом проекте реализована система распознавания рукописных цифр на базе классического набора MNIST. Объект исследования — изображения 28×28 пикселей в оттенках серого; предмет — алгоритмы и архитектура сверточной нейросети для их классификации. Цель — спроектировать, реализовать и протестировать CNN в среде Python с использованием TensorFlow/Keras и оценить влияние регуляризации и аугментации на качество.

📚 Что внутри

Документ содержит пошаговое описание подготовки и работы с данными, код и результаты экспериментов:

  • Предобработка: загрузка MNIST (60 000 train / 10 000 test), приведение к float32, нормализация делением на 255, добавление оси канала (28,28,1).
  • Разбиение выборок: стратифицированное выделение валидации (10% от train) с фиксированным random_state=42 для воспроизводимости.
  • Архитектура модели: вход (28,28,1) → Conv2D(32,(3,3),ReLU) → MaxPooling2D((2,2)) → Flatten → Dense(128,ReLU) → Dense(10,Softmax). Код реализован через Sequential в Keras.
  • Параметры обучения: optimizer='adam', loss='sparse_categorical_crossentropy', batch_size=128, epochs=15, EarlyStopping(patience=3), ModelCheckpoint для сохранения лучших весов.
  • Эксперименты: базовая CNN, CNN с Dropout(0.5) и CNN с Data Augmentation (rotation, width/height shift, zoom). Приведены графики распределения классов и сравнение точностей моделей.
  • Результаты: тестовые accuracy — базовая CNN ≈ 98.56%, CNN+Dropout ≈ 98.69%, CNN+Augmentation ≈ 98.85% (значения получены в эксперименте и обсуждены в тексте).
  • Код-приложение: полный код обучения и визуализации (Google Colab, Python, TensorFlow/Keras), функции построения модели, генератор аугментации и вспомогательные утилиты.

📊 Для кого подходит

Материал будет полезен студентам и преподавателям по направлениям 'Информатика', 'Прикладная математика' и 'Информационная безопасность', а также начинающим практикам в области компьютерного зрения и машинного обучения для изучения базовых приёмов построения и оценки CNN.

✨ Особенности

Работа выделяется конкретными реализованными экспериментами: сохранением лучших весов через ModelCheckpoint, автоматической остановкой обучения через EarlyStopping и сравнением эффектов Dropout и аугментации на реальных метриках. Включён готовый код для быстрого запуска в Google Colab и рекомендации по дальнейшему улучшению (добавление сверточных блоков, расширенная аугментация, автоматизированный подбор гиперпараметров).

❓ Частые вопросы

Подойдет ли для моего ВУЗа?
Структура и содержание соответствуют стандартным требованиям курсовой работы: введение, аналитическая часть, проектирование, реализация, эксперименты, заключение, список литературы и приложения с кодом.

Можно ли адаптировать?
Да — код и архитектура легко модифицируются: добавить слои Conv2D, изменить число фильтров, подобрать другие параметры аугментации или подключить поиск гиперпараметров.