← Назад к вопросам

Что такое cold start problem в рекомендациях?

3.0 Senior🔥 141 комментариев
#Python#Машинное обучение

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Cold Start Problem в рекомендациях

Cold Start Problem — это фундаментальная проблема в системах рекомендаций, когда система не может дать хорошие рекомендации для новых пользователей (user cold start), новых товаров (item cold start) или для новой системы в целом (system cold start). Проблема возникает потому, что алгоритмы коллаборативной фильтрации полагаются на историю взаимодействий пользователей с товарами, а у новых сущностей этой истории нет.

Три типа Cold Start Problem

1. User Cold Start (Новый пользователь)

Новый пользователь регистрируется
    |
    v
У него нет истории просмотров/покупок
    |
    v
Модель коллаборативной фильтрации не может найти похожих пользователей
    |
    v
Немогу дать персонализированные рекомендации
    |
    v
Приходится использовать популярные товары

2. Item Cold Start (Новый товар)

Новый товар добавлен в каталог
    |
    v
Никто ещё его не видел и не купил
    |
    v
Нет взаимодействий пользователей с товаром
    |
    v
Модель не может найти похожих товаров
    |
    v
Новый товар невидим в рекомендациях

3. System Cold Start (Новая система)

Новая платформа запускается
    |
    v
Нет исторических данных
    |
    v
Нельзя использовать коллаборативную фильтрацию
    |
    v
Приходится начинать с нуля

Математическое описание

Матрица взаимодействий в коллаборативной фильтрации:

        Товар1  Товар2  Товар3  ... ТоварN
Пользователь1   5       3       ?      4
Пользователь2   4       ?       2      ?
Пользователь3   ?       4       3      5
    ...         ?       ?       ?      ?
ПользовательM   3       5       ?      2

Проблема:
- Если новый пользователь: вся его строка = ?
- Если новый товар: весь его столбец = ?
- Матрица очень разреженная (sparse)

Решение 1: Content-Based Filtering

Вместо анализа взаимодействий используем признаки товаров:

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

# Признаки товаров
items_features = np.array([
    # книга 1: [жанр, длина, популярность, цена]
    [1, 0, 0, 450, 4.5, 15],  # научная фантастика
    [0, 1, 0, 380, 4.2, 12],  # детектив
    [1, 0, 0, 520, 4.7, 18],  # научная фантастика
    [0, 0, 1, 250, 3.9, 8],   # биография
])

# Профиль пользователя на основе его прошлых оценок
user_profile = np.array([0.8, 0.2, 0.3])  # Любит научную фантастику

# Находим похожие товары
similarities = cosine_similarity([user_profile], items_features)[0]
recommendations = np.argsort(-similarities)[:3]

print(f"Рекомендуемые товары: {recommendations}")

Преимущества:

  • Работает для новых товаров (если есть их описание)
  • Можно рекомендовать даже при нулевых взаимодействиях

Недостатки:

  • Нужно вручную описывать признаки товаров
  • Не учитывает коллективное знание других пользователей

Решение 2: Hybrid Approach (Гибридный подход)

Комбинируем коллаборативную фильтрацию и контент-based подход:

import numpy as np
from sklearn.preprocessing import normalize

class HybridRecommender:
    def __init__(self, cf_weight=0.6, content_weight=0.4):
        self.cf_weight = cf_weight
        self.content_weight = content_weight
    
    def get_recommendations(self, user_id, cf_scores, content_scores):
        """
        cf_scores: баллы от коллаборативной фильтрации
        content_scores: баллы от контент-based подхода
        """
        # Нормализуем оба набора оценок
        cf_scores = normalize([cf_scores])[0]
        content_scores = normalize([content_scores])[0]
        
        # Комбинируем
        hybrid_scores = (
            self.cf_weight * cf_scores + 
            self.content_weight * content_scores
        )
        
        return np.argsort(-hybrid_scores)

# Пример использования
recommender = HybridRecommender(cf_weight=0.7, content_weight=0.3)

cf_scores = np.array([0.8, 0.3, 0.9, 0.2])  # От CF
content_scores = np.array([0.6, 0.7, 0.4, 0.8])  # От Content

recommendations = recommender.get_recommendations(user_id=1, cf_scores=cf_scores, content_scores=content_scores)
print(f"Гибридные рекомендации: {recommendations}")

