MosHack-Change 2025 — Анализатор тональности отзывов

Постановка задачи (Правительство Москвы)

  • Классифицировать русскоязычные тексты по трем меткам: 0 — отрицательная, 1 — нейтральная, 2 — положительная.
  • Веб-интерфейс должен уметь загружать CSV, нормализовать текст, возвращать размеченный CSV и визуализации; по валидационной выборке считать macro‑F1. Дополнительные фичи: поиск/фильтрация по источникам и словам, ручная правка разметки, выбор визуализаций.
  • Ограничения: использовать открытые модели/библиотеки, работать на типовом CPU/GPU, обеспечить корректный обмен данными фронтенд бэкенд.

Датасет

  • Исходные файлы: data/ТОНАЛЬНОСТЬ/train.csv, test.csv, sample_submission.csv (структура из условия: text, label, src, плюс ID).
  • Размеры: train — 232 366 строк, test — 58 092 строк. Распределение классов в train: 0 — 77 243, 1 — 77 494, 2 — 77 629.
  • Источники (11): anime, bank, geo, kinopoisk, linis, news, perekrestok, ru-reviews-classification, rureviews, rusentiment, sber.
  • Подготовленные выборки:
    • data/processed/train_clean.csv — 209 109 строк, val_clean.csv — 23 235 строк (после очистки/дедупликации).
    • Финальные сбалансированные: train_super.csv — 106 311 (по 35 437 на класс), val_super.csv — 11 771 (по ~3.9k на класс), test_super.csv — 58 092.
    • Ключевые шаги препроцессинга (notebooks/preprocess.py):
      • Очистка текста: удаление HTML/URL/email/телефонов, токены для эмодзи/оценок/бранных слов, нормализация пунктуации и растянутых букв, пометки [ALL_CAPS]/[EN].
      • Укорачивание длинных текстов до ~900 символов по предложениям с сохранением “сигнальных” фраз (под max_length 256–320 токенов).
      • Даунсемплинг до 40 000 примеров на источник; общий лимит не используется; стратифицированный train/val сплит 90/10.
      • Мягкие аугментации (word dropout 0.05 + редкий swap, не более 1 аугм./текст) и добавление доменных токенов [SRC_<источник>] в начало текста.

Структура репозитория

  • data/ — исходные (ТОНАЛЬНОСТЬ/), подготовленные (processed/), предсчитанные эмбеддинги (embeddings_xlmr/), кеши вероятностей (cache/).
  • notebooks/ — пайплайны препроцессинга и обучения (RuRoBERTa base/tiny, RuBERT conversational, TF‑IDF baseline, ансамбль BERT+LR, подготовка теста и т.д.).
  • models/ — сохраненные веса/токенизаторы, истории обучения (training_history_*.csv), конфиги ансамбля.
  • src/ — скрипты для обучения и инференса (data_utils.py, train_model.py, inference.py, src/models).
  • pretrained/ — дополнительные артефакты моделей.
  • README.md, requirements.txt, environment.yml, ПравительствоМосквы_Hack&Change 2025.pdf.

Пример дерева (обрезано до ключевых узлов):

sentiment_project/
├─ data/
│  ├─ ТОНАЛЬНОСТЬ/             # train.csv, test.csv, sample_submission.csv
│  ├─ processed/               # train_super.csv, val_super.csv, test_super.csv, *_clean.csv
│  ├─ embeddings_xlmr/         # X_train.npy, X_val.npy, y_*.npy
│  └─ cache/                   # предсчитанные вероятности для ансамблей
├─ notebooks/
│  ├─ preprocess.py            # скрипт подготовки данных
│  ├─ preprocess.ipynb         # пошаговый препроцессинг
│  ├─ baseline.ipynb           # TF-IDF бэйзлайны (LR, SVC, SVD+HGB)
│  ├─ bert_tf_cv.ipynb         # ансамбль BERT + TF-IDF
│  ├─ train_rurorberta_base_manual.ipynb
│  ├─ train_rurorberta_tiny_manual.ipynb
│  ├─ train_rubert_base_conv.ipynb
│  ├─ train_xlmr_base.ipynb
│  └─ eval_model_universal.ipynb
├─ models/
│  ├─ rurorberta_base2_manual/    # веса, токенизатор, история обучения
│  ├─ rurorberta_tiny_manual/
│  ├─ rubert_base_conv_manual/
│  ├─ sentiment_*.joblib          # TF-IDF модели
│  └─ ensemble_config_cv*.json    # конфиги ансамблей
├─ src/
│  ├─ data_utils.py
│  ├─ train_model.py
│  ├─ inference.py
│  └─ models/
├─ pretrained/
├─ requirements.txt
├─ environment.yml
└─ README.md

Последовательность работы

  • Установить окружение: python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt (или conda env create -f environment.yml).
  • Подготовить данные: из папки notebooks/ запустить python preprocess.py — сохранит data/processed/train_super.csv, val_super.csv, test_super.csv.
  • (Опц.) Подготовить эмбеддинги/валидацию для классических моделей: notebooks/baseline.ipynb, bert_tf_cv.ipynb.
  • Обучить трансформеры: соответствующие ноутбуки (train_rurorberta_base_manual.ipynb, train_rurorberta_tiny_manual.ipynb, train_rubert_base_conv.ipynb, ubert-base-cased-sentiment-rusentiment.ipynb, train_xlmr_base.ipynb) — читают data/processed/*.csv, сохраняют веса/токенизатор в models/.
  • Оценка/ансамбль: bert_tf_cv.ipynb (считает macro-F1 на val_super, генерирует конфиги ансамбля), eval_model_universal.ipynb для сводной проверки.
  • Инференс на тесте/приложении: загрузить обученную модель из models/ и применять тот же препроцесс [SRC_*]/очистку, что в preprocess.py.

Метрики моделей (macro‑F1 на val_super)

Модель / пайплайн Откуда Macro‑F1
blanchefort/rubert-base-cased-sentiment-rusentiment notebooks/ubert-base-cased-sentiment-rusentiment.ipynb 0.7561
DeepPavlov/rubert-base-cased-conversational notebooks/train_rubert_base_conv.ipynb 0.7347
ai-forever/RuRoBERTa-base (дообученная) notebooks/train_rurorberta_base_manual.ipynb (models/rurorberta_base2_manual) 0.7338
FacebookAI/xlm-roberta-base
FacebookAI/xlm-roberta-base (дообученная на 30 тысяч данных) notebooks/train_xlmr_base.ipynb 0.7213
cointegrated/rubert-tiny2 (дообученная) notebooks/train_rurorberta_tiny_manual.ipynb 0.6871
Ансамбль BERT + TF‑IDF+LR notebooks/bert_tf_cv.ipynb 0.6642
TF‑IDF + Logistic Regression (Optuna) notebooks/baseline.ipynb 0.6222
TF‑IDF + SVD + HistGradientBoosting notebooks/baseline.ipynb 0.6101
TF‑IDF + LinearSVC notebooks/baseline.ipynb 0.5997

Метрики считаются на валидации val_super (стратифицированные 10% после очистки и балансировки). Логи обучения и истории сохранены рядом с соответствующими моделями в models/.