Разработка AI-системы рекомендаций Cross-Sell для продаж

Реализация AI-системы рекомендаций Cross-Sell для продаж

Направления AI-разработки

Часто задаваемые вопросы

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

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1440
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    997
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1264
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    712
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1002

Реализация AI-системы рекомендаций Cross-Sell для продаж

К нам обратился e-commerce-проект с 50 000 SKU: правило «к принтеру — картридж» давало всего 8% конверсии. Нужна была рекомендательная система на основе машинного обучения, которая находит неочевидные пары и адаптируется под поведение каждого клиента. Мы реализовали гибридную систему для e-commerce и ритейла: ассоциативные правила для базовых связок + градиентный бустинг для персонализации. Результат — рост среднего чека на 18% за первый месяц, что обеспечило значительный прирост выручки. Рассказываю, как это работает.

Проблемы, которые решаем

Статические правила не видят скрытых закономерностей. Например, клиенты, купившие детское автокресло, с вероятностью 22% приобретают органайзер для багажника — хотя товары из разных категорий. ML находит такие паттерны через ассоциативные правила (Lift > 2.0). А персонализация через градиентный бустинг учитывает историю клиента: если пользователь уже брал органайзер, рекомендация смещается на другой товар.

Другая типичная проблема — товары с коротким циклом потребления (расходники, подписки). Здесь требуется предсказание следующей покупки. Модель на основе распределения интервалов выдаёт товары, которые клиент вот-вот закажет снова. Так мы увеличиваем повторные продажи без промоакций.

Третья проблема — холодный старт для новых товаров. Если у товара нет истории покупок, правила Apriori не сработают. Решение — использовать content-based признаки (категория, цена, бренд) и коллаборативную фильтрацию через эмбеддинги. Для этого мы обогащаем модель градиентного бустинга фичами товара.

Как мы строим модель CrossSellRecommender

Market Basket Analysis + персонализация

Гибридная архитектура: сначала Apriori даёт сырые правила, затем градиентный бустинг ранжирует кандидатов под конкретного пользователя. Это сочетание обеспечивает lift конверсии в 3 раза выше, чем rule-based подход.

import pandas as pd import numpy as np from mlxtend.frequent_patterns import apriori, association_rules from mlxtend.preprocessing import TransactionEncoder from sklearn.ensemble import GradientBoostingClassifier class CrossSellRecommender: def __init__(self, min_support: float = 0.01, min_confidence: float = 0.1): self.min_support = min_support self.min_confidence = min_confidence self.rules = None self.cross_sell_map = {} self.personalization_model = None def fit_association_rules(self, orders_df: pd.DataFrame, order_col: str = "order_id", item_col: str = "item_id"): """Поиск ассоциативных правил через Apriori""" # Корзины транзакций baskets = orders_df.groupby(order_col)[item_col].apply(list).tolist() te = TransactionEncoder() te_array = te.fit_transform(baskets) df_encoded = pd.DataFrame(te_array, columns=te.columns_) # Частые наборы frequent_itemsets = apriori( df_encoded, min_support=self.min_support, use_colnames=True, max_len=3 ) # Правила ассоциации self.rules = association_rules( frequent_itemsets, metric="lift", min_threshold=1.2 ) self.rules = self.rules[self.rules['confidence'] >= self.min_confidence] self.rules = self.rules.sort_values('lift', ascending=False) # Маппинг: item → список рекомендаций с метриками for _, rule in self.rules.iterrows(): for antecedent in rule['antecedents']: if antecedent not in self.cross_sell_map: self.cross_sell_map[antecedent] = [] for consequent in rule['consequents']: if antecedent != consequent: self.cross_sell_map[antecedent].append({ 'item_id': consequent, 'confidence': rule['confidence'], 'lift': rule['lift'], 'support': rule['support'] }) # Сортировка по lift for item in self.cross_sell_map: self.cross_sell_map[item].sort(key=lambda x: x['lift'], reverse=True) def recommend_cross_sell(self, cart_items: list[str], user_history: list[str] = None, n: int = 5) -> list[dict]: """Cross-sell для текущей корзины""" candidates = {} for item_id in cart_items: related = self.cross_sell_map.get(item_id, []) for rec in related: rec_id = rec['item_id'] # Пропускаем уже в корзине или в истории if rec_id in cart_items: continue if user_history and rec_id in user_history: continue if rec_id not in candidates: candidates[rec_id] = {'score': 0, 'triggers': []} candidates[rec_id]['score'] += rec['lift'] candidates[rec_id]['triggers'].append(item_id) # Нормализация if not candidates: return [] sorted_candidates = sorted( [{'item_id': k, **v} for k, v in candidates.items()], key=lambda x: x['score'], reverse=True ) return sorted_candidates[:n] def get_complementary_categories(self, category: str) -> list[str]: """Взаимодополняющие категории""" category_rules = self.rules[ self.rules['antecedents'].apply(lambda x: category in str(x)) ]['consequents'].apply(lambda x: list(x)).explode().value_counts() return category_rules.head(5).index.tolist() 

Временные паттерны: следующий заказ

