Comment comparer une requête à chaque document
Le modèle vectoriel représente chaque document et chaque requête par une liste de nombres, un nombre par mot du vocabulaire. Le cosinus de l’angle entre deux listes dit à quel point elles se ressemblent.
Une étudiante tape « restaurant ouvre ». Le moteur doit classer les fiches de la plus proche à la plus lointaine, même si aucune ne contient exactement ces deux mots.
À la fin de cette leçon
Remarque
Je peux classer des documents selon l’angle entre leur vecteur et celui de la requête.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Vocabulaire | la liste de mots qui fixe les positions du vecteur | |
| Vecteur | une liste de nombres, un par mot du vocabulaire | [1, 0, 1, 0] |
| Produit scalaire | la somme des produits, position par position | |
| Norme | la longueur d’un vecteur | |
| Similarité cosinus | le produit scalaire divisé par les deux normes |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un document devient une liste de comptes
On choisit un vocabulaire, ici quatre mots : restaurant, bibliotheque, ouvre, trois. Le vecteur d’un texte donne le nombre d’apparitions de chaque mot, dans cet ordre.
La requête est traitée comme un petit document : « restaurant ouvre » devient [1, 0, 1, 0].
Exemple travaillé : quatre documents en vecteurs
| Document | restaurant | bibliotheque | ouvre | trois | Vecteur |
|---|---|---|---|---|---|
| 0 : le restaurant universitaire ouvre a midi | 1 | 0 | 1 | 0 | [1, 0, 1, 0] |
| 1 : la bibliotheque universitaire ouvre a huit heures | 0 | 1 | 1 | 0 | [0, 1, 1, 0] |
| 2 : le restaurant propose un menu a trois euros | 1 | 0 | 0 | 1 | [1, 0, 0, 1] |
| 3 : la bibliotheque prete un livre pour trois semaines | 0 | 1 | 0 | 1 | [0, 1, 0, 1] |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Le cosinus mesure l’angle entre deux vecteurs
Le produit scalaire multiplie deux vecteurs position par position, puis additionne. La norme est la racine carrée de la somme des carrés.
La similarité cosinus est le produit scalaire divisé par les deux normes. Elle vaut 1 pour la même direction et 0 sans mot commun. La longueur du texte ne joue pas.
Exemple travaillé : les quatre cosinus
| Document | Produit scalaire | Normes | Cosinus |
|---|---|---|---|
| 0 : [1, 0, 1, 0] | 2 | 1,41 et 1,41 | 2 / 2 = 1 |
| 1 : [0, 1, 1, 0] | 1 | 1,41 et 1,41 | 1 / 2 = 0,5 |
| 2 : [1, 0, 0, 1] | 1 | 1,41 et 1,41 | 1 / 2 = 0,5 |
| 3 : [0, 1, 0, 1] | 0 | 1,41 et 1,41 | 0 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Calculer un cosinus de deux vecteurs
docker exec jupyter python3 -c 'print(round(sum(x * y for x, y in zip([1, 0, 1, 0], [0, 1, 1, 0])) / (2 ** 0.5 * 2 ** 0.5), 2))'Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Une erreur fréquente
Attention
Beaucoup pensent que le produit scalaire seul suffit pour classer. Un long document a des comptes plus grands et gagnerait toujours. Diviser par les normes ne garde que les proportions de mots.
Calculer un cosinus pas à pas
vocabulaire = ["restaurant", "bibliotheque", "ouvre", "trois"]
requete = "restaurant ouvre".split()
document = "la bibliotheque universitaire ouvre a huit heures".split()
a = []
b = []
for mot in vocabulaire:
a.append(requete.count(mot))
b.append(document.count(mot))
produit = 0
for n in range(len(a)):
produit = produit + a[n] * b[n]
norme_a = (a[0] ** 2 + a[1] ** 2 + a[2] ** 2 + a[3] ** 2) ** 0.5
norme_b = (b[0] ** 2 + b[1] ** 2 + b[2] ** 2 + b[3] ** 2) ** 0.5
print(a, b)
print(round(produit / (norme_a * norme_b), 2))
# Remplacez le document par "le restaurant universitaire ouvre a midi", puis relancez.
Classer, c’est trier les documents par cosinus décroissant
On calcule le cosinus de la requête avec chaque document, puis on met le plus grand en tête. En cas d’égalité, on garde l’ordre des numéros.
Dans notre exemple, le document 0 arrive premier avec 1. Les documents 1 et 2 suivent à égalité à 0,5, et le 3 ferme la marche avec 0.
Pour aller plus loin
Dans un carnet de JupyterLab, choisissez un vocabulaire de cinq mots et vos six phrases. Calculez le cosinus de deux requêtes avec chaque phrase.
Les égalités sont-elles fréquentes ? Ajoutez un mot au vocabulaire : le classement change-t-il ?