Каждый третий посетитель интернет-магазина уходит без покупки из-за нерелевантных рекомендаций. Хуже того, показ однотипных товаров снижает доверие к площадке. На одном проекте — магазин электроники с 50 000 SKU — мы зафиксировали, что блок «похожие товары» на основе категорий выдавал почти одинаковые позиции: 8 из 8 — смартфоны той же марки. Click-through rate упал до 0.3%. Проблема не в отсутствии данных, а в выборе алгоритма. Content-based на атрибутах даёт узкую выдачу, коллаборативная фильтрация страдает от cold start, а гибрид требует грамотного микса. Мы реализовали системы рекомендаций для 15+ магазинов (оборот от 10 млн руб./мес) и нашли баланс: рост конверсии в среднем 18%, а для одного клиента — +34% за счёт внедрения ассоциативных правил «часто покупают вместе». Персонализация e-commerce — это не просто тренд, а необходимость для удержания клиентов.
Какой алгоритм рекомендаций выбрать?
Выбор зависит от данных и целей. Content-based ищет похожие по атрибутам — быстро запускается, но даёт однотипные результаты. Коллаборативная фильтрация (ALS) выявляет скрытые паттерны — точнее, но требует истории действий. Гибридный подход сочетает лучшее из обоих: на 25% больше кликов, чем чистый content-based. Для нового магазина без истории мы рекомендуем начинать с content-based на эмбеддингах, постепенно подключая ALS по мере накопления данных.
| Алгоритм | Требуемые данные | Преимущества | Недостатки | Скорость внедрения |
|---|---|---|---|---|
| Content-based (эмбеддинги) | Описания товаров | Работает сразу, без истории | Однотипные результаты | 2–3 дня |
| Коллаборативная фильтрация (ALS) | Поведение пользователей | Высокая точность, скрытые паттерны | Cold start для новых пользователей | 1–2 недели |
| Гибридный микс | Оба типа | Лучший CTR на 20%+, сглаживает cold start | Сложность настройки весов | 2–3 недели |
Почему гибридный подход эффективнее?
Он не страдает от cold start: новые товары получают рекомендации через эмбеддинги, а старые — через поведение пользователей. Разнообразие выше — блок не забивается одинаковыми позициями. Мы используем динамический микс: если у пользователя мало данных, делаем упор на content-based, и наоборот. На практике это даёт рост CTR на 15–20% по сравнению с однородной выдачей. Кроме того, гибрид позволяет увеличить средний чек на 12–15% за счёт кросс-продаж.
Структура данных и индексация
Для эмбеддингов собираем текстовое представление товара:
function buildProductText(product) {
return [
product.name,
product.brand,
product.category + ' > ' + product.subcategory,
product.description?.slice(0, 500),
product.tags?.join(', '),
Object.entries(product.attributes || {})
.map(([k, v]) => `${k}: ${v}`)
.join(', '),
].filter(Boolean).join('\n');
}
async function indexProduct(product) {
if (!product.active || product.stock === 0) return;
const text = buildProductText(product);
const { data: [{ embedding }] } = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: text,
});
await db.query(`
INSERT INTO product_embeddings (product_id, embedding, updated_at)
VALUES ($1, $2::vector, NOW())
ON CONFLICT (product_id) DO UPDATE
SET embedding = $2::vector, updated_at = NOW()
`, [product.id, JSON.stringify(embedding)]);
}
Индексация проходит при каждом обновлении товара. Эмбеддинги храним в pgvector — это даёт скорость поиска <10ms для 100К товаров.
Поиск похожих товаров
async function getSimilarProducts(productId, options = {}) {
const { limit = 8, minPrice, maxPrice, inStockOnly = true } = options;
const result = await db.query(`
WITH source AS (
SELECT pe.embedding, p.price, p.category_id
FROM product_embeddings pe
JOIN products p ON p.id = pe.product_id
WHERE pe.product_id = $1
)
SELECT p.id, p.name, p.slug, p.price, p.main_image, p.rating, p.reviews_count,
1 - (pe.embedding <=> source.embedding) AS similarity
FROM product_embeddings pe
JOIN products p ON p.id = pe.product_id
CROSS JOIN source
WHERE pe.product_id != $1 AND p.active = true
AND ($2::boolean IS FALSE OR p.stock > 0)
AND ($3::numeric IS NULL OR p.price >= $3)
AND ($4::numeric IS NULL OR p.price <= $4)
ORDER BY pe.embedding <=> source.embedding
LIMIT $5
`, [productId, inStockOnly, minPrice || null, maxPrice || null, limit]);
return result.rows;
}
Добавили фильтры по цене и наличию — результаты всегда актуальны и соответствуют бизнес-правилам.
Ассоциативные правила: «часто покупают вместе»
Анализируем историю заказов за последние 90 дней через FP-Growth (быстрее Apriori на больших данных):
from mlxtend.frequent_patterns import fpgrowth, association_rules
import pandas as pd
def compute_frequently_bought_together():
orders = fetch_orders_last_90_days()
basket = orders.groupby(['order_id', 'product_id'])['product_id'] \
.count().unstack().fillna(0)
basket = basket.map(lambda x: 1 if x > 0 else 0)
frequent_sets = fpgrowth(basket, min_support=0.005, use_colnames=True)
rules = association_rules(frequent_sets, metric='lift', min_threshold=1.5)
for _, rule in rules.iterrows():
antecedent = list(rule['antecedents'])[0]
consequent = list(rule['consequents'])[0]
save_association(antecedent, consequent, rule['confidence'], rule['lift'])
Практическая польза: когда кладут в корзину смартфон, предлагаем чехол и стекло — конверсия в допродажу растёт на 40%. Для магазина одежды мы выявили, что покупатели джинсов часто берут ремень — это увеличило средний чек на 12%. Повышение лояльности за счёт релевантных предложений снижает затраты на ретаргетинг на 20–25%.
Персональные рекомендации через ALS
Используем implicit.ALS (64 фактора, 30 итераций) на поведенческой матрице (просмотр=1, корзина=3, покупка=10):
import implicit
from scipy.sparse import csr_matrix
def train_product_model(events):
users_idx = {u: i for i, u in enumerate(events['user_id'].unique())}
items_idx = {p: i for i, p in enumerate(events['product_id'].unique())}
matrix = csr_matrix((
events['weight'],
(events['user_id'].map(users_idx), events['product_id'].map(items_idx))
))
model = implicit.als.AlternatingLeastSquares(factors=64, iterations=30)
model.fit(matrix.T)
return model, users_idx, items_idx
Для каждого пользователя получаем топ-N товаров, смешивая с content-based для разнообразия.
Разнообразие рекомендаций (Diversity)
Блок из 8 одинаковых ноутбуков ухудшает UX. Механизм диверсификации пересортирует выдачу, штрафуя похожие категории:
function diversify(recommendations, diversityFactor = 0.3) {
const selected = [recommendations[0]];
const remaining = recommendations.slice(1);
while (selected.length < 8 && remaining.length > 0) {
const scores = remaining.map(candidate => {
const maxSimilarity = Math.max(
...selected.map(s => categorySimilarity(s, candidate))
);
return { item: candidate, score: candidate.score * (1 - diversityFactor * maxSimilarity) };
});
scores.sort((a, b) => b.score - a.score);
selected.push(scores[0].item);
remaining.splice(remaining.indexOf(scores[0].item), 1);
}
return selected;
}
В результате в выдаче — товары разных категорий и ценовых сегментов. A/B тестирование показало, что разнообразная выдача увеличивает CTR на 22% без потери конверсии.
Как настраивается diversity на практике?
Можно добавить вес оценки от популярности или маржинальности, чтобы балансировать релевантность и бизнес-показатели.Процесс внедрения
- Анализ — изучаем ассортимент, сценарии поведения, данные.
- Проектирование — выбираем алгоритмы под задачи бизнеса.
- Прототип — запускаем на реальных данных, измеряем качество.
- A/B тест — сравниваем с текущей версией (или её отсутствием).
- Деплой и мониторинг — настраиваем дашборды, фиксируем базу.
Что входит в работу
- Документация архитектуры и описание моделей
- Обучение команды работе с системой
- Дашборд ключевых метрик (CTR, конверсия, выручка)
- Поддержка в течение месяца после запуска
Ориентировочные сроки
| Компонент | Срок |
|---|---|
| Content-based похожие товары (pgvector) | 3–4 дня |
| Ассоциативные правила («часто покупают вместе») | +2–3 дня |
| Персональные рекомендации (ALS) — Python-сервис | +4–5 дней |
| Полная система + A/B + аналитика | 3–4 недели |
Стоимость рассчитывается индивидуально после анализа вашего проекта. Получите консультацию инженера — мы подготовим коммерческое предложение с точными сроками и этапами. Свяжитесь с нами, чтобы обсудить детали и начать повышать конверсию вашего магазина.







