Сесійні рекомендації працюють з анонімними або короткочасними взаємодіями де немає довгострокової історії користувача. Замість user profiles, вони використовують поточну сесію - послідовність переглядів, кліків або покупок - щоб передбачити наступний item. Це критично для e-commerce, новинних сайтів та стрімінг платформ з анонімними користувачами.
Де використовується
Сесійні рекомендації застосовуються де user identity недоступний або непотрібен:
- E-commerce: Анонімні відвідувачі, нові користувачі
- Новини/Медіа: Читачі без login
- Стрімінг: Guest sessions, device-level персоналізація
- Пошук: Query suggestions, related searches
- Travel: Пошук рейсів/готелів в одній сесії
- Gaming: In-session рекомендації
Продукти: Amazon (visitors), news aggregators, Spotify radio.
Відмінності від user-based рекомендацій
| Аспект | User-based | Session-based |
|---|---|---|
| Історія | Довгострокова | Поточна сесія |
| Identity | Потрібна | Анонімна |
| Data | User profiles | Послідовності items |
| Cold start | User cold start | Менш проблематичний |
| Privacy | Потребує tracking | Більш приватний |
Типові дані
| Аспект | Типові значення |
|---|---|
| Session length | 2-20 items |
| Sessions/day | 10K до 10M |
| Catalog size | 1K до 10M items |
| Session duration | 5 хв до 1 години |
| Conversion rate | 1-5% |
Що ви робите на практиці
- Визначте сесію - Cookie, device, time-based cutoff
- Зберіть сесійні дані - Перегляди, кліки, покупки в порядку
- Фільтруйте короткі сесії - Зазвичай < 2 items
- Оберіть модель - Item-KNN, GRU4Rec, SASRec
- Тренуйте на історичних сесіях - Передбачення next item
- Оптимізуйте retrieval - ANN для швидкого inference
- Деплойте real-time - Низька латентність для кожного кліку
- A/B тестуйте - CTR, conversion, session length
- Моніторте drift - Catalog changes, behavior shifts
- Ітеруйте - Додайте features, tune hyperparameters
Спочатку базова лінія: Item-KNN
Найпростіший але ефективний підхід:
import numpy as np
from collections import defaultdict
from scipy.sparse import csr_matrix
class ItemKNN:
def __init__(self, k=20, similarity='cosine'):
self.k = k
self.similarity = similarity
def fit(self, sessions):
"""Побудова матриці co-occurrence."""
# Item-to-item co-occurrence
self.item_counts = defaultdict(int)
self.cooccurrence = defaultdict(lambda: defaultdict(int))
for session in sessions:
for item in session:
self.item_counts[item] += 1
for i, item_i in enumerate(session):
for j, item_j in enumerate(session):
if i != j:
self.cooccurrence[item_i][item_j] += 1
# Compute similarities
self.similarities = {}
for item_i, neighbors in self.cooccurrence.items():
sims = []
for item_j, count in neighbors.items():
if self.similarity == 'cosine':
sim = count / np.sqrt(self.item_counts[item_i] * self.item_counts[item_j])
sims.append((item_j, sim))
self.similarities[item_i] = sorted(sims, key=lambda x: -x[1])[:self.k]
def recommend(self, session, n=10):
"""Рекомендації на основі поточної сесії."""
scores = defaultdict(float)
for item in session:
if item in self.similarities:
for neighbor, sim in self.similarities[item]:
if neighbor not in session:
scores[neighbor] += sim
ranked = sorted(scores.items(), key=lambda x: -x[1])
return [item for item, _ in ranked[:n]]
Deep Learning підходи
GRU4Rec - RNN для сесій:
import torch
import torch.nn as nn
class GRU4Rec(nn.Module):
def __init__(self, n_items, embedding_dim=64, hidden_dim=128, n_layers=1):
super().__init__()
self.embedding = nn.Embedding(n_items, embedding_dim, padding_idx=0)
self.gru = nn.GRU(embedding_dim, hidden_dim, n_layers, batch_first=True)
self.output = nn.Linear(hidden_dim, n_items)
def forward(self, x, lengths=None):
# x: (batch, seq_len) - item indices
embedded = self.embedding(x) # (batch, seq_len, embed_dim)
output, hidden = self.gru(embedded) # (batch, seq_len, hidden_dim)
# Використовуємо останній hidden state
logits = self.output(output[:, -1, :]) # (batch, n_items)
return logits
def train_gru4rec(model, train_loader, epochs=10):
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
criterion = nn.CrossEntropyLoss()
for epoch in range(epochs):
model.train()
for batch_sessions, batch_targets in train_loader:
optimizer.zero_grad()
logits = model(batch_sessions)
loss = criterion(logits, batch_targets)
loss.backward()
optimizer.step()
SASRec - Self-Attention:
class SASRec(nn.Module):
def __init__(self, n_items, max_len=50, d_model=64, n_heads=2, n_layers=2):
super().__init__()
self.item_emb = nn.Embedding(n_items + 1, d_model, padding_idx=0)
self.pos_emb = nn.Embedding(max_len, d_model)
encoder_layer = nn.TransformerEncoderLayer(
d_model=d_model,
nhead=n_heads,
dim_feedforward=d_model * 4,
batch_first=True
)
self.transformer = nn.TransformerEncoder(encoder_layer, n_layers)
self.output = nn.Linear(d_model, n_items + 1)
def forward(self, x):
seq_len = x.shape[1]
positions = torch.arange(seq_len, device=x.device).unsqueeze(0)
x = self.item_emb(x) + self.pos_emb(positions)
# Causal mask для auto-regressive
mask = torch.triu(torch.ones(seq_len, seq_len), diagonal=1).bool()
x = self.transformer(x, mask=mask.to(x.device))
return self.output(x[:, -1, :])
Метрики оцінки
| Метрика | Опис | Використання |
|---|---|---|
| HR@K | Hit Rate - чи target в top-K | Recall-like |
| MRR | Mean Reciprocal Rank | Ranking quality |
| NDCG@K | Normalized DCG | Ranking quality |
| Coverage | % catalog recommended | Diversity |
| CTR | Click-through rate | Online metric |
def hit_rate_at_k(recommendations, targets, k=10):
"""Hit Rate @ K."""
hits = 0
for recs, target in zip(recommendations, targets):
if target in recs[:k]:
hits += 1
return hits / len(targets)
def mrr(recommendations, targets):
"""Mean Reciprocal Rank."""
rr_sum = 0
for recs, target in zip(recommendations, targets):
try:
rank = recs.index(target) + 1
rr_sum += 1 / rank
except ValueError:
pass
return rr_sum / len(targets)
Типові помилки та чек-лист
- [ ] Session definition: Неправильний cutoff між сесіями
- [ ] Short sessions: Недостатньо сигналу для prediction
- [ ] Popularity bias: Рекомендуються лише популярні items
- [ ] Cold items: Нові items без co-occurrence
- [ ] Latency: Занадто повільний inference
Чек-лист для продакшену
Перед деплоєм: - [ ] Offline метрики валідовані - [ ] Inference latency < 50ms - [ ] A/B test framework готовий - [ ] Fallback до popularity
Після деплою: - [ ] Моніторинг CTR та conversion - [ ] Відстеження session length - [ ] Catalog refresh handling - [ ] Регулярне перенавчання
Інструменти та стек
| Категорія | Інструменти |
|---|---|
| Бібліотеки | RecBole, Surprise, TensorFlow Recommenders |
| Deep Learning | PyTorch, JAX |
| Serving | TensorFlow Serving, Triton |
| Vector DB | Milvus, Pinecone, Faiss |
Приклад міні-кейсу
Сценарій: Session-based рекомендації для e-commerce.
Підхід: - GRU4Rec з 128-dim embeddings - Items: 50K SKUs - Сесії: 5M/місяць
Результати: - HR@10: 0.35 (vs 0.22 popularity baseline) - +8% conversion rate - Inference: 25ms p99
Пов'язані сторінки
- Індекс: ML Field Guide
- Collaborative Filtering
- Embedding рекомендації
Додаткові матеріали
Спробуйте наживо
Дослідіть пов'язану модель на практиці: відкрийте Video Recommender — Matrix Factorization Live і змінюйте параметри під час роботи. Усе лишається у вашому браузері.
▶ Відкрити симуляцію Video Recommender — Matrix Factorization Live