Решение 3: Knowledge Graph / Semantic Similarity

Используем граф знаний для связывания товаров:

import networkx as nx

# Граф товаров
G = nx.Graph()
G.add_edges_from([
    ('Книга1_SciFi', 'Книга3_SciFi'),  # похожие жанры
    ('Книга3_SciFi', 'Книга2_Detective'),  # один автор
    ('Книга2_Detective', 'Книга4_Biography'),  # похожие темы
])

# Для нового товара находим похожие
new_item = 'Книга5_SciFi'
G.add_node(new_item)
G.add_edge(new_item, 'Книга1_SciFi')

# Находим соседей
neighbors = list(G.neighbors(new_item))
print(f"Похожие товары: {neighbors}")

# Используем PageRank для более сложных рекомендаций
scores = nx.pagerank(G, personalization={new_item: 1})
top_items = sorted(scores.items(), key=lambda x: x[1], reverse=True)[:5]
print(f"Top 5 релевантных товаров: {[item for item, _ in top_items]}")

Решение 4: Demographic Filtering

Для новых пользователей используем их демографические данные:

import pandas as pd

# Базовые профили по демографии
demographic_profiles = {
    'age_18_25': [0.9, 0.3, 0.8, 0.2],  # предпочтения по категориям
    'age_25_35': [0.5, 0.7, 0.3, 0.8],
    'age_35_50': [0.4, 0.8, 0.6, 0.3],
    'age_50_plus': [0.2, 0.9, 0.5, 0.1],
}

def recommend_for_new_user(age, gender, location):
    # Выбираем профиль по возрасту
    if age < 25:
        profile = demographic_profiles['age_18_25']
    elif age < 35:
        profile = demographic_profiles['age_25_35']
    else:
        profile = demographic_profiles['age_35_50']
    
    # Можем персонализировать дальше по полу/локации
    return profile

# Рекомендуем новому пользователю 22 года
scores = recommend_for_new_user(age=22, gender='M', location='Moscow')
print(f"Рекомендации для 22-летнего: {scores}")

Решение 5: Popularity-Based Filtering

Для новых пользователей показываем популярные товары:

import pandas as pd
from collections import Counter

# История взаимодействий
interactions = pd.DataFrame({
    'user_id': [1, 1, 2, 2, 3, 4, 4, 4, 5, 5],
    'item_id': ['A', 'B', 'A', 'C', 'A', 'B', 'C', 'D', 'A', 'E']
})

# Считаем популярность
popularity = interactions['item_id'].value_counts()
print(f"Популярность товаров:\n{popularity}")

# Top N популярных товаров для новых пользователей
top_n = popularity.head(5).index.tolist()
print(f"\nРекомендуемые товары для новых пользователей: {top_n}")

Решение 6: Contextual Bandits

Обучаемый подход, который учится на ходу:

import numpy as np

class ContextualBandit:
    def __init__(self, n_arms=5, n_features=3):
        self.n_arms = n_arms
        self.n_features = n_features
        self.weights = np.random.normal(0, 1, (n_arms, n_features))
    
    def select_item(self, context):
        """
        context: признаки пользователя/ситуации
        Выбираем товар с наибольшим ожидаемым вознаграждением
        """
        scores = np.dot(self.weights, context)
        return np.argmax(scores)
    
    def update(self, context, selected_item, reward):
        """
        Обновляем модель после получения вознаграждения
        """
        # Простой градиентный шаг
        learning_rate = 0.01
        prediction = np.dot(self.weights[selected_item], context)
        error = reward - prediction
        self.weights[selected_item] += learning_rate * error * context

# Использование
bandit = ContextualBandit(n_arms=5, n_features=3)

# Для новых пользователей начинаем с их контекста
user_context = np.array([1, 0.5, 0.8])  # [возраст_норм, активность, платежеспособность]
selected_item = bandit.select_item(user_context)

# После взаимодействия обновляем
reward = 1  # Пользователю понравилось
bandit.update(user_context, selected_item, reward)

Решение 7: Matrix Factorization с регуляризацией

Используем факторизацию матриц с дополнительными признаками:

import torch
import torch.nn as nn

