Two-tower DSSM на собеседовании Data Scientist
Карьерник — Duolingo для аналитиков: 10 минут в день тренируй SQL, Python, A/B, статистику, метрики и ещё 3 темы собеса. 1500+ вопросов в Telegram-боте. Бесплатно.
Содержание:
Зачем разбирать на собесе
Two-tower — основной паттерн для retrieval (recsys, search) в production. На собесе DS / MLE: «отличие от MF», «зачем разделение», «in-batch negatives».
Архитектура two-tower
User features Item features
↓ ↓
[User Tower] [Item Tower]
↓ ↓
user_emb (dim k) item_emb (dim k)
\ /
\ /
dot product / cosine
↓
scoreUser Tower — MLP / Transformer от user features (id + контекст + history).
Item Tower — MLP / Transformer от item features (id + categorical + content).
Score — dot product или cosine между embeddings.
Ключевая фишка: towers независимы при inference. Item embeddings можно предпосчитать, user embedding считать online.
Обучение и loss
Pairwise / softmax loss.
L = -log( exp(u · i+) / Σ_j exp(u · i_j) )i+ — positive (item, с которым interaction). i_j — все items в batch (positive и negatives).
Можно с temperature τ:
L = -log( exp(u · i+ / τ) / Σ exp(u · i_j / τ) )Маленький τ → жёстче, большой τ → мягче.
Hard negative mining. Включать в negatives «трудные» items (похожие, но не релевантные). Improves quality.
In-batch negatives
Главный приём:
В батче из N (user, positive_item) пар — для каждого user остальные N-1 items в батче — negatives.
# batch: u_emb (N, k), pos_item_emb (N, k)
logits = u_emb @ pos_item_emb.T # (N, N) матрица
labels = torch.arange(N) # diagonal — positives
loss = cross_entropy(logits, labels)Преимущества:
- Негативы получаются «бесплатно».
- Размер batch большой → много негативов.
Минусы:
- Negatives — random items, может быть слишком легко.
- Bias: item-частоты в негативах = popularity. Лечение — popularity correction (
logits -= log(freq)).
ANN search для retrieval
Production retrieval — найти top-K items для user из миллиона items. Brute force dot(u, all_items) — O(N·k), медленно на 100M+ items.
Approximate Nearest Neighbors (ANN):
- FAISS (Facebook) — IVF, HNSW, PQ. Стандарт.
- ScaNN (Google).
- HNSW (graph-based) — быстро, точно, но больше памяти.
- Annoy (Spotify) — ranges trees.
import faiss
index = faiss.IndexFlatIP(k)
index.add(item_embeddings)
D, I = index.search(user_embedding, k=100) # top-100 for userLatency ~ms, точность 95-99% к brute force.
Применения
Recsys retrieval. Candidate generation: 1M items → 1000 кандидатов через two-tower.
Search. Query embedding (user tower на тексте) vs document embedding.
Ad ranking — user features vs ad features.
Multi-modal. CLIP — text tower vs image tower.
Частые ошибки
Симметричные towers. User и item не симметричны (разные features). Не делать их одной сетью.
Random sampling negatives только. Слишком легко. In-batch + hard negatives.
Не делать popularity correction. Модель учит популярное. Хуже на «длинном хвосте».
Online inference обоих towers. Item tower должен быть оффлайн. Online — только user tower.
Tanh вместо linear на конце. Embedding должен быть free — не bounded.
Cosine vs dot product без нормализации. Решай явно — cosine требует l2-normalize обоих embeddings.
Связанные темы
- Collaborative Filtering на собесе DS
- Embeddings на собесе DS
- Ranking метрики NDCG для DS
- Loss функции на собесе DS
- Подготовка к собесу Data Scientist
FAQ
Two-tower vs cross-attention?
Two-tower — independent encoding, score = dot. Cross-attention — joint encoding, гораздо точнее, но не масштабируется на retrieval (нельзя предпосчитать item embeddings).
В production — two-tower для retrieval (millions), cross-encoder для re-ranking (десятки кандидатов).
Как работать с user history?
User tower принимает sequence — последние N items. Можно через mean pooling, LSTM, attention (как в SASRec).
Это официальная информация?
Нет. Статья основана на работах (Huang 2013 DSSM, YouTube ranking 2016, Yi 2019 sampling-bias).
Тренируйте Data Science — откройте тренажёр с 1500+ вопросами для собесов.