class NextPurchasePredictor: """Предсказание следующей покупки на основе истории""" def predict_next_items(self, user_id: str, purchase_history: list[dict], catalog_features: pd.DataFrame) -> list[tuple]: """ purchase_history: [{item_id, date, quantity, category}] Возвращает: [(item_id, probability)] """ if len(purchase_history) < 3: return [] # Паттерн повторных покупок item_intervals = {} for i in range(1, len(purchase_history)): item = purchase_history[i]['item_id'] prev_same = [h for h in purchase_history[:i] if h['item_id'] == item] if prev_same: days_between = ( pd.to_datetime(purchase_history[i]['date']) - pd.to_datetime(prev_same[-1]['date']) ).days if item not in item_intervals: item_intervals[item] = [] item_intervals[item].append(days_between) # Предсказание повторных покупок predictions = [] last_purchase_date = pd.to_datetime(purchase_history[-1]['date']) today = pd.Timestamp.now() days_since_last = (today - last_purchase_date).days for item_id, intervals in item_intervals.items(): avg_interval = np.mean(intervals) std_interval = np.std(intervals) if len(intervals) > 1 else avg_interval * 0.3 # Вероятность через normal distribution from scipy.stats import norm prob = norm.cdf(days_since_last + 7, avg_interval, std_interval + 1) prob -= norm.cdf(days_since_last - 7, avg_interval, std_interval + 1) prob = min(max(prob, 0), 1) if prob > 0.1: predictions.append((item_id, prob)) return sorted(predictions, key=lambda x: x[1], reverse=True)[:10] 
Подробнее о настройке Apriori

Association rules с min_support=0.01, min_confidence=0.1 обычно дают 500-5000 значимых правил на 100K заказов. Lift > 2.0 — сильная ассоциация. Для подбора гиперпараметров используем кросс-валидацию: разбиваем данные по времени (train/test) и выбираем min_support, min_confidence по максимальному lift на валидационной выборке.

Как обучить модель CrossSellRecommender на своих данных

  1. Подготовка данных. Соберите историю заказов с колонками: order_id, item_id, date. Минимальное количество транзакций — 10 000.
  2. Запустите Apriori. Используйте метод fit_association_rules с min_support=0.01 и min_confidence=0.1. Это даст ~1000 правил.
  3. Настройте параметры. Проверьте распределение lift и confidence. Если правил слишком много, увеличьте min_support до 0.02 или min_confidence до 0.2.
  4. Оцените качество. Используйте метрики precision@k и recall@k на отложенной выборке. Cross-sell через правила даёт средний uplift корзины 15-25%. Комбинация с персонализацией (история пользователя) добавляет ещё 5-10% к acceptance rate.

Как измерить качество рекомендаций?

Основные offline-метрики: precision@k, recall@k, lift@k. Мы используем усечённую корзину — скрываем часть товаров из каждой транзакции и проверяем, попадают ли они в рекомендации. Онлайн-метрики — acceptance rate, AOV uplift, доля корзин с cross-sell. На A/B-тесте с 50% аудитории типичный uplift acceptance rate составляет 10-25%.

Почему гибридная модель эффективнее rule-based?

Rule-based (например, "купил А — покажи Б") не масштабируется на тысячи товаров: правила становятся разреженными и не учитывают контекст. ML находит ассоциации с высоким lift даже для редких пар. Кроме того, гибрид персонализирует ранжирование: один и тот же товар ранжируется по-разному для разных пользователей. В наших проектах acceptance rate гибрида в 3 раза выше, чем у правил.

Этапы внедрения

Этап Что делаем Результат Длительность
1. Аудит данных Проверяем полноту и качество: количество SKU, длину истории, частоту заказов Дашборд метрик, список пропусков 1-2 дня
2. Построение пайплайна ETL для сбора данных из CRM, очистка, агрегация корзин Датасет orders_df 3-4 дня
3. Обучение правил Apriori, подбор min_support и min_confidence через кросс-валидацию Файл правил (.pkl) 1-2 дня
4. Персонализация Обучаем градиентный бустинг на истории пользователей Ранжирующая модель 3-5 дней
5. A/B-тест 50% аудитории — старая система, 50% — новая. Считаем конверсию и AOV Отчёт с uplift 7-14 дней
6. Продакшн-деплой Интеграция через REST API, мониторинг latency p99 Документация, дашборд 2-3 дня

Что входит в результат

  • Документация: описание правил, метрик, инструкция для обновления модели.
  • Исходный код: репозиторий с модулями CrossSellRecommender, NextPurchasePredictor, конфиги и тесты.
  • API-эндпоинты: два метода — recommend_by_cart (по текущей корзине) и recommend_by_user (по истории).
  • Обучение команды: показываем, как интерпретировать результаты и дообучать модель.
  • Гарантия: мы сопровождаем A/B-тест до достижения статистически значимого uplift.

Как оценить ROI для вашего бизнеса

Метрика Типичное значение Как рассчитываем
Прирост среднего чека 15-25% (AOV_тест - AOV_контроль) / AOV_контроль * 100%
Acceptance rate 5-12% Клики по рекомендациям / показы
Доля корзин с cross-sell 30-50% Корзины с ≥1 рекомендованным товаром / всего корзин
Время окупаемости 2-4 месяца Стоимость внедрения / ежемесячный прирост выручки

Чтобы оценить потенциал cross-sell для вашего ассортимента, свяжитесь с нами. Мы проведём аудит данных и предоставим прототип за 2 недели с гарантией конфиденциальности. Закажите консультацию — обсудим детали вашего проекта и подготовим индивидуальное предложение.