Решения задач хакатона Codenrock по анализу данных и машинному обучению.
- 1 место (Задача 4, Macro-F1 1.0), 3 место (Задача 1, ROC-AUC 0.6761), 6 место (Задача 2, NDCG@5 0.3508), 18 место (Задача 3, Public Score 0.9823)
- Сильный упор на EDA, feature engineering и стабильную валидацию
- Стек: Python, Pandas/NumPy, CatBoost, Scikit-learn (SVM/TF-IDF), Optuna, MLflow, Matplotlib/Seaborn, PyTorch
- Задача 3 — распознавание изображений (CV), Задача 4 — классификация текстов (NLP)
| Задача | Описание | Public Score | Место |
|---|---|---|---|
| 1 | Предсказание выживаемости ёлки | 0.6761 (ROC-AUC) | 3 место |
| 2 | Рекомендация блюд из холодильника | 0.3508 (NDCG@5) | 6 место |
| 3 | Распознавание изображений (колбаса/конфетти) | 0.9823 | 18 место |
| 4 | Классификация сообщений чата (NLP) | 1.0 (Macro-F1) | 1 место |
- EDA: проверка гипотез, поиск сигналов и ошибок в данных
- Feature engineering для табличных данных
- CatBoost для классификации и ранжирования (Learning to Rank)
- Оптимизация гиперпараметров и CV (Optuna, Stratified/temporal)
- Логирование экспериментов и воспроизводимость (MLflow)
- Computer Vision: базовый опыт, регрессия по изображению (PyTorch)
- NLP: классификация текстов, TF-IDF, предобработка (pymorphy3, regex)
├── README.md
├── requirements.txt
├── Task 1/ # Задача 1: Предсказание выживаемости ёлки
│ ├── task1_tree_survival.ipynb # Jupyter notebook с решением
│ ├── data/ # Игнорируется (данные не в репозитории)
│ ├── catboost_info/ # Игнорируется (логи CatBoost)
│ └── mlruns/ # Игнорируется (эксперименты MLflow)
├── Task 2/ # Задача 2: Рекомендация блюд
│ ├── task2_food_recs.ipynb # Jupyter notebook с решением
│ └── data/ # Игнорируется (данные не в репозитории)
├── Task 3/ # Задача 3: Колбаса или конфетти (распознавание изображений)
│ ├── task3_sausage_cv.ipynb # Jupyter notebook с решением
│ └── data/ # Игнорируется (данные не в репозитории)
└── Task 4/ # Задача 4: Чат дома (NLP)
├── task4_chat_nlp.ipynb # Jupyter notebook с решением
└── data/ # Игнорируется (данные не в репозитории)
Кратко:
- Метрика: ROC-AUC
- Модель: CatBoost + bagging (5 моделей)
- Оптимизация: Optuna, 5-fold Stratified CV, MLflow
Описание задачи
18 января в городе пройдут съёмки новогодней франшизы, и декораторам нужны тысячи украшенных ёлок, которые всё ещё выглядят свежо. Необходимо предсказать вероятность того, что ёлка в квартире доживёт до этой даты.
Данные
Датасет содержит информацию о 18,000 квартирах с различными характеристиками:
- Характеристики жилья: площадь, высота потолков, тип отопления, сторона дома
- Микроклимат: температура, влажность, расстояние до батареи
- Ёлка: порода (ель/пихта/сосна), высота, форма кроны, тип подставки
- Уход: полив, опрыскивание, проветривание
- Украшения: мишура, игрушки, гирлянды
Подход и признаки
- Анализ распределений всех признаков
- Выявление логических несоответствий (например, дата сруба у ёлок в горшках)
- Исследование пропусков и их влияния на таргет
- Проверка гипотез о влиянии различных факторов на выживаемость
Создано более 30 новых признаков, включая:
| Категория | Примеры признаков |
|---|---|
| Флаги пропусков | humidity_pct_isna, radiator_distance_m_isna |
| Климатические | dryness, heat_dry_interaction, vpd_like (аналог дефицита давления пара) |
| Расстояние до радиатора | radiator_inv_x_temp, radiator_dist_relative |
| Уход за ёлкой | care_score, waterings_per_100cm |
| Украшения | ornaments_per_cm, ornaments_x_tinsel, cat_tinsel_combo |
| Геометрия | room_volume_m3, tree_height_to_ceiling |
| Гирлянда | garland_heat_proxy, effective_heat |
Модель и валидация
Выбор модели: CatBoost
- Нативная обработка категориальных признаков без One-Hot Encoding
- Автоматическая работа с пропусками
- Высокая производительность на табличных данных
Оптимизация гиперпараметров:
- Использован Optuna с 50 trials
- 5-fold Stratified Cross-Validation
- Логирование экспериментов через MLflow
Финальная модель:
- Bagging из 5 моделей с CV
- Усреднение предсказаний для большей стабильности
Результат
✅ Public Score: 0.6761 (ROC-AUC)
Кратко:
- Метрика: NDCG@5
- Модель: CatBoostRanker (YetiRank)
- Валидация: временной holdout + GroupShuffleSplit
Описание задачи
После новогодних праздников в семейном холодильнике осталось много еды. Родственники постоянно меняют мнение о том, что хотят съесть. Необходимо по контексту (время суток, уровень похмелья, наличие гостей и т.д.) и предпочтениям пользователя предсказать, какое блюдо он выберет, и выдать топ-5 рекомендаций.
Данные
- dishes.csv — справочник из 200 блюд (категория, калорийность, аллергены, теги)
- users.csv — 15,000 пользователей (аллергии, предпочтения, флаги: сладкоежка, кофеман и др.)
- train.csv — 300,000 событий выбора блюда
- test.csv — 20,000 запросов для предсказания
Каждый запрос содержит:
- Контекст: день января, приём пищи, уровень похмелья, количество гостей, режим диеты
- Список из 20 кандидатов (блюд, доступных в холодильнике)
Подход и признаки
- Анализ блюд: распределение по категориям, калорийность, аллергены и теги
- Анализ пользователей: предпочтения, аллергии, выявление "противоречивых" профилей
- Анализ контекста: влияние похмелья, времени суток, гостей на выбор
- Анализ взаимодействий: как сочетание факторов меняет поведение
Ключевые инсайты:
- При высоком уровне похмелья вероятность выбора супа возрастает до 30%+
- Наличие гостей смещает выбор в сторону основных блюд (+5 п.п.)
diet_mode— сильный предиктор выбора низкокалорийных блюд- В 67.4% случаев пользователи выбирают блюдо с "любимым" тегом
- Аллергии — жёсткий фильтр: 0% нарушений в данных
Создано более 25 признаков в нескольких категориях:
| Категория | Примеры признаков |
|---|---|
| Матчинг тегов | n_liked_matches, n_disliked_matches, is_allergy_violation |
| Категории блюд | cat_is_soup, cat_is_main, cat_is_dessert и др. |
| Теги блюд | tag_is_low_cal, tag_is_sweet |
| Контекстные взаимодействия | x_hangover_soup, x_guests_main, x_diet_low_cal, x_holiday_soup |
| Время | slot_is_breakfast, slot_is_dinner, x_lunch_soup |
| Состав холодильника | fridge_soup_count, fridge_soup_ratio, fridge_mean_calories, relative_calories |
| Замещение | x_sweettooth_no_dessert_snack |
| Противоречия профиля | is_confused_sweet, is_confused_coffee, is_confused_low_cal |
Модель и валидация
Выбор модели: CatBoostRanker
- Специализированная модель для задач ранжирования (Learning to Rank)
- Нативная поддержка группировки по запросам
- Loss-функция: YetiRank
Стратегия валидации:
- Временной holdout: обучение на днях 1–12, валидация на 13–18
- GroupShuffleSplit для inner-validation (80/20)
- Метрика: NDCG@5
Гиперпараметры:
iterations=4000
learning_rate=0.03
depth=8
l2_leaf_reg=5
early_stopping_rounds=300Результат
✅ Public Score: 0.3508 (NDCG@5)
Кратко:
- Метрика: Score (0...1)
- Модель: ResNet18 (Pretrained)
- Особенности: Первый опыт в CV, решение-бейзлайн
Описание задачи
Необходимо по фотографии ковра определить, какую долю площади занимают два вида объектов: конфетти (c) и кружочки колбасы (s).
Датасет синтетический, содержит шум, размытие и перекрытия объектов. Требуется предсказать два числа (float) в диапазоне [0, 1].
Данные
train/images— обучающий набор изображенийtest/images— тестовый набор
В качестве таргетов выступают доли пикселей, занимаемых объектами.
Подход и реализация
Это мой первый опыт решения задач Computer Vision, поэтому использовался подход Transfer Learning:
- Препроцессинг:
- Ресайз изображений до
224x224 - Преобразование в тензоры (
transforms.ToTensor)
- Ресайз изображений до
- Архитектура:
- Backbone:
ResNet18(предобученная на ImageNet) - Head: Замена полносвязного слоя на
nn.Linearс 2 выходами +Sigmoid
- Backbone:
- Обучение:
- Loss:
MSELoss - Optimizer:
Adam(lr=0.001) - 3 эпохи обучения
- Loss:
Планы на развитие
В дальнейшем планирую углубиться в CV:
- Освоить библиотеки аугментаций (Albumentations)
- Попробовать более современные архитектуры (EfficientNet, ViT)
- Использовать Test Time Augmentation (TTA)
Результат
✅ Public Score: 0.9823 (18 место)
Кратко:
- Метрика: Macro-F1
- Модель: LinearSVC + TF-IDF
- Особенности: Синтетический датасет (Score 1.0), мощный Feature Engineering
Описание задачи
Необходимо классифицировать сообщения из домового чата по 14 темам (ЖКХ, шум, доставка, праздники и т.д.). Дана история сообщений за 1–14 января.
Основные классы: congratulations, cooking, repairs, kids_school, shopping, pets, conflicts, cleaning, bills, market, delivery, lost_found, plans_guests, other_chat.
Данные
train.csv— обучающая выборка (текст, день, час, тема)test.csv— тестовая выборка (текст, день, час)
Особенности данных:
- Четкие временные паттерны (праздники 1-4 янв, стресс 5-10 янв, рутина 11-14 янв)
- Зависимость тем от времени суток (ночные конфликты, утренние школы, вечерние посиделки)
Подход и признаки
- Выделены 3 временных периода:
holiday,stress,routine - Выделены 4 времени суток:
is_night,is_morning,is_day,is_evening - Финансовые темы (
bills,market) содержат символы валют и цифры - Эмоциональные темы (
congratulations,conflicts) выделяются пунктуацией (! и ?)
Использован гибридный подход (Текст + Meta-признаки):
- TF-IDF: униграммы и триграммы (ngram_range=(1, 3))
- Meta-признаки:
- Временные:
period_*(One-Hot),is_night/msg/day/evening - Текстовые:
exclam_count(!),quest_count(?),digit_count,has_currency(₽/руб)
- Временные:
- Препроцессинг: лемматизация (pymorphy3), удаление стоп-слов, демоджификация
LinearSVC (Support Vector Classification)
- Идеально подходит для разреженных данных высокой размерности (TF-IDF)
class_weight="balanced"для компенсации дисбаланса классовloss="squared_hinge",penalty="l2"
Результат
✅ Public Score: 1.0 (Macro-F1)
# Клонирование репозитория
git clone https://github.com/1dober1/codenrock-hackathon.git
cd codenrock-hackathon
# Создание виртуального окружения
python -m venv venv
source venv/bin/activate # Linux/macOS
# или venv\Scripts\activate # Windows
# Установка зависимостей
pip install -r requirements.txt
# Запуск Jupyter Notebook
jupyter notebook