Этот проект представляет собой полный цикл разработки production-ready ML-сервиса: от обучения и отладки легковесной модели для классификации токсичности в русскоязычных комментариях до ее упаковки в API с использованием FastAPI.
- Сверхлегковесная модель: Квантованная CNN-модель весит ~5 МБ, что идеально для быстрого развертывания.
- Высокая производительность: Время инференса на CPU составляет единицы миллисекунд.
- Production-Ready API: Готовый к развертыванию API-сервис на FastAPI с документацией Swagger.
- Чистая архитектура: Проект структурирован по принципам SOLID, DRY, KISS и ООП для легкой поддержки и масштабирования.
- Воспроизводимость: Проект включает Jupyter-блокнот для полного воспроизведения процесса обучения и оптимизации модели.
- Машинное обучение: Python, PyTorch, Natasha, scikit-learn
- API: FastAPI, Pydantic, Uvicorn
- Развертывание: Docker
- Среда разработки: Jupyter Notebook (Kaggle), VS Code
Проект имеет логическую структуру, разделяющую данные, код обучения, обученные модели и код приложения.
AI_Toxic/
│
├── .gitignore # Исключение ненужных файлов из Git
├── README.md # Этот файл
│
├── data/ # Данные для обучения
│ └── raw/
│ └── dataset.csv
│
├── models/ # Обученные модели и артефакты
│ └── v1.0/
│ ├── solo_cnn_fp32.pth (мастер-модель)
│ ├── solo_cnn_int8.pth (модель для API)
│ └── vocab.json (словарь)
│
├── notebooks/ # Jupyter-блокнот с процессом обучения
│ └── cnn_training.ipynb
│
└── api/ # Код API-сервиса
├── main.py
├── classifier.py
├── preprocessor.py
├── schemas.py
├── config.py
├── requirements.txt
└── Dockerfile
Все команды выполняются из корневой папки проекта (AI_Toxic/).
-
Клонируйте репозиторий:
git clone [URL вашего репозитория] cd AI_Toxic -
Создайте и активируйте виртуальное окружение:
python -m venv venv # Для Windows: # venv\Scripts\activate # Для macOS/Linux: # source venv/bin/activate
-
Установите зависимости: Проект имеет два набора зависимостей: для обучения и для API.
# Зависимости для запуска API pip install -r api/requirements.txt # Зависимости для запуска Jupyter-блокнота # Рекомендуется создать отдельный requirements.txt для блокнота pip install pandas jupyter scikit-learn
- Откройте и запустите ячейки в блокноте
notebooks/cnn_training.ipynb. - Этот блокнот выполнит все шаги: от предобработки данных до обучения, оценки и квантизации модели.
- В результате в папке
models/v1.0/будут созданы все необходимые артефакты (.pthфайлы иvocab.json).
Вы можете запустить API локально для разработки или через Docker для продакшена.
Локальный запуск:
# Убедитесь, что вы находитесь в корне проекта AI_Toxic/ и venv активировано
uvicorn api.main:app --reloadОткройте в браузере http://127.0.0.1:8000/docs для доступа к интерактивной документации.
Запуск через Docker:
docker build -t toxic-classifier-api . -f api/Dockerfile
docker run -d -p 8000:8000 --name my-toxic-api toxic-classifier-api```
Финальная модель версии v1.0 была оценена на валидационной выборке и показала следующие результаты:
- Размер квантованной модели: ~5 МБ
- F1-score (токсичный класс): 0.58
| Класс | Precision | Recall | F1-score |
|---|---|---|---|
| Нетоксичный (0) | 0.78 | 0.88 | 0.83 |
| Токсичный (1) | 0.68 | 0.51 | 0.58 |
| Предсказано: Нетоксичный | Предсказано: Токсичный | |
|---|---|---|
| Реальный: Нетоксичный | 1685 (TN) | 233 (FP) |
| Реальный: Токсичный | 473 (FN) | 492 (TP) |
Интерпретация: Модель работает в "осторожном" режиме. Когда она помечает комментарий как токсичный, она права в 68% случаев (Precision), но при этом находит только 51% всех токсичных комментариев (Recall). Баланс можно настроить с помощью параметра threshold в API.
- Токенизация: Из-за проблем с лемматизацией
natashaв облачной среде был выбран более надежный подход с использованиемSegmenterдля токенизации и последующей ручной очистки. - Стабилизация обучения: Модель была склонна к коллапсу (предсказание одного класса). Проблема была решена комбинацией
BatchNorm1d,ReLUкак модуля,gradient clippingиCosineAnnealingLR. - Квантизация: Для успешной квантизации потребовалось явно указать "мосты" (
QuantStub,DeQuantStub), использовать специальныйqconfigдляnn.Embeddingи, что самое важное, явно сливать (fuse) модулиConv-BN-ReLUперед подготовкой модели.
Для проверки производительности модели был проведен локальный стресс-тест на CPU (8 ядер), чтобы измерить "сырую" пропускную способность (RPS - Requests Per Second).
| Конфигурация | Пропускная способность (RPS) | Прирост |
|---|---|---|
| 1 ядро CPU | ~680 RPS | - |
| 8 ядер CPU | ~2400 RPS | x3.5 |
Вывод: Модель демонстрирует отличную производительность на одном ядре и хорошо масштабируется на многоядерных системах, достигая почти 2400 предсказаний в секунду.
В ходе тестирования был выявлен классический "performance trap". При первой попытке распараллелить вычисления с помощью multiprocessing производительность практически не выросла (прирост x1.08).
- Причина: Каждый из 8 дочерних процессов пытался использовать внутреннее распараллеливание PyTorch (через MKL/OpenMP), создавая избыточное количество потоков (8 процессов * N потоков), которые боролись друг с другом за ресурсы CPU.
- Решение: Проблема была решена принудительной установкой однопоточного режима для PyTorch внутри каждого дочернего процесса (
torch.set_num_threads(1)). Это позволилоmultiprocessingэффективно распределять нагрузку на уровне процессов и достичь реального прироста производительности в 3.5 раза.