Probleme – -moyennes : le paquet vide, le minimum local, les relances
Exercice · niveau 3 (difficile) · informatique (MP2I/MPI), chapitre 26 — Apprentissage automatique
Énoncé
- Le code du cours calcule
barycentre points affectation c. Que vaut ce barycentre si le paquet est vide ? Que devient l'algorithme ? - Sur les neuf points avec , exhiber deux départs qui donnent deux résultats différents, et calculer les deux inerties.
- Combien de départs, parmi tous les choix de trois points distincts, atteignent l'optimum ?
- Quelle stratégie en tirer, et comment la coder ?
Corrigé
1. Le paquet vide donne nan. Le barycentre est une somme divisée par un effectif ; sur un paquet vide, c'est , et en flottants IEEE cela vaut nan. Le cas se produit vraiment : sur les points avec et les centres initiaux , , , l'affectation est — le troisième centre ne reçoit personne — et son barycentre vaut nan.
Ce qui suit est pire que l'arrêt : nan contamine tout. Toute distance à ce centre vaut nan, et toute comparaison avec nan est fausse : est faux, et est faux aussi. Le centre vide n'est donc jamais choisi comme « plus proche », il reste vide, et le programme tourne en rendant paquets sans le dire.
(* Barycentre du paquet c. Si le paquet est vide, on RELANCE le centre sur
un point tiré au hasard plutôt que de rendre nan. *)
let barycentre points aff c defaut =
let s = ref 0.0 and n = ref 0 in
Array.iteri (fun i x -> if aff.(i) = c then (s := !s +. x; incr n)) points;
if !n = 0 then defaut else !s /. float_of_int !n
La règle : une division dont le dénominateur peut être nul se traite avant de diviser, pas après. En C, sur des entiers plante ; en flottants, il ne plante pas — et c'est plus dangereux.
2. Deux départs, deux résultats. Mesuré :
| centres de départ | paquets obtenus | inertie |
|---|---|---|
| \ \ | ||
| \ \ |
La seconde partition est stable : aucun point ne veut changer de paquet, aucun centre ne veut bouger. C'est bien un minimum local, et il est fois pire que l'optimum. Le mécanisme est visible : deux centres se sont posés dans le paquet de droite, aucun dans celui du milieu, et l'unique centre restant a dû couvrir les deux paquets de gauche à la fois. Une fois cette division faite, aucun pas local ne la défait.
3. Le compte. Sur les façons de choisir trois points distincts comme centres initiaux, atteignent et échouent — soit près d'un départ sur quatre. La pire inertie atteinte est , celle du tableau ci-dessus.
4. La stratégie : relancer, et garder le meilleur.
(* Meilleure partition sur r exécutions indépendantes.
Précondition : r >= 1. Complexité : r fois celle de k_moyennes. *)
let k_moyennes_relance points k r =
let meilleur = ref None in
for _ = 1 to r do
let (aff, centres, cout) = k_moyennes points (tirer points k) in
match !meilleur with
| Some (_, _, c) when c <= cout -> ()
| _ -> meilleur := Some (aff, centres, cout)
done;
!meilleur
Avec une probabilité d'échec de par départ et des départs indépendants, la probabilité que relances échouent toutes vaut : pour , pour , pour . Trois relances suffisent ici à ramener le risque au centième, pour trois fois le temps de calcul.
Le statut de cet algorithme. C'est un Las Vegas dégradé, au sens du chapitre chap:probabilistes : le résultat rendu est toujours valide — une partition stable —, seul son coût dépend du hasard. On ne peut pas savoir si l'on a l'optimum ; on peut seulement rendre l'échec improbable, et c'est exactement ce que fait la relance. Un raffinement classique, -moyennes++, tire les centres initiaux loin les uns des autres au lieu de les tirer uniformément, et réduit fortement les cas.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.