Guide
Créer un système de recommandation en Python : les étapes
Construire un système de recommandation en Python se fait en cinq étapes : réunir les données, construire un premier modèle par contenu, ajouter le filtrage collaboratif, évaluer les résultats, puis servir les recommandations en production. Les trois premières tiennent en quelques dizaines de lignes avec pandas, scikit-learn et la bibliothèque implicit. La dernière est celle qui demande le plus de travail. Voici chaque étape, avec le code.
Quelles données faut-il pour un système de recommandation ?
Deux tables suffisent pour commencer :
- Le catalogue : un identifiant par article, un titre, une description, et les attributs utiles (catégorie, marque, genre).
- Les interactions : qui a vu, cliqué, ajouté au panier ou acheté quoi, et quand. Ce sont des signaux implicites : on ne demande rien à l’utilisateur, on observe. On leur donne souvent un poids, par exemple 1 pour une vue et 5 pour un achat.
Pas besoin de notes explicites (les étoiles) : la plupart des sites n’en ont presque pas, et les signaux implicites sont bien plus nombreux.
Étape 1 : un premier modèle par contenu avec scikit-learn
Le filtrage par contenu recommande des articles proches de celui que l’on regarde. Il fonctionne sans aucun historique, ce qui en fait le bon point de départ. On vectorise les textes avec TF-IDF, puis on compare les vecteurs :
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kernel
items = pd.read_csv("items.csv") # item_id, title, description
text = items["title"].fillna("") + " " + items["description"].fillna("")
matrix = TfidfVectorizer(min_df=2).fit_transform(text)
similarity = linear_kernel(matrix, matrix) # vecteurs normalisés : cosinus
def similar_items(index, k=5):
best = similarity[index].argsort()[::-1]
best = [i for i in best if i != index][:k]
return items.iloc[best]["item_id"].tolist()TF-IDF ne connaît que des listes de mots vides en anglais : pour un catalogue en français, passez votre propre liste au paramètre stop_words. Pour aller plus loin, remplacez TF-IDF par des embeddings sémantiques (par exemple avec sentence-transformers), qui rapprochent deux descriptions formulées différemment. Sur un gros catalogue, la matrice de similarité complète devient trop lourde : on stocke alors les vecteurs dans une base vectorielle et on cherche les plus proches voisins à la demande.
Étape 2 : le filtrage collaboratif avec implicit
Le filtrage collaboratif apprend du comportement : des personnes qui achètent les mêmes articles ont des goûts proches. L’algorithme ALS (Alternating Least Squares), adapté aux signaux implicites, est disponible dans la bibliothèque implicit :
import implicit
import pandas as pd
from scipy.sparse import csr_matrix
events = pd.read_csv("events.csv") # user_id, item_id, weight (vue = 1, achat = 5...)
users = events["user_id"].astype("category")
products = events["item_id"].astype("category")
user_items = csr_matrix(
(events["weight"].astype("float32"), (users.cat.codes, products.cat.codes))
)
model = implicit.als.AlternatingLeastSquares(factors=64, regularization=0.05, iterations=20)
model.fit(user_items)
user = 0
ids, scores = model.recommend(user, user_items[user], N=10, filter_already_liked_items=True)
print(products.cat.categories[ids].tolist())Les paramètres factors et regularization se règlent en évaluant le modèle (étape suivante). Gardez en tête la limite principale : un utilisateur ou un article sans interaction n’a pas de vecteur, donc pas de recommandation. C’est le problème du cold start, que l’on traite en retombant sur le contenu ou sur les articles populaires. Nous comparons ces approches en détail dans filtrage collaboratif, par contenu ou hybride.
Étape 3 : combiner les deux en un modèle hybride
Le plus simple est de normaliser les deux scores entre 0 et 1, puis de les mélanger avec un poids : score = alpha * contenu + (1 - alpha) * collaboratif. Un alpha élevé suit ce que la personne regarde maintenant, un alpha faible reflète ses goûts passés. Pour un nouvel utilisateur, on commence avec un alpha proche de 1 et on le baisse à mesure que son historique grandit.
Étape 4 : comment évaluer un système de recommandation ?
On coupe les interactions dans le temps : on entraîne sur le passé et on vérifie si le modèle retrouve ce que les utilisateurs ont fait ensuite. Une coupe aléatoire laisse fuiter le futur dans l’entraînement et donne des scores trop optimistes. Les mesures courantes :
- Precision@k et recall@k : parmi les k articles recommandés, combien ont réellement été consultés ou achetés.
- NDCG@k : tient compte de la position, une bonne recommandation en premier vaut plus qu’en dixième.
- Couverture et diversité : un modèle qui recommande toujours les dix mêmes best-sellers peut avoir une bonne précision et n’apporter rien.
Comparez toujours à une base simple, comme les articles les plus populaires : si le modèle ne fait pas mieux, il n’est pas prêt.
Étape 5 : mettre le système de recommandation en production
Un notebook qui produit de bonnes recommandations n’est pas encore un système. Il reste à :
- exposer les recommandations derrière une API, avec des temps de réponse courts ;
- collecter les événements du site en continu ;
- ré-entraîner régulièrement, sans dégrader la production si un nouveau modèle est moins bon ;
- gérer le cold start et les visiteurs anonymes ;
- mesurer quelles recommandations sont vues, cliquées et achetées.
C’est cette partie qui coûte le plus dans la durée, comme nous le détaillons dans LIKYLY vs. construire sa propre solution.
Ce que LIKYLY simplifie avec son SDK Python
Si votre objectif est d’afficher des recommandations plutôt que d’exploiter un moteur, le SDK Python LIKYLY remplace les étapes 1 à 5 par trois appels. Il s’installe avec pip install likyly, fonctionne avec Python 3.9 ou plus récent, est entièrement typé et propose un client synchrone (Likyly) et un client asyncio (AsyncLikyly) :
import os
from likyly import Likyly
# Côté serveur uniquement : la clé secrète donne accès à votre catalogue.
likyly = Likyly(api_key=os.environ["LIKYLY_SECRET_KEY"])
# 1. Envoyer le catalogue (avec vos propres identifiants).
likyly.items.upsert_many([
{"item_id": "SKU-1", "title": "Nike Air Max", "description": "Chaussure de running amortie"},
{"item_id": "SKU-2", "title": "Adidas Ultraboost", "description": "Chaussure de running réactive"},
])
# 2. Enregistrer ce que font les visiteurs.
likyly.events.view(user_id="user_123", item_id="SKU-1")
# 3. Demander quoi afficher : LIKYLY choisit la stratégie selon ce qu'il sait.
recs = likyly.recommendations.get(
user_id="user_123", item_id="SKU-1", placement="product_page", limit=6
)
for item in recs.items:
print(item.item_id, item.title, item.score)Vous ne choisissez pas l’algorithme : selon ce que vous envoyez (un utilisateur connu, une session anonyme, le produit affiché), LIKYLY utilise le contenu, la session, le filtrage collaboratif ou l’hybride. Les SDK pour les autres langages sont sur la page développeurs.