{
  "chapter": {
    "id": "knn",
    "level": "premiere",
    "theme": "Algorithmique",
    "title": "k plus proches voisins (k-NN)",
    "description": "Algorithme des k plus proches voisins (k-NN) : exemple\nd'algorithme d'apprentissage supervisé. Distance entre\npoints, vote majoritaire, choix de k, applications,\nforces et limites.",
    "prerequisites": [],
    "references": []
  },
  "questions": [
    {
      "id": "q01",
      "difficulty": 1,
      "skills": [
        "definition"
      ],
      "title": "k-NN : qu'est-ce que c'est ?",
      "statement": "Que fait l'algorithme des **k plus proches voisins**\n(k-NN, *k-Nearest Neighbors*) ?",
      "options": [
        {
          "text": "Prédire la classe d'un point selon ses voisins",
          "correct": true,
          "feedback": "Bonne réponse : c'est un algorithme\nd'**apprentissage supervisé** par\nmémorisation. On classe un nouveau point\nselon ses voisins.\n"
        },
        {
          "text": "Mesure la complexité d'un programme",
          "correct": false,
          "feedback": "Erreur : la mesure de\ncomplexité algorithmique\nn'a aucun rapport avec\nl'algorithme des k plus\nproches voisins.\n"
        },
        {
          "text": "Cherche un élément dans une liste triée",
          "correct": false,
          "feedback": "Erreur : c'est la recherche dichotomique.\n"
        },
        {
          "text": "Trie une liste par ordre croissant",
          "correct": false,
          "feedback": "Erreur : aucun rapport avec le tri.\n"
        }
      ],
      "explanation": "Apprentissage supervisé : on dispose d'exemples\nétiquetés (avec leur classe connue), on\napprend à prédire la classe pour de nouveaux\nexemples."
    },
    {
      "id": "q02",
      "difficulty": 1,
      "skills": [
        "supervisé"
      ],
      "title": "Apprentissage supervisé",
      "statement": "Pourquoi parle-t-on d'apprentissage\n**supervisé** pour k-NN ?",
      "options": [
        {
          "text": "Parce qu'il est lent à l'exécution",
          "correct": false,
          "feedback": "La rapidité d'exécution n'a\naucun rapport avec le\ncaractère supervisé d'un\nalgorithme d'apprentissage.\n"
        },
        {
          "text": "Parce qu'il ne fonctionne qu'avec un professeur dans la salle",
          "correct": false,
          "feedback": "Cette interprétation est\nfantaisiste. Le mot\n« supervisé » est un terme\ntechnique précis, sans\nrapport avec une\nprésence humaine.\n"
        },
        {
          "text": "Parce qu'un humain doit surveiller le programme pendant son exécution",
          "correct": false,
          "feedback": "Cette interprétation littérale\nne correspond pas au sens\ntechnique. En apprentissage\nautomatique, « supervisé »\nrenvoie au fait que les\ndonnées portent une\nétiquette connue, et non à\nune surveillance humaine.\n"
        },
        {
          "text": "Les données d'entraînement sont étiquetées",
          "correct": true,
          "feedback": "Bonne réponse : « supervisé » = on a la\nréponse pour les exemples\nd'entraînement. L'algorithme apprend la\nrelation entrée → classe.\n"
        }
      ],
      "explanation": "Distinction : **supervisé** (avec étiquettes,\nex. classification, régression) vs **non supervisé** (sans étiquettes, ex.\npartitionnement automatique). k-NN est\nsupervisé."
    },
    {
      "id": "q03",
      "difficulty": 1,
      "skills": [
        "distance"
      ],
      "title": "Distance euclidienne",
      "statement": "Comment calcule-t-on la **distance euclidienne**\nentre deux points $A=(x_A, y_A)$ et $B=(x_B,\ny_B)$ du plan ?",
      "options": [
        {
          "text": "$d = \\sqrt{(x_B - x_A)^2 + (y_B - y_A)^2}$",
          "correct": true,
          "feedback": "Bonne réponse : formule de Pythagore.\nC'est la distance « à vol d'oiseau »\nentre les deux points.\n"
        },
        {
          "text": "$d = (x_B - x_A)^2 + (y_B - y_A)^2$",
          "correct": false,
          "feedback": "Erreur : c'est le **carré** de la distance,\nil manque la racine carrée. Comparer des\ncarrés de distances reste possible pour\nk-NN, mais ce n'est pas la distance.\n"
        },
        {
          "text": "$d = \\sqrt{(x_B - x_A) + (y_B - y_A)}$",
          "correct": false,
          "feedback": "Erreur : sans les carrés, les écarts\nnégatifs se compensent et l'expression\nsous la racine peut être négative.\n"
        },
        {
          "text": "$d = |x_B - x_A| + |y_B - y_A|$",
          "correct": false,
          "feedback": "Erreur : c'est la distance de Manhattan\n(somme des écarts absolus), une autre\ndistance possible, mais pas l'euclidienne.\n"
        }
      ],
      "explanation": "Cette formule se généralise en dimension n :\n$d = \\\\sqrt{\\\\sum_{i=1}^{n}(b_i - a_i)^2}$.\nPour comparer des distances, on peut omettre\nla racine carrée."
    },
    {
      "id": "q04",
      "difficulty": 1,
      "skills": [
        "vote-majoritaire"
      ],
      "title": "Vote majoritaire",
      "statement": "Une fois les k plus proches voisins\nidentifiés, comment k-NN détermine-t-il la\nclasse à attribuer ?",
      "options": [
        {
          "text": "Au hasard",
          "correct": false,
          "feedback": "Erreur : k-NN est déterministe.\n"
        },
        {
          "text": "En choisissant la classe du voisin le plus proche",
          "correct": false,
          "feedback": "C'est k-NN avec k = 1, cas particulier. En\ngénéral on utilise plusieurs voisins pour\nplus de robustesse.\n"
        },
        {
          "text": "Par vote majoritaire parmi les k voisins",
          "correct": true,
          "feedback": "Bonne réponse : si parmi les 5 voisins\nles plus proches, 3 sont de la classe A et\n2 de la classe B, on prédit A.\n"
        },
        {
          "text": "En faisant la moyenne des classes",
          "correct": false,
          "feedback": "Erreur : on ne fait pas la moyenne d'une\nclasse (c'est une catégorie, pas un\nnombre).\n"
        }
      ],
      "explanation": "Variante : **vote pondéré** par la distance\n(les voisins plus proches comptent plus).\nPermet de gérer les ex æquo."
    },
    {
      "id": "q05",
      "difficulty": 1,
      "skills": [
        "choix-k"
      ],
      "title": "Choix de k",
      "statement": "Pourquoi prend-on souvent k **impair** quand\non classe en deux classes ?",
      "options": [
        {
          "text": "Pour éviter les égalités lors du vote",
          "correct": true,
          "feedback": "Bonne réponse : avec k pair (par exemple\nk = 4), on peut avoir 2 votes pour chaque\nclasse → indécision. Avec k impair (k = 5),\nimpossible.\n"
        },
        {
          "text": "Aucune raison particulière",
          "correct": false,
          "feedback": "Cette parité répond au\ncontraire à un besoin\ntechnique précis : éviter\nles égalités lors du\nvote, comme expliqué dans\nla bonne réponse.\n"
        },
        {
          "text": "Parce que les nombres impairs sont plus rapides à calculer",
          "correct": false,
          "feedback": "Aucun lien n'existe entre la\nparité d'un nombre et la\nrapidité de calcul.\n"
        },
        {
          "text": "Parce que k pair ne fonctionne pas",
          "correct": false,
          "feedback": "Erreur : ça fonctionne, mais on doit gérer\nles ex æquo.\n"
        }
      ],
      "explanation": "Pour trois classes ou plus, un\n$k$ impair n'évite pas\nforcément les ex æquo : trois\nclasses peuvent par exemple\nobtenir chacune $k/3$ voix.\nOn peut alors recourir à la\nclasse du voisin le plus\nproche, ou à un vote pondéré\npar la distance."
    },
    {
      "id": "q06",
      "difficulty": 1,
      "skills": [
        "exemple-iris"
      ],
      "title": "Exemple typique",
      "statement": "Lequel de ces problèmes est un **bon candidat**\npour l'algorithme k-NN ?",
      "options": [
        {
          "text": "Compresser un fichier pour gagner de la place",
          "correct": false,
          "feedback": "La compression de fichiers\nest une tâche très\ndifférente, sans rapport\navec la classification.\n"
        },
        {
          "text": "Trier une liste de nombres",
          "correct": false,
          "feedback": "Erreur : ce n'est pas un problème de\nclassification.\n"
        },
        {
          "text": "Reconnaître un spam à partir d'exemples",
          "correct": true,
          "feedback": "Bonne réponse : tâche de classification\nbinaire (spam / non spam). On peut\ncomparer le mail aux exemples connus\nselon des caractéristiques (mots-clés,\nlongueur, etc.).\n"
        },
        {
          "text": "Calculer la racine carrée exacte d'un nombre",
          "correct": false,
          "feedback": "Erreur : pas un problème d'apprentissage.\n"
        }
      ],
      "explanation": "Autres exemples : reconnaissance de\nchiffres manuscrits, classification de\nfleurs (jeu de données Iris), recommandation\nde films."
    },
    {
      "id": "q07",
      "difficulty": 1,
      "skills": [
        "absence-apprentissage"
      ],
      "title": "Pas d'entraînement explicite",
      "statement": "Quelle particularité de k-NN le distingue\nd'autres algorithmes d'apprentissage ?",
      "options": [
        {
          "text": "Presque aucun entraînement, calcul à la prédiction",
          "correct": true,
          "feedback": "Bonne réponse : k-NN est un algorithme\ndit « paresseux ». Pas de modèle interne ;\ntout le travail est fait à la prédiction.\n"
        },
        {
          "text": "Il fonctionne sans aucune donnée d'entraînement",
          "correct": false,
          "feedback": "Au contraire, l'algorithme\na besoin d'exemples\nétiquetés pour pouvoir\ncomparer le nouveau\npoint.\n"
        },
        {
          "text": "Il a une phase d'entraînement très longue",
          "correct": false,
          "feedback": "Erreur : c'est l'inverse. La phase\nd'entraînement consiste juste à\n**mémoriser** les exemples.\n"
        },
        {
          "text": "Il invente de nouveaux exemples au cours de la prédiction",
          "correct": false,
          "feedback": "Aucun exemple n'est\ninventé. L'algorithme se\ncontente de comparer le\npoint à classer aux\nexemples déjà connus.\n"
        }
      ],
      "explanation": "Conséquence : prédiction lente quand le jeu\nd'entraînement est gros (il faut calculer la\ndistance à tous les exemples). Compromis :\nstockage important, calcul à la prédiction."
    },
    {
      "id": "q08",
      "difficulty": 1,
      "skills": [
        "pseudocode"
      ],
      "title": "Squelette de l'algorithme",
      "statement": "Quelle est la **structure générale** de\nl'algorithme k-NN pour classer un nouveau\npoint `p` ?",
      "options": [
        {
          "text": "1. Calculer la distance de `p` à chaque exemple connu.\n2. Trier les exemples par distance croissante.\n3. Garder les k premiers.\n4. Retourner la classe majoritaire parmi ces k voisins.\n",
          "correct": true,
          "feedback": "Bonne réponse : algorithme en quatre\nétapes claires. Les étapes 1 et 2\ndominent le coût.\n"
        },
        {
          "text": "1. Calculer la distance de `p` à chaque exemple connu.\n2. Trier les exemples par distance décroissante.\n3. Garder les k premiers.\n4. Retourner la classe majoritaire parmi ces k voisins.\n",
          "correct": false,
          "feedback": "Erreur : trié par distance décroissante,\nles k premiers sont les k exemples les\nplus **éloignés** de `p`, l'inverse de ce\nque l'on veut.\n"
        },
        {
          "text": "1. Calculer la distance de `p` à chaque exemple connu.\n2. Trier les exemples par distance croissante.\n3. Garder les k premiers.\n4. Retourner la classe du plus proche d'entre eux.\n",
          "correct": false,
          "feedback": "Erreur : retourner la classe du seul plus\nproche voisin revient à prendre k = 1 ; le\nvote majoritaire parmi les k voisins est\njustement ce qui rend k-NN robuste au\nbruit.\n"
        },
        {
          "text": "1. Calculer la moyenne des exemples de chaque classe.\n2. Calculer la distance de `p` à chacune de ces moyennes.\n3. Garder la moyenne la plus proche.\n4. Retourner sa classe.\n",
          "correct": false,
          "feedback": "Erreur : c'est un autre algorithme (le\nplus proche centre). k-NN ne calcule\naucune moyenne : il compare `p` aux\nexemples eux-mêmes.\n"
        }
      ],
      "explanation": "En Python, on utilise typiquement :\n```python\ndistances = [(dist(p, e), c) for (e, c) in exemples]\ndistances.sort()\nvoisins = distances[:k]\n```"
    },
    {
      "id": "q09",
      "difficulty": 1,
      "skills": [
        "parametres"
      ],
      "title": "Paramètre k",
      "statement": "Que se passe-t-il si l'on prend **k = 1** ?",
      "options": [
        {
          "text": "La classe du seul voisin, très sensible au bruit",
          "correct": true,
          "feedback": "Bonne réponse : un seul exemple aberrant\npeut fausser la prédiction. Augmenter k\nrend la décision plus robuste.\n"
        },
        {
          "text": "La complexité du calcul devient alors logarithmique",
          "correct": false,
          "feedback": "Le coût d'un calcul de\nprédiction ne dépend pas\ndu choix de $k$ : il\nreste linéaire en\n$N$ (nombre d'exemples).\n"
        },
        {
          "text": "La prédiction est plus stable",
          "correct": false,
          "feedback": "Erreur : c'est l'inverse. k = 1 est très\nsensible au bruit.\n"
        },
        {
          "text": "L'algorithme ne fonctionne pas avec $k = 1$",
          "correct": false,
          "feedback": "Le choix $k = 1$ est tout\nà fait valide d'un point\nde vue algorithmique. Il\nest simplement peu\nrobuste face au bruit\ndes données.\n"
        }
      ],
      "explanation": "Choix de k : compromis. k trop petit →\nsensibilité au bruit. k trop grand → frontières\nlissées, perte de précision locale. On choisit\nsouvent k empiriquement."
    },
    {
      "id": "q10",
      "difficulty": 1,
      "skills": [
        "exemple-trace"
      ],
      "title": "Trace simple",
      "statement": "Avec k = 3, on classe un nouveau point P. Ses\n3 plus proches voisins ont les classes : A, B,\nA. Quelle classe prédit k-NN pour P ?",
      "options": [
        {
          "text": "Aucune des deux (égalité)",
          "correct": false,
          "feedback": "Erreur : il n'y a pas d'égalité (2 vs 1).\n"
        },
        {
          "text": "B (le plus proche)",
          "correct": false,
          "feedback": "Erreur : ce serait k = 1. Avec k = 3, on\nfait un vote majoritaire.\n"
        },
        {
          "text": "A (deux votes contre un pour B)",
          "correct": true,
          "feedback": "Bonne réponse : vote majoritaire. A\nobtient 2 votes, B obtient 1. La classe\nprédite est A.\n"
        },
        {
          "text": "Les deux à la fois",
          "correct": false,
          "feedback": "Erreur : k-NN renvoie une seule classe.\n"
        }
      ],
      "explanation": "Le vote est très simple à implémenter en\nPython : `Counter([cl for (_, cl) in\nvoisins]).most_common(1)[0][0]`."
    },
    {
      "id": "q11",
      "difficulty": 2,
      "skills": [
        "code-distance"
      ],
      "title": "Code distance",
      "statement": "Quel code calcule correctement la **distance euclidienne** entre deux points 2D représentés\ncomme tuples `a = (xa, ya)` et `b = (xb, yb)` ?",
      "options": [
        {
          "text": "`((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) ** 0.5`",
          "correct": true,
          "feedback": "Bonne réponse : Pythagore en Python.\n`** 0.5` calcule la racine carrée. Variante :\n`math.sqrt(...)`.\n"
        },
        {
          "text": "`a[0] * b[0] + a[1] * b[1]`",
          "correct": false,
          "feedback": "Erreur : c'est le produit scalaire.\n"
        },
        {
          "text": "`((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) ** 1/2`",
          "correct": false,
          "feedback": "Erreur de priorité : `**` est prioritaire\nsur `/`, donc l'expression vaut\n`(...) ** 1 / 2`, la moitié du carré de la\ndistance. Il faut `** 0.5` ou `** (1/2)`.\n"
        },
        {
          "text": "`abs(a[0] - b[0]) + abs(a[1] - b[1])`",
          "correct": false,
          "feedback": "Erreur : c'est la distance de Manhattan\n(|Δx| + |Δy|), pas l'euclidienne.\n"
        }
      ],
      "explanation": "Astuce : pour comparer des distances, on\npeut omettre la racine carrée (la fonction\nracine est croissante). Plus rapide."
    },
    {
      "id": "q12",
      "difficulty": 2,
      "skills": [
        "tri-distances"
      ],
      "title": "Sélection des voisins",
      "statement": "Pour trouver les k plus proches voisins d'un\npoint P parmi N exemples, quelle approche est\nla plus simple ?",
      "options": [
        {
          "text": "Calculer les distances, trier, garder les k premiers",
          "correct": true,
          "feedback": "Bonne réponse : simple à implémenter.\nCoût : O(N) pour les distances + O(N log\nN) pour le tri = O(N log N).\n"
        },
        {
          "text": "Aucune solution simple n'existe vraiment pour ce problème",
          "correct": false,
          "feedback": "Plusieurs solutions\nexistent au contraire ;\nla plus simple est\nprécisément celle qu'on\nvient de décrire.\n"
        },
        {
          "text": "Choisir k exemples au hasard",
          "correct": false,
          "feedback": "Erreur : pas k-NN.\n"
        },
        {
          "text": "Calculer la moyenne des exemples",
          "correct": false,
          "feedback": "Erreur : ce n'est pas le rôle.\n"
        }
      ],
      "explanation": "Optimisations possibles : structures\nspatiales (kd-trees), heuristiques (pas au\nprogramme Première). Mais l'approche naïve\nsuffit pour comprendre."
    },
    {
      "id": "q13",
      "difficulty": 2,
      "skills": [
        "normalisation"
      ],
      "title": "Pourquoi normaliser ?",
      "statement": "Pourquoi est-il souvent **utile de normaliser**\nles caractéristiques des données avant\nd'appliquer k-NN ?",
      "options": [
        {
          "text": "Pour qu'aucune caractéristique n'écrase les autres",
          "correct": true,
          "feedback": "Bonne réponse : la distance euclidienne\nest sensible aux échelles, une grande\nplage de valeurs domine les autres\ncaractéristiques. Normaliser\n(rescaler entre 0 et 1, ou centrer-\nréduire) garantit que toutes les\ncaractéristiques pèsent autant.\n"
        },
        {
          "text": "Pour rendre l'algorithme déterministe d'une exécution à l'autre",
          "correct": false,
          "feedback": "L'algorithme des $k$ plus\nproches voisins est déjà\ndéterministe par\nconstruction. La\nnormalisation joue un\nautre rôle, comme\nexpliqué dans la bonne\nréponse.\n"
        },
        {
          "text": "Pour économiser la mémoire occupée par les données",
          "correct": false,
          "feedback": "La normalisation n'a pas\nd'effet notable sur la\nconsommation mémoire.\nSon intérêt se situe sur\nle plan numérique.\n"
        },
        {
          "text": "Parce que les bibliothèques Python l'exigent",
          "correct": false,
          "feedback": "Erreur : aucune obligation n'est imposée\npar le langage ni par les bibliothèques.\nLa normalisation est une bonne pratique,\nmais reste facultative.\n"
        }
      ],
      "explanation": "Exemple concret : si on classe des personnes\npar (âge en années [0-100], revenu en € [0-\n100 000]), le revenu domine totalement la\ndistance. Normaliser remet les deux sur une\néchelle comparable."
    },
    {
      "id": "q14",
      "difficulty": 2,
      "skills": [
        "k-petit-grand"
      ],
      "title": "Compromis sur k",
      "statement": "Quel **risque** y a-t-il à choisir un k **trop grand** (par exemple k = nombre total\nd'exemples) ?",
      "options": [
        {
          "text": "Aucun risque ; un grand $k$ est toujours préférable",
          "correct": false,
          "feedback": "Au contraire, un $k$ trop\ngrand pose un problème\nspécifique, comme expliqué\ndans la bonne réponse.\n"
        },
        {
          "text": "Le coût d'un calcul explose en $n^3$",
          "correct": false,
          "feedback": "Le coût d'un calcul de\nprédiction reste linéaire\nen $N$ : il ne dépend pas\ndu choix de $k$.\n"
        },
        {
          "text": "L'algorithme cesse alors complètement de fonctionner",
          "correct": false,
          "feedback": "L'algorithme continue de\nfonctionner, mais le\nrésultat qu'il produit\nn'est plus pertinent.\n"
        },
        {
          "text": "La prédiction tend vers la classe majoritaire globale",
          "correct": true,
          "feedback": "Bonne réponse : si k = N, tous les\nexemples votent. Le résultat est toujours\nla classe la plus représentée dans tout\nle jeu de données, indépendamment de la\nposition de P. Plus rien d'utile.\n"
        }
      ],
      "explanation": "Compromis biais-variance : k petit = haute\nvariance, faible biais ; k grand = faible\nvariance, biais élevé. À doser selon la\ntaille du jeu."
    },
    {
      "id": "q15",
      "difficulty": 2,
      "skills": [
        "donnees-entrainement"
      ],
      "title": "Rôle des données d'entraînement",
      "statement": "Que sont les **données d'entraînement**\n(training set) pour k-NN ?",
      "options": [
        {
          "text": "Les nouvelles données que l'on cherche à classer",
          "correct": false,
          "feedback": "Erreur : ce sont les données de **test**\n(à classer).\n"
        },
        {
          "text": "Une formule mathématique",
          "correct": false,
          "feedback": "Les données d'entraînement\nne sont pas une formule,\nmais un ensemble\nd'exemples concrets,\nchacun étiqueté avec sa\nclasse.\n"
        },
        {
          "text": "Les exemples étiquetés servant de comparaison",
          "correct": true,
          "feedback": "Bonne réponse : plus le jeu\nd'entraînement est riche et représentatif,\nmeilleures sont les prédictions.\n"
        },
        {
          "text": "Le code source de l'algorithme",
          "correct": false,
          "feedback": "Le code source est une\nnotion distincte des\ndonnées d'entraînement,\nqui sont les exemples\nutilisés.\n"
        }
      ],
      "explanation": "En pratique, on divise un jeu étiqueté en\n**train** (entraînement) + **test**\n(évaluation) pour mesurer la performance\nsans tricher."
    },
    {
      "id": "q16",
      "difficulty": 2,
      "skills": [
        "code-knn"
      ],
      "title": "Code k-NN simple",
      "statement": "Quel code en Python implémente correctement\nk-NN pour classer un point `p` ?\n```python\n# exemples = [(point, classe), ...]\n# k entier, dist(a, b) renvoie la distance\n# majoritaire(liste) renvoie la classe la plus\n# fréquente de la liste\n```",
      "options": [
        {
          "text": "```python\npaires = [(dist(p, x), c) for (x, c) in exemples]\npaires.sort(reverse=True)\nvoisins = [c for (d, c) in paires[:k]]\nreturn majoritaire(voisins)\n```\n",
          "correct": false,
          "feedback": "Erreur : le tri **décroissant** fait voter\nles k exemples les plus **éloignés** de `p`.\nIl faut trier par distance croissante pour\nretenir les plus proches voisins.\n"
        },
        {
          "text": "```python\nvoisins = [c for (x, c) in exemples[:k]]\nreturn majoritaire(voisins)\n```\n",
          "correct": false,
          "feedback": "Erreur : on fait voter les k premiers\nexemples **dans l'ordre du tableau**, sans\ncalculer aucune distance. Le vote ne porte\ndonc pas sur les voisins de `p`.\n"
        },
        {
          "text": "```python\npaires = [(dist(p, x), c) for (x, c) in exemples]\npaires.sort()\nreturn paires[0][1]\n```\n",
          "correct": false,
          "feedback": "Erreur : on renvoie la classe du seul plus\nproche voisin, comme si k valait toujours 1.\nLe paramètre `k` est ignoré et le vote\nmajoritaire disparaît.\n"
        },
        {
          "text": "```python\npaires = [(dist(p, x), c) for (x, c) in exemples]\npaires.sort()\nvoisins = [c for (d, c) in paires[:k]]\nreturn majoritaire(voisins)\n```\n",
          "correct": true,
          "feedback": "Bonne réponse : on calcule les distances,\non trie par distance croissante, on garde\nles k plus proches, et `majoritaire`\nréalise le vote.\n"
        }
      ],
      "explanation": "Implémentation simple et lisible. La fonction\n`majoritaire` se programme avec un dictionnaire\nqui compte les occurrences de chaque classe.\nPour de gros volumes, des bibliothèques comme\nscikit-learn proposent des implémentations\noptimisées (kd-trees)."
    },
    {
      "id": "q17",
      "difficulty": 2,
      "skills": [
        "iris"
      ],
      "title": "Jeu de données Iris",
      "statement": "Le jeu de données **Iris** est célèbre pour\nillustrer la classification. Que contient-il ?",
      "options": [
        {
          "text": "Des mesures de couleurs au format rouge-vert-bleu",
          "correct": false,
          "feedback": "Le jeu de données Iris ne\ncontient pas de mesures\ncolorimétriques, mais des\nmesures morphologiques\ndes fleurs.\n"
        },
        {
          "text": "150 fleurs décrites par 4 mesures et leur espèce",
          "correct": true,
          "feedback": "Bonne réponse : jeu de données\nhistorique introduit par Fisher en 1936.\nTrès utilisé pour tester les algorithmes\nde classification.\n"
        },
        {
          "text": "Des graines à planter",
          "correct": false,
          "feedback": "Cette interprétation\nlittérale du nom « Iris »\nest sans rapport avec le\ncontenu du jeu de\ndonnées.\n"
        },
        {
          "text": "Des images de fleurs au format JPEG haute résolution",
          "correct": false,
          "feedback": "Erreur : ce sont des **mesures**\nnumériques, pas des images.\n"
        }
      ],
      "explanation": "Ce jeu est le « hello world » de\nl'apprentissage automatique. Idéal pour\nillustrer k-NN : 4 dimensions, 3 classes,\ntaille raisonnable."
    },
    {
      "id": "q18",
      "difficulty": 2,
      "skills": [
        "coût"
      ],
      "title": "Coût de la prédiction",
      "statement": "Si l'on a N exemples d'entraînement, quel est\nle **coût** d'une prédiction k-NN naïve ?",
      "options": [
        {
          "text": "Logarithmique en N",
          "correct": false,
          "feedback": "Erreur : il faut bien examiner tous les\nexemples.\n"
        },
        {
          "text": "Linéaire en N (nombre d'exemples)",
          "correct": true,
          "feedback": "Bonne réponse : on calcule N distances.\nLe tri ajoute un facteur log N (donc\nO(N log N) total), mais au plus simple\non peut prendre les k minimums en O(N k)\nou O(N) avec un tri partiel.\n"
        },
        {
          "text": "Constant, indépendant de N",
          "correct": false,
          "feedback": "Erreur : il faut bien comparer le\nnouveau point à chaque exemple.\n"
        },
        {
          "text": "Quadratique en N (double boucle)",
          "correct": false,
          "feedback": "Erreur : on ne fait pas de double boucle.\n"
        }
      ],
      "explanation": "Conséquence : prédiction lente sur de gros\njeux d'entraînement. Optimisations possibles\n(kd-trees) hors programme."
    },
    {
      "id": "q19",
      "difficulty": 2,
      "skills": [
        "forces-faiblesses"
      ],
      "title": "Forces et limites",
      "statement": "Quelle est une **limite importante** de k-NN ?",
      "options": [
        {
          "text": "Il ne peut pas faire de classification",
          "correct": false,
          "feedback": "Erreur : c'est précisément son rôle.\n"
        },
        {
          "text": "Il ne fonctionne qu'en dimension 2",
          "correct": false,
          "feedback": "Erreur : k-NN se généralise à toute\ndimension.\n"
        },
        {
          "text": "Lent à la prédiction et sensible aux échelles",
          "correct": true,
          "feedback": "Bonne réponse : tous les calculs ont lieu\nà la prédiction. Pour 1 million d'exemples\nen haute dimension, k-NN peut être\nimpraticable.\n"
        },
        {
          "text": "Il invente de nouveaux exemples au cours de la prédiction",
          "correct": false,
          "feedback": "L'algorithme se contente\nde comparer le nouveau\npoint aux exemples déjà\nfournis. Il n'en invente\naucun.\n"
        }
      ],
      "explanation": "Forces : simple, intuitif, sans hypothèse\nsur la distribution des données.\nLimites : lent, sensible à la malédiction de\nla dimensionnalité (en très haute dimension,\nles distances perdent leur sens)."
    },
    {
      "id": "q20",
      "difficulty": 2,
      "skills": [
        "vote-pondéré"
      ],
      "title": "Vote pondéré",
      "statement": "Une variante de k-NN consiste à **pondérer le vote** des voisins. Pourquoi ?",
      "options": [
        {
          "text": "Pour donner plus de poids aux voisins proches",
          "correct": true,
          "feedback": "Bonne réponse : un voisin très proche\ndevrait peser plus qu'un voisin éloigné.\nAméliore souvent la qualité des\nprédictions et résout les égalités.\n"
        },
        {
          "text": "Pour économiser la mémoire",
          "correct": false,
          "feedback": "La pondération n'a aucun\neffet sur la consommation\nmémoire.\n"
        },
        {
          "text": "Pour rendre l'algorithme aléatoire",
          "correct": false,
          "feedback": "Cette pondération reste\nparfaitement déterministe.\nElle ne fait pas\nintervenir le hasard.\n"
        },
        {
          "text": "Pour ralentir intentionnellement tout le programme",
          "correct": false,
          "feedback": "Aucun procédé de\npondération n'a pour but\nde ralentir le\nprogramme.\n"
        }
      ],
      "explanation": "Vote uniforme = chaque voisin compte 1.\nVote pondéré = poids dépendant de la\ndistance. Variante classique du k-NN."
    },
    {
      "id": "q21",
      "difficulty": 3,
      "skills": [
        "trace-detaillee"
      ],
      "title": "Trace détaillée",
      "statement": "Avec k = 3, on classe un point P. Les 5\nexemples les plus proches sont (par distance\ncroissante) : (1.0, classe A), (1.5, B), (2.0,\nA), (3.0, A), (4.0, B). Quelle classe prédit\nk-NN ?",
      "options": [
        {
          "text": "A",
          "correct": true,
          "feedback": "Bonne réponse : on garde les k = 3 plus\nproches : (1.0, A), (1.5, B), (2.0, A).\nVote : A = 2, B = 1 → A gagne.\n"
        },
        {
          "text": "B",
          "correct": false,
          "feedback": "Erreur : B n'a qu'un seul vote.\n"
        },
        {
          "text": "Indéterminé",
          "correct": false,
          "feedback": "Erreur : k-NN est déterministe.\n"
        },
        {
          "text": "Égalité",
          "correct": false,
          "feedback": "Erreur : pas d'égalité.\n"
        }
      ],
      "explanation": "Méthode : trier par distance, garder les k\npremiers, voter à la majorité. Les exemples\nau-delà de k (4ᵉ et 5ᵉ ici) ne comptent pas."
    },
    {
      "id": "q22",
      "difficulty": 3,
      "skills": [
        "malediction"
      ],
      "title": "Malédiction de la dimensionnalité",
      "statement": "Pourquoi k-NN devient-il **moins efficace en haute dimension** (par exemple 1000 attributs) ?",
      "options": [
        {
          "text": "En haute dimension, les distances se ressemblent toutes",
          "correct": true,
          "feedback": "Bonne réponse : phénomène\ncontre-intuitif. Les volumes en haute\ndimension se concentrent dans les coins,\nles distances se ressemblent. k-NN\nfonctionne mal.\n"
        },
        {
          "text": "La mémoire n'est plus suffisante",
          "correct": false,
          "feedback": "Cet effet peut survenir\ndans certains cas\nextrêmes, mais ce n'est\npas la cause principale\nde la dégradation des\nperformances en haute\ndimension.\n"
        },
        {
          "text": "Aucun problème particulier ne survient en haute dimension",
          "correct": false,
          "feedback": "Au contraire, un phénomène\nréel et bien étudié\ndégrade les performances\nde l'algorithme en haute\ndimension : c'est la\nmalédiction de la\ndimensionnalité, comme\ndétaillé dans la bonne\nréponse.\n"
        },
        {
          "text": "Le programme plante systématiquement",
          "correct": false,
          "feedback": "Le programme s'exécute\nsans erreur, mais sa\nqualité de prédiction se\ndégrade fortement.\n"
        }
      ],
      "explanation": "Solutions : réduction de dimension (ACP,\nautres méthodes), sélection de\ncaractéristiques. En NSI, on reste sur des\ncas simples (2D, 3D, jeu Iris à 4D)."
    },
    {
      "id": "q23",
      "difficulty": 3,
      "skills": [
        "evaluation"
      ],
      "title": "Évaluation de la performance",
      "statement": "Pour évaluer la qualité de k-NN sur un jeu\nétiqueté, quelle est la **bonne pratique** ?",
      "options": [
        {
          "text": "Mesurer la précision sur les exemples d'entraînement eux-mêmes",
          "correct": false,
          "feedback": "Erreur : on testerait sur les données\ndéjà mémorisées (k = 1 donnerait 100 %),\nce qui est sans intérêt.\n"
        },
        {
          "text": "Aucune évaluation n'est possible",
          "correct": false,
          "feedback": "Plusieurs méthodes\nd'évaluation existent au\ncontraire ; la plus\nsimple consiste à\nséparer les données en\nun ensemble\nd'entraînement et un\nensemble de test.\n"
        },
        {
          "text": "Demander l'avis d'un expert humain",
          "correct": false,
          "feedback": "Faire intervenir un expert\npeut être utile, mais\nc'est une démarche\nsubjective et coûteuse.\nPour évaluer la\nperformance d'un\nalgorithme, on préfère\nune mesure quantitative\nsur des données de test.\n"
        },
        {
          "text": "Séparer entraînement et test, mesurer sur le test",
          "correct": true,
          "feedback": "Bonne réponse : on évalue sur des\nexemples que l'algorithme n'a jamais\n« vus ». Pratique standard en\napprentissage automatique. Souvent 80 %\n/ 20 %.\n"
        }
      ],
      "explanation": "Variantes : validation croisée\n(cross-validation, on découpe en plusieurs\nblocs et on alterne). Pratique standard pour\ndes évaluations robustes."
    },
    {
      "id": "q24",
      "difficulty": 3,
      "skills": [
        "variantes"
      ],
      "title": "k-NN pour la régression",
      "statement": "Peut-on adapter k-NN pour **prédire un nombre**\n(régression) au lieu d'une classe ?",
      "options": [
        {
          "text": "Oui, mais à condition de doubler la valeur de $k$",
          "correct": false,
          "feedback": "Le passage à la régression\nn'a aucun rapport avec un\ndoublement de $k$. C'est\nla nature de l'agrégation\nfinale (vote majoritaire\nou moyenne) qui change.\n"
        },
        {
          "text": "Non, l'algorithme est strictement limité à la classification",
          "correct": false,
          "feedback": "L'algorithme s'adapte au\ncontraire très naturellement\nau cas de la régression,\ncomme expliqué dans la\nbonne réponse.\n"
        },
        {
          "text": "Non, il faut nécessairement un autre algorithme",
          "correct": false,
          "feedback": "L'algorithme des $k$ plus\nproches voisins s'étend\nnaturellement à la\nrégression, sans qu'il\nsoit nécessaire de le\nremplacer.\n"
        },
        {
          "text": "Oui, en remplaçant le vote par la moyenne des k voisins",
          "correct": true,
          "feedback": "Bonne réponse : si la cible est\nnumérique (prix d'une maison, note\nattendue), la classe « majoritaire » est\nremplacée par la moyenne des cibles des\nk voisins. Idée générale identique.\n"
        }
      ],
      "explanation": "Algorithme **k-NN régresseur** : très utilisé\nen pratique pour des prédictions de prix,\ndurées, scores. Même principe que la\nclassification."
    },
    {
      "id": "q25",
      "difficulty": 3,
      "skills": [
        "synthese"
      ],
      "title": "Synthèse",
      "statement": "Parmi les affirmations suivantes sur k-NN,\nlaquelle est **fausse** ?",
      "options": [
        {
          "text": "La phase d'entraînement se résume essentiellement à mémoriser les exemples.",
          "correct": false,
          "feedback": "Vrai : algorithme paresseux.\n"
        },
        {
          "text": "La distance euclidienne est un choix courant pour la mesure de proximité.",
          "correct": false,
          "feedback": "Vrai : c'est la mesure standard, mais\nd'autres existent (Manhattan, cosinus).\n"
        },
        {
          "text": "Plus k est grand, plus l'algorithme est sensible au bruit local.",
          "correct": true,
          "feedback": "Faux (donc bonne réponse) : c'est\nl'**inverse**. Avec k grand, le vote\nintègre beaucoup de voisins, ce qui\n**lisse** la décision et la rend\n**moins** sensible aux exemples isolés\n(bruit). Avec k petit (k = 1), un seul\nexemple aberrant change la prédiction.\n"
        },
        {
          "text": "k-NN est un algorithme d'apprentissage supervisé.",
          "correct": false,
          "feedback": "Vrai : il apprend depuis des exemples\nétiquetés.\n"
        }
      ],
      "explanation": "Mnémonique : k petit = local, sensible au\nbruit ; k grand = global, lissé. Choisir k\nempiriquement par validation."
    },
    {
      "id": "q26",
      "difficulty": 2,
      "skills": [
        "choix-distance"
      ],
      "title": "Choix de la distance",
      "statement": "Outre la distance euclidienne, on rencontre\nsouvent la **distance de Manhattan**\n(|Δx| + |Δy|). Quel critère permet de choisir\nentre ces deux distances ?",
      "options": [
        {
          "text": "Aucun critère, on choisit au hasard",
          "correct": false,
          "feedback": "Erreur : le choix de la distance influence\nfortement les résultats de l'algorithme. Il\nfaut le justifier en fonction du problème,\npas le tirer au hasard.\n"
        },
        {
          "text": "La distance euclidienne est toujours préférable car elle est plus précise",
          "correct": false,
          "feedback": "Erreur : ces deux distances sont des choix\nvalides selon le contexte. Aucune n'est\nuniversellement meilleure. Le choix dépend\nde la nature des données et de la\nstructure de la proximité que l'on veut\nmodéliser.\n"
        },
        {
          "text": "Cela dépend du problème (espace continu ou grille)",
          "correct": true,
          "feedback": "Bonne réponse : la distance de Manhattan\nest moins sensible aux valeurs aberrantes\ndans les coordonnées car elle ne carre pas\nles écarts. Elle est aussi plus naturelle\nquand les composantes ont une signification\nindépendante. La distance euclidienne, plus\nrégulière, convient bien aux espaces\ngéométriques classiques.\n"
        },
        {
          "text": "La distance de Manhattan est plus rapide à calculer",
          "correct": false,
          "feedback": "Différence négligeable en pratique : les\ndeux distances se calculent en O(d) où d\nest la dimension. La performance n'est pas\nle critère qui motive le choix.\n"
        }
      ],
      "explanation": "Repère pratique : essayer plusieurs distances,\nmesurer la performance sur l'ensemble de test,\nretenir la meilleure. C'est ce qu'on appelle\nl'optimisation des hyperparamètres."
    },
    {
      "id": "q27",
      "difficulty": 3,
      "skills": [
        "classes-desequilibrees"
      ],
      "title": "Classes déséquilibrées",
      "statement": "On veut détecter une maladie rare avec k-NN.\nLe jeu d'entraînement contient 95 % d'exemples\n« sain » et 5 % d'exemples « malade ». Avec\nk = 7, que va prédire l'algorithme pour\npresque tous les nouveaux patients ?",
      "options": [
        {
          "text": "« malade » à 5 % des nouveaux patients, par symétrie",
          "correct": false,
          "feedback": "Erreur : ce serait le comportement attendu\nd'une distribution aléatoire. Or k-NN ne\ntire rien au hasard ; il prédit en\nfonction des voisins, et ceux-ci sont\nprincipalement « sain ».\n"
        },
        {
          "text": "Une classe choisie au hasard, l'algorithme étant non déterministe",
          "correct": false,
          "feedback": "Erreur : k-NN est strictement\ndéterministe. Pour une même entrée et un\nmême jeu d'entraînement, il prédit\ntoujours la même classe.\n"
        },
        {
          "text": "« sain » presque toujours, les voisins étant surtout sains",
          "correct": true,
          "feedback": "Bonne réponse : c'est le piège classique\ndes classes déséquilibrées. La précision\nglobale peut sembler élevée (95 %), mais le\nrappel sur la classe minoritaire est\nquasiment nul. Solutions : suréchantillonner\nla classe minoritaire, sous-échantillonner\nla majoritaire, ou utiliser un vote\npondéré par l'inverse de la fréquence des\nclasses.\n"
        },
        {
          "text": "« malade » dans la majorité des cas, par sécurité",
          "correct": false,
          "feedback": "Erreur : k-NN n'a aucune logique de\nprudence sanitaire. Il vote simplement à\nla majorité des voisins. Or les voisins\ntirés aléatoirement sont presque toujours\n« sain ».\n"
        }
      ],
      "explanation": "Le déséquilibre de classes est un problème\nmajeur en apprentissage. Mesurer uniquement la\nprécision globale peut être trompeur ; on\ncomplète par le rappel et la précision sur la\nclasse minoritaire, ou par la matrice de\nconfusion."
    },
    {
      "id": "q28",
      "difficulty": 2,
      "skills": [
        "calcul-concret"
      ],
      "title": "Calcul concret",
      "statement": "On classe le point `P = (3, 4)` avec k = 3 et\nla distance euclidienne. Les exemples\nétiquetés sont :\n`(0, 0, A)`, `(6, 8, A)`, `(2, 1, B)`,\n`(5, 4, B)`, `(3, 0, A)`. Quelle classe\nprédit k-NN ?",
      "options": [
        {
          "text": "A",
          "correct": false,
          "feedback": "Erreur : ce serait correct si A obtenait\nla majorité parmi les 3 plus proches.\nRefaire le calcul des distances : `(0, 0)`\n→ 5 ; `(6, 8)` → 5 ; `(2, 1)` → √10 ≈ 3,16 ;\n`(5, 4)` → 2 ; `(3, 0)` → 4. Les 3 plus\nproches sont `(5, 4, B)` (2), `(2, 1, B)`\n(3,16) et `(3, 0, A)` (4).\n"
        },
        {
          "text": "Égalité entre A et B",
          "correct": false,
          "feedback": "Erreur : avec k = 3 (impair) et deux\nclasses, il ne peut pas y avoir égalité.\nLe calcul donne B = 2 voix, A = 1 voix.\n"
        },
        {
          "text": "Indéterminé sans plus d'informations",
          "correct": false,
          "feedback": "Erreur : toutes les informations\nnécessaires sont fournies (point, k,\ndistance, exemples étiquetés). Le résultat\nest parfaitement calculable.\n"
        },
        {
          "text": "B",
          "correct": true,
          "feedback": "Bonne réponse. Distances calculées :\n`(0, 0)` → 5 ; `(6, 8)` → 5 ; `(2, 1)` →\n√10 ≈ 3,16 ; `(5, 4)` → 2 ; `(3, 0)` → 4.\nLes 3 plus proches sont `(5, 4, B)`,\n`(2, 1, B)`, `(3, 0, A)`. Vote : B = 2,\nA = 1 → B gagne.\n"
        }
      ],
      "explanation": "Méthode systématique : (1) calculer la\ndistance de P à chaque exemple ; (2) trier par\ndistance croissante ; (3) garder les k\npremiers ; (4) voter à la majorité. Sur les\npetits jeux, refaire le calcul à la main est\nle meilleur exercice de compréhension."
    }
  ]
}