Введение
В декабре 2025 года VK провёл RecSys Challenge LSVD — соревнование по машинному обучению с нестандартной постановкой задачи. Традиционные рекомендательные системы решают проблему "что показать пользователю", но здесь требовалось обратное: для каждого нового клипа определить, каким пользователям он может быть интересен. Такой подход помогает решать проблему холодного старта контента, когда новое видео только появляется в системе и не имеет истории взаимодействий.
Я принял участие в этом челлендже и хочу поделиться своим решением, архитектурой системы и практическими выводами.
Постановка задачи и данные
Задача: Для каждого клипа из тестовой выборки предсказать упорядоченный список из 100 пользователей, которые с наибольшей вероятностью проявят к нему интерес.
Ограничения:
Каждый пользователь может встречаться в рекомендациях не более 100 раз
Основная метрика — NDCG@100, рассчитываемая по клипам
Объём данных: VK-LSVD содержит десятки миллиардов взаимодействий
Данные:
Взаимодействия пользователей с клипами за 25 недель
Метаданные пользователей и клипов
Эмбеддинги клипов размерностью 256
Архитектура решения
1. Стратегия работы с большими данными
Поскольку полный датасет занимает сотни гигабайт, я реализовал стратегию поэтапной обработки:
# Конфигурация для разных режимов работы
class DataStrategy:
TEST_MODE = {
'sample_fraction': 0.01, # 1% данных
'num_weeks': 4, # 4 недели из 25
'embedding_dim': 16, # Урезанная размерность
'max_interactions': 1000000 # Лимит строк
}
PRODUCTION_MODE = {
'sample_fraction': 1.0,
'num_weeks': 25,
'embedding_dim': 64,
'max_interactions': None
}Ключевой инсайт: использование подвыборки на этапе разработки позволяет быстро тестировать гипотезы без необходимости обработки терабайтов данных.
2. Гибридный рекомендательный алгоритм
Я разработал ContentAwareRecommender, который комбинирует три подхода:
А) Коллаборативная фильтрация на основе общих взаимодействий
def get_similar_users(self, target_item_id):
"""Находит пользователей, взаимодействовавших с похожими клипами"""
similar_items = self.find_content_similar_items(target_item_id)
similar_users = set()
for item_id in similar_items:
if item_id in self.item_to_users:
similar_users.update(self.item_to_users[item_id])
return similar_usersБ) Контентная фильтрация через эмбеддинги
Использование предобученных эмбеддингов клипов позволяет оценивать семантическую схожесть даже для новых видео, с которыми ещё не было взаимодействий.
В) Статистические признаки
Частота релевантных действий пользователя
Общая активность пользователя
Популярность клипа среди похожих пользователей
3. Система балансировки рекомендаций
Ограничение "не более 100 упоминаний на пользователя" требовало специального подхода:
class RecommendationBalancer:
def balance_recommendations(self, raw_recommendations):
"""Распределяет пользователей с учётом ограничений"""
user_mentions = Counter()
balanced = {}
# Первый проход: учитываем ограничения
for item_id, recommendations in raw_recommendations.items():
balanced_list = []
for user_id in recommendations:
if user_mentions[user_id] < self.max_mentions:
balanced_list.append(user_id)
user_mentions[user_id] += 1
if len(balanced_list) >= self.recommendations_per_item:
break
balanced[item_id] = balanced_list
return balancedКлючевые проблемы и их решения
Проблема 1: Холодный старт для новых клипов
Решение: Использование контентных признаков (эмбеддингов) позволяет оценивать схожесть даже при отсутствии истории взаимодействий.
Проблема 2: Вычислительная сложность
Решение:
Индексация данных в памяти через словари вида
user_to_itemsиitem_to_usersЛенивая загрузка и обработка батчами
Кэширование промежуточных результатов
Проблема 3: Соблюдение ограничений
Решение: Двухэтапный алгоритм балансировки с приоритизацией релевантных пользователей и дозаполнением из пула наименее используемых.
Основные тезисы и выводы
1. О важности инженерии признаков
В задаче обратных рекомендаций решающую роль играют не столько сложные модели, сколько качественные признаки. Наиболее информативными оказались:
Средний эмбеддинг клипов, с которыми взаимодействовал пользователь
Частота релевантных действий (лайки, шеры, комментарии)
Активность пользователя в разных временных интервалах
2. ��алансировка как отдельная задача
Ограничения на распределение рекомендаций превращают задачу из чисто предсказательной в оптимизационную. Наивные подходы приводят к нарушению ограничений, поэтому требуется специальный алгоритм перераспределения.
3. Прагматичный подход к большим данным
Работа с терабайтными датасетами требует стратегии:
Начинать с подвыборки для отладки пайплайна
Использовать эффективные форматы хранения (Parquet)
Внедрять систему чекпоинтов для возможности продолжения после сбоев
4. Значение контентных признаков
Эмбеддинги клипов оказались мощным инструментом для оценки схожести контента. Даже простая косинусная мера близости даёт значимый прирост качества по сравнению с использованием только коллаборативных данных.
5. Метрическая специфика
NDCG@100, рассчитываемый по клипам, а не по пользователям, требует особого подхода к ранжированию. Важно не только отобрать релевантных пользователей, но и правильно упорядочить их внутри списка.
Что можно улучшить
Временные признаки: Учёт сезонности и трендов мог бы улучшить рекомендации для свежего контента.
Графовые методы: Построение графа взаимодействий и использование алгоритмов типа Node2Vec для получения эмбеддингов пользователей.
Ансамблирование: Комбинация нескольких моделей (LightFM, матричная факторизация, градиентный бустинг) могла бы дать синергетический эффект.
Оптимизация распределения: Формализация задачи балансировки как задачи оптимизации с ограничениями.
Заключение
Участие в VK RecSys Challenge позволило глубоко погрузиться в задачу обратных рекомендаций — область, которая становится всё более актуальной в эпоху переизбытка контента.
Основные уроки:
Качественные признаки важнее сложности модели
Ограничения системы часто определяют архитектуру решения
Работа с промышленными объёмами данных требует продуманной инфраструктуры
Балансировка рекомендаций — нетривиальная задача, требующая отдельного внимания
Предложенное решение демонстрирует работоспособный подход, который можно развивать в сторону более сложных моделей и признаков. Код решения доступен на GitHub и может служить основой для дальнейших эксперимен��ов в области рекомендательных систем.
