От диплома до продакшена: Как я создавал архитектуры ИИ-проектов
Часть 4: Обучение и валидация модели — 250 эпох, 94.55% точности и борьба с переобучением
В этой части я расскажу о самом критическом этапе — обучении модели. Здесь 250 эпох отделяют работающую модель от неработающей, а правильная настройка гиперпараметров определяет успех всего проекта.
Содержание
Введение: Почему обучение — это не просто «нажать кнопку»
Многие считают, что обучение нейросети — это просто загрузить данные и нажать «старт». На практике всё сложнее. Неправильная настройка гиперпараметров, отсутствие контроля переобучения или неправильная подготовка данных могут свести на нет всю предыдущую работу.
В этой части я подробно расскажу о том, как проходило обучение моей модели для распознавания голосовых команд, с какими проблемами я столкнулся и как их решал.
Подготовка данных к обучению
Структура датасета
Перед обучением необходимо было подготовить данные в формате, пригодном для подачи в нейросеть. Исходные аудиофайлы были обработаны и преобразованы в числовые признаки.
Параметр | Значение | Описание |
|---|---|---|
Общее количество примеров | 273 | После отбора и структурирования |
Классы команд | 4 | Комната, Дверь, Камера, Фон |
Примеров на класс | ~68 | В среднем на каждый класс |
Признаков на пример | 21 | 9 SSR + 9 CHZ + 3 MFC |
Проверочная выборка | 20% | 55 примеров для валидации |
Нормализация данных
Перед обучением все признаки были нормализованы для исключения резких разниц в расчётах:
from sklearn import preprocessing as prep # Нормализация данных xTrainSSR = prep.normalize(xTrainSSR) xTrainCHZ = prep.normalize(xTrainCHZ) xTrainMFC = prep.normalize(xTrainMFC)
Почему нормализация важна:
Вижу что наборы значений сильно отличаются между собой, там где цифровые значения низкие, будут менее значимы при объединении. Можно использовать вариант с нормализацией данных, а можно написать нейронку с несколькими входами.
Нормализация обеспечивает:
Равный вклад всех признаков в обучение
Стабильную сходимость градиентного спуска
Защиту от доминирования признаков с большими значениями
Гиперпараметры и их обоснование
Таблица гиперпараметров
Параметр | Значение | Обоснование |
|---|---|---|
epochs | 250 | Экспериментально подобрано. 100 эпох — недостаточная сходимость (val_accuracy ~87%), 500 эпох — начинается переобучение (val_accuracy падает до ~91%) |
batch_size | 10 | Маленький датасет (273 примера). Меньший батч даёт более стабильные градиенты |
learning_rate | 1e-4 | Стандарт для Adam. Слишком высокий — нестабильность, слишком низкий — медленная сходимость |
validation_split | 0.2 | Стандартное соотношение. 20% данных достаточно для контроля переобучения |
optimizer | Adam | Адаптивный оптимизатор. Лучше SGD для небольших датасетов |
loss | categorical_crossentropy | Для многоклассовой классификации (4 класса) |
Компиляция модели
model.compile(optimizer=Adam(1e-4), loss='categorical_crossentropy', metrics=['accuracy'])
Процесс обучения: ключевые эпохи
Полный лог обучения содержит 250 эпох. Для наглядности привожу ключевые эпохи, которые показывают динамику обучения:
Эпоха | loss | val_loss | accuracy | val_accuracy |
|---|---|---|---|---|
1 | 1.82 | 1.26 | 21% | 94.55% |
20 | 0.55 | 1.34 | 79% | 27% |
77 | 0.38 | 0.61 | 83% | 94.55% |
150 | 0.28 | 1.01 | 87% | 85% |
247 | 0.16 | 0.91 | 94% | 94.55% |
Наблюдения на ранних эпохах
Эпоха 1: Точность на обучении 21.10%, на валидации 94.55%
Высокая валидация на первой эпохе — случайное совпадение. Модель ещё не обучилась, но случайная инициализация весов дала хороший результат на маленькой валидационной выборке.
Эпоха 2-3: Точность на валидации упала до 0%
Модель начала переобучаться на обучающей выборке. Это нормальное явление на ранних этапах обучения.
Эпоха 20: Стабилизация на уровне 78.90% (train) и 27.27% (val)
Начало сходимости модели. После этой эпохи точность на валидации начинает расти.
Полные логи обучения (фрагмент)
Epoch 1/250 22/22 [==============================] - 3s 33ms/step - loss: 1.8197 - accuracy: 0.2110 - val_loss: 1.2615 - val_accuracy: 0.9455 ....... Epoch 77/250 22/22 [==============================] - 0s 13ms/step - loss: 0.3819 - accuracy: 0.8257 - val_loss: 0.6105 - val_accuracy: 0.9455 ....... Epoch 247/250 22/22 [==============================] - 0s 16ms/step - loss: 0.1618 - accuracy: 0.9404 - val_loss: 0.9144 - val_accuracy: 0.9455
Проблемы и решения
Проблема 1: Нестабильность на ранних эпохах
Проблема: Точность на валидации падала до 0% на 2-3 эпохах
Причина:
Маленький размер батча (10 примеров)
Небольшой размер датасета (273 примера)
Случайная инициализация весов
Решение:
Продолжение обучения до стабилизации
Dropout (0.2-0.3) для регуляризации
BatchNormalization для стабилизации градиентов
Результат: После эпохи 20 точность на валидации начала стабильно расти.
Проблема 2: Переобучение
Проблема: Разница между точностью на обучении и валидации
Причина:
Модель «запоминает» обучающие данные
Недостаточная регуляризация
Решение:
Dropout (0.2 на ранних слоях, 0.3 на поздних)
BatchNormalization после каждого Conv1D и Dense слоя
20% валидационная выборка для контроля
Результат:
Метрика | Значение | Интерпретация |
|---|---|---|
Train Accuracy | 94.04% | Модель хорошо выучила данные |
Val Accuracy | 94.55% | Хорошая обобщающая способность |
Разница | 0.51% | Признак отсутствия значительного переобучения |
Разница между точностью на обучении и валидации менее 1% — признак отсутствия значительного переобучения.
Проблема 3: Маленький датасет
Проблема: Всего 273 примера для обучения
Причина:
Ограниченное время на сбор данных
Ограниченные ресурсы для разметки
Решение:
Тщательный отбор качественных примеров
Нормализация данных для стабильности обучения
Регуляризация (Dropout + BatchNorm)
Что можно улучшить:
# Data Augmentation для аудио def add_noise(data, noise_level=0.005): noise = np.random.randn(len(data)) * noise_level return data + noise def change_speed(data, speed_factor=1.1): return librosa.effects.time_stretch(data, rate=speed_factor) def change_pitch(data, pitch_factor=0.7): return librosa.effects.pitch_shift(data, sr=22050, n_steps=pitch_factor)
Ожидаемый эффект: Увеличение датасета в 5-10 раз, улучшение обобщающей способности.
Результаты и выводы
Финальные метрики
Метрика | Значение | Комментарий |
|---|---|---|
Train Accuracy | 94.04% | Модель хорошо выучила данные |
Val Accuracy | 94.55% | Хорошая обобщающая способность |
Train Loss | 0.1618 | Низкая ошибка на обучении |
Val Loss | 0.9144 | Приемлемая ошибка на валидации |
Эпох обучения | 250 | Достаточно для сходимости |
Размер батча | 10 | Малый размер из-за ограничений Colab |
Ключевые выводы
Стабильность важнее скорости — 250 эпох обеспечили стабильную сходимость
Регуляризация работает — Dropout + BatchNormalization предотвратили переобучение
Валидация обязательна — 20% на валидацию позволили контролировать качество
Есть куда расти — Data Augmentation, Transfer Learning, Early Stopping могут улучшить результат
Что можно улучшить в будущем
Метод | Ожидаемый эффект | Сложность реализации |
|---|---|---|
Data Augmentation | +3-5% точности | Низкая |
Transfer Learning | +5-10% точности | Средняя |
Early Stopping | Экономия времени | Низкая |
Квантование | Уменьшение размера модели в 4 раза | Средняя |
Что будет в следующей части?
Часть 5: Интеграция с устройствами «Умного дома»
В следующей части я расскажу о том, как обученная модель интегрируется с реальными устройствами умного дома:
Протоколы связи (Wi-Fi, Bluetooth, Zigbee)
Управление освещением
Управление дверями и замками
Управление камерами наблюдения
Интеграция с бытовой техникой
Пример: GSM-звонок и шлагбаум
Пример: Детекция госномера
Масштабируемость архитектуры
Источники и ресурсы
Исходный код проекта
Файл | Описание | Ссылка |
|---|---|---|
Jupyter Notebook | Код модели и обучение | [SmartHome v4.6.ipynb](SmartHome v4.6.ipynb) |
GitHub | Репозиторий проекта |
Библиотеки и инструменты
# Основные библиотеки для работы с аудио import librosa # Обработка аудио import librosa.display # Визуализация аудио # Библиотеки для нейросетей import tensorflow as tf # Фреймворк для глубокого обучения from tensorflow.keras import layers, models # Утилиты from sklearn.preprocessing import StandardScaler # Нормализация
Вопросы для обсуждения
Какие методы регуляризации вы используете в своих проектах?
Как вы боретесь с переобучением на маленьких датасетах?
Используете ли вы Transfer Learning для аудио-задач?
Делитесь в комментариях! 👇
