Ranking et search engine

Links: notebook, html, PDF, python, slides, GitHub

C’est un petit exemple de ranking avec un très petit jeu de données, trop petit pour que le modèle soit performant, mais le code peut être réutilisé pour des exemples de taille raisonnable. C’est à dire probablement pas pour apprendre un moteur de recherche.

%matplotlib inline
from papierstat.datasets import load_search_engine_dataset
X, y, qid = load_search_engine_dataset()
X[:5,:6].todense()
matrix([[3., 3., 0., 0., 3., 1.],
        [3., 0., 3., 0., 3., 1.],
        [3., 0., 2., 0., 3., 1.],
        [3., 0., 3., 0., 3., 1.],
        [3., 0., 3., 0., 3., 1.]])
X.shape
(582, 136)

Le tableau qid contient l’identifiant de la requête, toutes les lignes associées à un identifiant correspondent à des résultats associés à cette requête. Dans ce jeu, il y a 7 requêtes distinctes.

set(qid)
{1, 16, 31, 46, 61, 76, 91}

On peut essayer d’abord XGBoost. Ce petit jeu de données est aussi disponible sur github/papierstat/datasets/data.

X_train, y_train, qid_train = load_search_engine_dataset()
import pandas
df = pandas.DataFrame(qid_train)
df['c'] = 1
df.columns = ['qid', 'c']
gr_train = df.groupby('qid').count()
gr_train
c
qid
1 86
16 106
31 92
46 120
61 59
76 45
91 74
from xgboost import DMatrix
dtrain = DMatrix(data=X_train, label=y_train)
dtrain.set_group(gr_train.values)
from xgboost import XGBRegressor, train
rk = train(params={'objective': 'rank:ndcg'}, dtrain=dtrain, num_boost_round=10)
X_test, y_test, qid_test = load_search_engine_dataset(False)
import pandas
df = pandas.DataFrame(qid_test)
df['c'] = 1
df.columns = ['qid', 'c']
gr_test = df.groupby('qid').count()
dtest = DMatrix(data=X_test)
dtest.set_group(gr_test.values)
pred = rk.predict(dtest)

On peut calculer l’erreur au carré.

from sklearn.metrics import mean_squared_error
mean_squared_error(y_test, pred)
0.9505686427514932

Mais cela n’est valable que si le score a un sens, ce qui est le cas ici. Si ce n’est pas le cas, il est possible d’évaluer les résultats avec la corrélation des rangs des résultats (coefficient de Kendall). Le module lightgbm est une autre option.

from lightgbm import LGBMRanker

model = LGBMRanker()
model.fit(X_train, y_train, group=gr_train.values.flatten())
LGBMRanker()
Epred = model.predict(X_test.toarray())
Epred[:5]
array([-5.23613848, -1.07701321, -4.46995424, -3.28967461, -1.87554731])

Autre option lightfm (article : Learning to Rank Sketchfab Models with LightFM). scikit-learn ne propose pas de modèle de ranking, il faut implémenter soi-même la transformation des données.