Aller au contenu

Bloc B — Classer⚓︎

Au programme

Le plus proche voisin · écrire un classifieur · frontière de décision · données d'entraînement et de test · le surapprentissage

Séances 2 et 3

Séance 2 : écrire un classifieur qui apprend d'exemples. Séance 3 : mesurer s'il a vraiment appris.

L'idée du plus proche voisin⚓︎

Comment classer une nouvelle pomme ou orange sans écrire de règle ? L'idée la plus simple qui soit :

Le principe

Pour deviner l'étiquette d'un nouveau fruit, on cherche, parmi les exemples connus, celui qui lui ressemble le plus — et on lui donne la même étiquette.

« Se ressembler », ici, veut dire : avoir des mesures proches.

C'est l'algorithme du plus proche voisin. Il n'y a rien de plus dans beaucoup de systèmes réels — juste en plus grand.

Mesurer une ressemblance⚓︎

Nos fruits ont deux mesures : masse et rugosité. Chaque fruit est donc un point. Deux fruits se ressemblent si leurs points sont proches.

La distance entre deux points se calcule comme à l'école — le théorème de Pythagore, croisé en M0 :

Activité 1 — La distance

🐍 Script Python
def distance(a, b):
    return ((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) ** 0.5


orange = [150, 7]
pomme = [130, 2]
inconnu = [145, 6]

print("distance à l'orange :", round(distance(inconnu, orange), 1))
print("distance à la pomme :", round(distance(inconnu, pomme), 1))
Résultat
📋 Texte
distance à l'orange : 5.1
distance à la pomme : 15.5

L'inconnu est trois fois plus proche de l'orange. On parierait donc : orange.

Le ** 0.5

Élever à la puissance 0,5, c'est prendre la racine carrée. On retrouve le calcul de Pythagore vu en M0 — appliqué ici non pas à une figure, mais à une ressemblance.

Écrire le classifieur⚓︎

À toi de jouer B.1 ⭐⭐⭐

Écris classer(point, exemples) qui renvoie l'étiquette de l'exemple le plus proche du point.

Indice : c'est le schéma du minimum de M0, mais on garde l'exemple qui réalise le minimum, pas seulement la distance.

Corrigé
🐍 Script Python
exemples = [
 [150, 7, "orange"], [170, 8, "orange"], [140, 6, "orange"], [160, 9, "orange"],
 [130, 2, "pomme"],  [145, 3, "pomme"],  [120, 1, "pomme"],  [155, 2, "pomme"]]


def classer(point, exemples):
    meilleur = exemples[0]
    d_min = distance(point, meilleur)
    for exemple in exemples:
        d = distance(point, exemple)
        if d < d_min:
            d_min = d
            meilleur = exemple
    return meilleur[2]
📋 Texte
>>> classer([135, 2], exemples)
'pomme'
>>> classer([165, 8], exemples)
'orange'
>>> classer([148, 5], exemples)
'orange'

Tu viens d'écrire une IA

Ce programme apprend d'exemples : change les exemples, et il classe différemment, sans qu'une seule ligne de code soit modifiée.

C'est la différence du bloc A, rendue concrète : la connaissance n'est pas dans le code, elle est dans les données.

Le lien avec M0

Compare avec la fonction maximum de M0 : on parcourt, on garde le meilleur candidat, on le renvoie. C'est exactement le même schéma. Un classifieur, c'est une recherche de minimum.

Voir ce que le modèle a appris⚓︎

On peut visualiser la décision du classifieur sur tout l'espace : pour chaque combinaison de masse et de rugosité, quelle étiquette donne-t-il ?

Activité 2 — La frontière de décision

🐍 Script Python
def frontiere(exemples):
    for rugosite in range(10, -1, -1):
        ligne = ""
        for masse in range(115, 176, 5):
            if classer([masse, rugosite], exemples) == "orange":
                ligne = ligne + "O"
            else:
                ligne = ligne + "."
        print(str(rugosite).rjust(2), ligne)


frontiere(exemples)
Résultat
📋 Texte
10 ....OOOOOOOOO
 9 ....OOOOOOOOO
 8 ....OO.OOOOOO
 7 ....OO.OOOOOO
 6 ....OO.O.OOOO
 5 ....OO.O.OOOO
 4 ....OO.O.OOOO
 3 .....O.O..OOO
 2 .....O.O..OOO
 1 .....O....OOO
 0 ..........OOO

Les O sont les zones classées « orange », les . les zones « pomme ». On voit la frontière que le modèle a construite — sans qu'on l'ait dessinée.

Regarde les irrégularités

La frontière n'est pas une ligne nette. Il y a des O isolés au milieu des ., des découpes bizarres.

Ce sont les endroits où un exemple particulier « attire » son voisinage. Le modèle n'a pas dégagé une loi générale : il a mémorisé des cas, et la frontière porte la trace de chaque exemple.

Cette observation prépare directement la notion de surapprentissage.

Entraîner et tester⚓︎

Séance 3

Voici la question qui distingue une démarche sérieuse d'une illusion : comment sait-on que le modèle a vraiment appris ?

La faute méthodologique à ne jamais commettre

On ne teste jamais un modèle sur les exemples qui ont servi à l'entraîner.

Pourquoi ? Parce que le plus proche voisin d'un exemple d'entraînement, c'est lui-même (distance nulle). Testé sur ses propres données, ce classifieur a toujours 100 % de réussite — et cela ne prouve rien.

C'est comme réviser un contrôle avec le corrigé sous les yeux : réussir ne dit rien de ce qu'on a compris.

La règle

On sépare les exemples en deux groupes :

  • les données d'entraînement : le modèle les connaît, il apprend dessus ;
  • les données de test : le modèle ne les a jamais vues, on mesure sa réussite dessus.

Seule la réussite sur les données de test compte.

À toi de jouer B.2 ⭐⭐

Écris evaluer(entrainement, test) qui renvoie le nombre de bonnes réponses sur les données de test.

Corrigé
🐍 Script Python
def evaluer(entrainement, test):
    bons = 0
    for point in test:
        prediction = classer(point, entrainement)
        if prediction == point[2]:
            bons = bons + 1
    return bons, len(test)


entrainement = exemples[:6]
test = [[140, 6, "orange"], [125, 2, "pomme"]]

print(evaluer(entrainement, test))
📋 Texte
(2, 2)

Deux bonnes réponses sur deux : le modèle généralise — il classe correctement des fruits qu'il n'avait jamais vus.

Le vocabulaire officiel

  • Entraîner (ou apprendre) : construire le modèle à partir des données d'entraînement.
  • Tester (ou évaluer) : mesurer sa réussite sur des données réservées.
  • Généraliser : bien fonctionner sur des données nouvelles. C'est le seul but qui compte.

Le surapprentissage⚓︎

Activité 3 — Le piège

Un élève propose : « Pour être sûr d'avoir un bon modèle, mettons tous les exemples dans l'entraînement. Plus il en voit, mieux c'est. »

Où est le problème ?

Corrigé

Il ne reste alors aucune donnée de test. On ne peut plus mesurer si le modèle généralise — on est revenu à réviser avec le corrigé.

Le problème plus profond s'appelle le surapprentissage (overfitting) : un modèle qui colle trop exactement à ses exemples d'entraînement.

Repense à la frontière de décision, avec ses O isolés. Un modèle qui mémorise chaque cas particulier reproduit parfaitement l'entraînement mais se trompe sur les données nouvelles, parce qu'il a appris les détails — y compris les accidents — au lieu de la tendance.

L'analogie qui marche

Un élève qui apprend par cœur les corrigés des exercices du manuel aura 20/20 sur ces exercices précis, et échouera au contrôle sur des exercices légèrement différents.

Un élève qui comprend la méthode réussira les deux.

Un bon modèle est comme le second : il a dégagé la règle, pas mémorisé les cas. Et la seule façon de faire la différence, c'est de tester sur des données nouvelles.

Ce qu'il faut retenir⚓︎

L'essentiel du bloc B

  • Le plus proche voisin classe un point comme l'exemple connu qui lui ressemble le plus.
  • Un classifieur est une recherche de minimum — le même schéma que maximum en M0.
  • La connaissance est dans les données, pas dans le code : changer les exemples change les décisions.
  • On entraîne sur un groupe de données, on teste sur un autre, jamais vu. Seul le test compte.
  • Un modèle qui colle trop à ses exemples fait du surapprentissage : il mémorise au lieu de généraliser.