class NeuralCollaborativeFiltering(nn.Module):
    def __init__(self, n_users, n_items, embedding_dim=32, use_side_info=True):
        super().__init__()
        self.user_embedding = nn.Embedding(n_users, embedding_dim)
        self.item_embedding = nn.Embedding(n_items, embedding_dim)
        
        # Дополнительные признаки для новых пользователей/товаров
        if use_side_info:
            self.user_fc = nn.Linear(embedding_dim + 10, 32)  # 10 доп признаков
            self.item_fc = nn.Linear(embedding_dim + 20, 32)  # 20 доп признаков
        
        self.fc = nn.Sequential(
            nn.Linear(32, 16),
            nn.ReLU(),
            nn.Linear(16, 1)
        )
    
    def forward(self, user_id, item_id, user_features=None, item_features=None):
        user_emb = self.user_embedding(user_id)
        item_emb = self.item_embedding(item_id)
        
        # Комбинируем с дополнительными признаками
        if user_features is not None:
            user_input = torch.cat([user_emb, user_features], dim=1)
            user_emb = self.user_fc(user_input)
        
        # Умножаем эмбеддинги
        x = user_emb * item_emb
        return self.fc(x)

# Для новых пользователей:
# - Используем их демографические признаки вместо ID
# - Инициализируем случайные эмбеддинги
# - Быстро обучаем на их взаимодействиях

Практический пример: Стратегия onboarding

class RecommendationSystem:
    def __init__(self):
        self.user_stage = {}  # Отслеживаем, на каком этапе пользователь
    
    def recommend(self, user_id):
        if user_id not in self.user_stage:
            # Новый пользователь
            return self._recommend_stage_1_new(user_id)
        
        stage = self.user_stage[user_id]
        if stage == 1:
            # Набрал несколько взаимодействий
            if len(self.get_user_history(user_id)) >= 3:
                self.user_stage[user_id] = 2
                return self._recommend_stage_2_learning(user_id)
            else:
                return self._recommend_stage_1_new(user_id)
        elif stage == 2:
            # Достаточно данных для CF
            if len(self.get_user_history(user_id)) >= 10:
                self.user_stage[user_id] = 3
                return self._recommend_stage_3_cf(user_id)
            else:
                return self._recommend_stage_2_learning(user_id)
        else:
            # Полная коллаборативная фильтрация
            return self._recommend_stage_3_cf(user_id)
    
    def _recommend_stage_1_new(self, user_id):
        # Популярные товары
        return self.get_popular_items(top_n=5)
    
    def _recommend_stage_2_learning(self, user_id):
        # Гибридный подход
        cf_scores = self.get_cf_scores(user_id)
        content_scores = self.get_content_scores(user_id)
        return self.hybrid_scores(cf_scores, content_scores)
    
    def _recommend_stage_3_cf(self, user_id):
        # Полная коллаборативная фильтрация
        return self.get_cf_recommendations(user_id)

Метрики для оценки cold start решений

from sklearn.metrics import precision_score, recall_score

# Отслеживаем:
# 1. Click-through rate (CTR) для новых пользователей
# 2. Конверсия новых пользователей
# 3. Удержание (retention) новых пользователей
# 4. Diversity рекомендаций

def evaluate_cold_start(recommendations, user_interactions):
    # Precision@5
    p5 = precision_score(user_interactions, recommendations[:5])
    # Recall@5
    r5 = recall_score(user_interactions, recommendations[:5])
    # Coverage (разнообразие)
    coverage = len(set(recommendations)) / len(recommendations)
    
    return {'precision@5': p5, 'recall@5': r5, 'coverage': coverage}

Лучшие практики

  1. Комбинируй методы: популярность + контент + CF
  2. Используй контекст: демография, время, местоположение
  3. Запроси информацию: онбординг с вопросами о предпочтениях
  4. Diversity: показывай разнообразные товары, а не только популярные
  5. Эксплуатация vs исследование: баланс между известными предпочтениями и новыми
  6. Fast feedback loop: узнавай предпочтения быстро

Заключение

Cold Start Problem остаётся фундаментальной проблемой в системах рекомендаций. Нет универсального решения — успех зависит от того, какая информация доступна, вычислительные ресурсы и требования к системе. Лучший подход — гибридный, комбинирующий контент, демографию, популярность и коллаборативную фильтрацию с постепенным переходом от одного метода к другому по мере накопления данных о пользователе.