מבוא
תארו לעצמכם: יש לכם 500,000 משתמשים, קטלוג של 100,000 מוצרים, אבל ההמרה על המלצות היא רק 2%. הסיבה? פריטים פופולריים סטנדרטיים אינם מותאמים אישית. אנחנו פותרים זאת עם סינון שיתופי (CF), שמנתח את מטריצת האינטראקציה משתמש×מוצר ומספק תוצאות מותאמות אישית. אין צורך במידע על המוצר—רק אותות התנהגותיים. זו הסיבה ש-CF עובד במקום שבו Content-Based נכשל: בהמלצות לבגדים, ספרים, תוכן עם מטא-דאטה לא מובנה. לפי מחקר של אמזון, יישום CF מגדיל מכירות ב-20–30% בחודשים הראשונים. ניסיון היישום שלנו מראה שכיוונון משקלים נכון ובדיקות A/B יכולים להשיג עלייה יציבה ב-CTR של 30–50%.
סינון שיתופי: הליבה הטכנית והאתגרים המרכזיים
פירוק מטריצה כבסיס
CF קלאסי דרך חיפוש שכנים קרובים במכפלה סקלרית אינו ניתן להרחבה מעבר ל-100K משתמשים. הגישה העובדת היא פירוק מטריצת האינטראקציה לשני מרחבי embedding: משתמשים ופריטים מיוצגים כווקטורים במימד קבוע (בדרך כלל 64–256). ההמלצה היא מציאת פריטים שה-embedding שלהם קרוב ביותר ל-embedding של המשתמש.
ספריות לאימון: Implicit (Python, מתמחה בפידבק מרומז), LightFM (CF+תוכן היברידי), RecBole (מסגרת מחקר עם 70+ אלגוריתמים). לפריסה בייצור, אנחנו בדרך כלל בוחרים ב-Implicit + FAISS לחיפוש ANN. מבחינת מהירות, Implicit מהיר פי 3 מ-LightFM על מטריצות דלילות.
| ספרייה | סוג נתונים | מהירות אימון | גמישות | מוכנות לייצור |
|---|---|---|---|---|
| Implicit | מרומז/מפורש | ★★★★★ | ★★★ | ★★★★★ |
| LightFM | היברידי | ★★★★ | ★★★★★ | ★★★★ |
| RecBole | מחקר | ★★★ | ★★★★ | ★★★ |
איך סינון שיתופי פותר את בעיית ה-Cold Start?
משתמש חדש ללא היסטוריית אינטראקציות הוא cold start טיפוסי. פתרון סטנדרטי: עבור 5–10 האינטראקציות הראשונות, אנחנו משתמשים בכלל של "פריטים פופולריים מהקטגוריה המעניינת" (תהליך קליטה עם בחירת העדפות). לאחר צבירת היסטוריה מינימלית, אנחנו עוברים למודל המותאם אישית.
בקוד, זה נראה כמו תבנית אסטרטגיה:
// Android: стратегия рекомендаций в зависимости от истории
interface RecommendationStrategy {
suspend fun getRecommendations(userId: String, count: Int): List<Product>
}
class ColdStartStrategy(private val api: RecommendationApi) : RecommendationStrategy {
override suspend fun getRecommendations(userId: String, count: Int) = api.getPopularByPreferences(userId, count)
}
class CFStrategy(private val api: RecommendationApi) : RecommendationStrategy {
override suspend fun getRecommendations(userId: String, count: Int) = api.getPersonalized(userId, count)
}
class RecommendationRepository(private val api: RecommendationApi) {
suspend fun getRecommendations(user: User): List<Product> {
val strategy = if (user.interactionCount < 10) {
ColdStartStrategy(api)
} else {
CFStrategy(api)
}
return strategy.getRecommendations(user.id, count = 20)
}
} למה פידבק מרומז עדיף על מפורש?
ברוב האפליקציות הניידות, משתמשים לא מדרגים פריטים. פידבק מרומז—צפיות, קליקים, הוספה לעגלה, זמן שהייה בכרטיס המוצר—הוא הרבה יותר אינפורמטיבי אבל דורש שקלול נכון: צפייה ללא קליק ≠ עניין, קליק ללא רכישה ≠ שביעות רצון.
סכימת המשקלים שאנחנו משתמשים בה בפועל:
| פעולה | משקל |
|---|---|
| צפייה בכרטיס > 3 שניות | 1 |
| קליק על "פרטים" | 3 |
| הוספה למועדפים | 5 |
| הוספה לעגלה | 7 |
| רכישה | 10 |
| החזרה | -5 |
CF עם משקלים נכונים נותן עלייה ב-CTR של 30–50% בהשוואה ל-Content-Based, בהינתן מספיק נתונים. בפרויקט אחד עבור קמעונאי בגדים, יישמנו Implicit ALS עם המשקלים הנ"ל. לאחר שבועיים של בדיקות A/B, ה-CTR עלה ב-40%, וההמרה לרכישה ב-15%. אנחנו מבטיחים שעם הנתונים שלכם, התוצאה תהיה לפחות טובה באותה מידה.
רישום אירועים בצד הלקוח
האיכות של CF תלויה ישירות בשלמות ובדיוק של רישום האירועים:
// iOS: логирование взаимодействий с точностью до времени просмотра
class ProductInteractionTracker {
private var viewStartTime: Date?
private let analytics: AnalyticsService
func trackViewStart(productId: String) {
viewStartTime = Date()
}
func trackViewEnd(productId: String) {
guard let start = viewStartTime else { return }
let duration = Date().timeIntervalSince(start)
if duration > 3.0 {
analytics.log(InteractionEvent(
productId: productId,
type: .view,
weight: min(Int(duration / 3), 3),
timestamp: start
))
}
viewStartTime = nil
}
func trackAddToCart(productId: String) {
analytics.log(InteractionEvent(productId: productId, type: .addToCart, weight: 7))
}
}מעקב אחר זמן צפייה דרך // Android: стратегия рекомендаций в зависимости от истории interface RecommendationStrategy { suspend fun getRecommendations(userId: String, count: Int): List<Product> } class ColdStartStrategy(private val api: RecommendationApi) : RecommendationStrategy { override suspend fun getRecommendations(userId: String, count: Int) = api.getPopularByPreferences(userId, count) } class CFStrategy(private val api: RecommendationApi) : RecommendationStrategy { override suspend fun getRecommendations(userId: String, count: Int) = api.getPersonalized(userId, count) } class RecommendationRepository(private val api: RecommendationApi) { suspend fun getRecommendations(user: User): List<Product> { val strategy = if (user.interactionCount < 10) { ColdStartStrategy(api) } else { CFStrategy(api) } return strategy.getRecommendations(user.id, count = 20) } } מאפשר להבחין בין צפיות מקריות לעניין אמיתי. ללא האות הזה, מטריצת האינטראקציה הופכת לרועשת.
Serving: FAISS לחיפוש ANN של Embeddings
המודל המאומן מייצא את ה-embeddings של הפריטים לאינדקס FAISS. על בקשה להמלצות משתמש: קבלת ה-embedding שלו → חיפוש K פריטים קרובים ב-FAISS → סינון פריטים שכבר נרכשו → החזרת הרשימה. זמן השהיה עם 1M פריטים: 5–15 אלפיות השנייה על השרת.
ארכיטקטורת ה-Serving של FAISS
האינדקס נבנה במצב לא מקוון לאחר אימון המודל. עבור inference, אנחנו משתמשים ב-REST API (Ktor/Kotlin או Vapor/Swift). על כל בקשת משתמש, ה-embedding של המשתמש מחושב תוך כדי תנועה או נשמר במטמון. חיפוש ה-top-K מתבצע באמצעות `IndexIVFFlat` עם nprobe=10 למהירות. התוצאות עוברות עיבוד לאחר מכן: פריטים שכבר נרכשו מוסרים, ומופעלת לוגיקה עסקית (למשל, גיוון קטגוריות).מה העבודה כוללת
- ביקורת נתונים: גודל מטריצת אינטראקציות, דלילות, נוכחות cold start.
- הגדרת רישום אירועים בלקוחות iOS/Android, תוך התחשבות ב-App Store Review Guidelines וב-Google Play Console.
- אימון מודל (Implicit ALS או LightFM) על נתונים היסטוריים.
- פיתוח API להמלצות + serving עם FAISS באמצעות Ktor (Kotlin) או Vapor (Swift).
- בדיקות A/B: המלצות CF מול פריטים פופולריים → מדידת CTR והמרה.
- תיעוד והדרכת צוות.
- תמיכה לאחר ההשקה, ניטור לסטיות נתונים.
לוחות זמנים
MVP עם Implicit ALS + serving בסיסי: 2–3 שבועות. מערכת מלאה עם רישום אירועים, fallback ל-cold start, בדיקות A/B וניטור: 6–8 שבועות. העלות מחושבת באופן אישי לאחר ביקורת פרויקט. יש לנו ניסיון של למעלה מ-10 שנים בפיתוח נייד, ואנחנו מבטיחים תהליך שקוף עם הדגמות קבועות.
שפרו את ההמרה על ההמלצות שלכם — קבלו ייעוץ מהמהנדס שלנו על הגדרת CF לנתונים שלכם. הזמינו ביקורת על מטריצת האינטראקציות שלכם — נעריך את הפוטנציאל. צרו קשר כדי להתחיל את הפרויקט.







