Come Funzionano i Sistemi di Raccomandazione
I sistemi di raccomandazione sono tra le applicazioni più diffuse e redditizie del Machine Learning. Alimentano le raccomandazioni di Amazon, Netflix, Spotify, YouTube e praticamente ogni piattaforma che personalizza l'esperienza utente. L'obiettivo è predire le preferenze dell'utente e suggerire contenuti rilevanti che non ha ancora scoperto. Si stima che il 35% delle vendite di Amazon e l'80% dei contenuti visti su Netflix provengano dai sistemi di raccomandazione.
Esistono tre approcci principali: il collaborative filtering (basato sul comportamento di utenti simili), il content-based filtering (basato sulle caratteristiche degli item) e gli approcci ibridi che combinano entrambi per superare i limiti di ciascuno.
Cosa Imparerai in Questo Articolo
- Collaborative Filtering: user-based e item-based
- Content-Based Filtering: feature similarity
- Matrix Factorization: SVD e NMF
- Hybrid Systems e il Cold-Start Problem
- Metriche di valutazione: Precision@K, NDCG, RMSE
- Implementazione pratica con Python
Collaborative Filtering
Il collaborative filtering si basa sull'idea che utenti con gusti simili in passato avranno gusti simili in futuro. La user-item matrix è la struttura dati fondamentale: le righe sono gli utenti, le colonne sono gli item, e i valori sono i rating (o interazioni). Questa matrice è tipicamente molto sparsa: ogni utente ha interagito solo con una piccola frazione degli item disponibili.
Il user-based CF trova utenti simili a quello target e raccomanda item che questi utenti hanno apprezzato. L'item-based CF trova item simili a quelli apprezzati dall'utente e li raccomanda. La similarità viene misurata tipicamente con la cosine similarity o la Pearson correlation.
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
# User-Item Matrix (0 = non valutato)
# Righe: utenti, Colonne: film
ratings = np.array([
[5, 3, 0, 1, 4], # Utente 0
[4, 0, 0, 1, 5], # Utente 1
[1, 1, 0, 5, 0], # Utente 2
[0, 0, 5, 4, 0], # Utente 3
[0, 3, 4, 0, 0], # Utente 4
])
film_names = ['Matrix', 'Inception', 'Notebook', 'Titanic', 'Interstellar']
# --- USER-BASED CF ---
# Calcola similarità' tra utenti (usando solo film valutati in comune)
user_similarity = cosine_similarity(ratings)
np.fill_diagonal(user_similarity, 0) # escludi auto-similarità'
def predict_user_based(user_id, item_id, ratings, similarity, k=2):
"""Predici il rating dell'utente per un item."""
# Trova i k utenti più' simili che hanno valutato l'item
item_ratings = ratings[:, item_id]
rated_mask = item_ratings > 0
rated_mask[user_id] = False # escludi l'utente stesso
if not rated_mask.any():
return 0
sim_scores = similarity[user_id][rated_mask]
user_ratings = item_ratings[rated_mask]
# Top-k più' simili
top_k_idx = np.argsort(sim_scores)[-k:]
top_sims = sim_scores[top_k_idx]
top_ratings = user_ratings[top_k_idx]
if top_sims.sum() == 0:
return 0
return np.dot(top_sims, top_ratings) / top_sims.sum()
# Predizioni per Utente 0 su film non visti
user = 0
print(f"Raccomandazioni per Utente {user}:")
for item in range(ratings.shape[1]):
if ratings[user, item] == 0:
pred = predict_user_based(user, item, ratings, user_similarity)
print(f" {film_names[item]:<15s}: rating predetto = {pred:.2f}")
Content-Based Filtering
Il content-based filtering raccomanda item simili a quelli già apprezzati dall'utente, basandosi sulle caratteristiche degli item (genere, regista, attori per i film; artista, genere, BPM per la musica). Ogni item è rappresentato come un vettore di feature, e la similarità tra item viene calcolata con la cosine similarity. Non soffre del cold-start problem per gli item (basta conoscerne le caratteristiche), ma non riesce a raccomandare item al di fuori del profilo dell'utente.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# Database film con descrizioni
films = {
'Matrix': 'sci-fi action cyberpunk hacker virtual reality',
'Inception': 'sci-fi action dreams psychological thriller',
'Notebook': 'romance drama love story emotional',
'Titanic': 'romance drama historical ship love',
'Interstellar': 'sci-fi space exploration time gravity',
'Blade Runner': 'sci-fi cyberpunk android dystopia',
'Pride and Prejudice': 'romance historical drama society',
'Dark Knight': 'action superhero crime thriller',
}
# Crea matrice TF-IDF dalle descrizioni
film_names = list(films.keys())
descriptions = list(films.values())
tfidf = TfidfVectorizer()
tfidf_matrix = tfidf.fit_transform(descriptions)
# Calcola similarità' tra tutti i film
item_similarity = cosine_similarity(tfidf_matrix)
def recommend_content_based(liked_films, all_films, similarity, n=3):
"""Raccomanda film simili a quelli apprezzati."""
liked_idx = [all_films.index(f) for f in liked_films if f in all_films]
# Media della similarità' con i film apprezzati
scores = np.zeros(len(all_films))
for idx in liked_idx:
scores += similarity[idx]
scores /= len(liked_idx)
# Escludi film gia' visti
for idx in liked_idx:
scores[idx] = -1
# Top-N raccomandazioni
top_idx = np.argsort(scores)[::-1][:n]
return [(all_films[i], scores[i]) for i in top_idx]
# Raccomanda basandosi sui film apprezzati
liked = ['Matrix', 'Interstellar']
recs = recommend_content_based(liked, film_names, item_similarity)
print(f"Ti sono piaciuti: {liked}")
print("Raccomandazioni:")
for film, score in recs:
print(f" {film:<25s} (score: {score:.3f})")
Matrix Factorization: SVD
La Matrix Factorization scompone la user-item matrix sparsa in due matrici dense a bassa dimensionalità: una per gli utenti e una per gli item. Il prodotto di queste matrici approssima la matrice originale e riempie i valori mancanti con predizioni. SVD (Singular Value Decomposition) e NMF (Non-negative Matrix Factorization) sono le tecniche più usate. I fattori latenti catturano concetti astratti come i generi preferiti o lo stile narrativo.
Il Cold-Start Problem
Il cold-start problem è la sfida più grande dei sistemi di raccomandazione: come raccomandare a un nuovo utente di cui non conosciamo le preferenze? Come raccomandare un nuovo item che nessuno ha ancora valutato? Le soluzioni includono: chiedere preferenze iniziali (onboarding quiz), usare informazioni demografiche, combinare content-based (che non soffre del cold-start per gli item) con collaborative filtering, e usare popularity-based recommendations come fallback.
Collaborative vs Content-Based: Il collaborative filtering scopre preferenze inaspettate (serendipity) ma soffre del cold-start. Il content-based non richiede dati sugli altri utenti ma resta confinato nel profilo dell'utente (filter bubble). I sistemi ibridi combinano i punti di forza di entrambi e sono la scelta standard nell'industria.
Metriche di Valutazione
Le metriche per i sistemi di raccomandazione si dividono in metriche di rating prediction (RMSE, MAE) e metriche di ranking (Precision@K, Recall@K, NDCG). Precision@K misura quanti degli item raccomandati nei top-K sono rilevanti. NDCG (Normalized Discounted Cumulative Gain) tiene conto della posizione: un item rilevante in prima posizione vale più di uno in decima. Hit Rate misura la probabilità che almeno un item rilevante appaia nelle raccomandazioni.
Punti Chiave
- Collaborative Filtering sfrutta utenti simili; Content-Based sfrutta feature degli item
- La cosine similarity è la metrica standard per misurare la similarità
- Matrix Factorization (SVD) scompone la user-item matrix in fattori latenti
- Il cold-start problem richiede strategie ibride e fallback intelligenti
- Precision@K e NDCG sono le metriche più importanti per valutare le raccomandazioni
- I sistemi ibridi (collaborative + content-based) sono lo standard industriale







