Adloun

Probleme – Le dendrogramme : deux liens, et où couper

Exercice · niveau 3 (difficile) · informatique (MP2I/MPI), chapitre 26 — Apprentissage automatique

Énoncé

Corrigé

1. Le code.


type arbre = Feuille of string | Fusion of arbre * arbre * float

let rec noms = function
  | Feuille s -> [s]
  | Fusion (a, b, _) -> noms a @ noms b

(* Distance entre deux paquets. complet = true donne le lien complet
   (maximum), false le lien simple (minimum). Complexité : Theta(|a|·|b|). *)
let lien complet dist a b =
  let l = List.concat_map (fun u -> List.map (dist u) (noms b)) (noms a) in
  if complet then List.fold_left max neg_infinity l
  else List.fold_left min infinity l

(* Dendrogramme des points. Précondition : la liste est non vide.
   Terminaison : chaque tour réduit le nombre de paquets de 1.
   Complexité : O(n³). *)
let cha complet dist points =
  let paquets = ref (List.map (fun s -> Feuille s) points) in
  while List.length !paquets > 1 do
    let meilleur = ref None in
    List.iteri (fun i a -> List.iteri (fun j b ->
        if i < j then begin
          let d = lien complet dist a b in
          match !meilleur with
          | Some (_, _, dm) when dm <= d -> ()
          | _ -> meilleur := Some (a, b, d)
        end) !paquets) !paquets;
    match !meilleur with
    | None -> ()
    | Some (a, b, d) ->
        paquets := Fusion (a, b, d) :: List.filter (fun p -> p != a && p != b) !paquets
  done;
  List.hd !paquets

(* Les paquets obtenus en coupant le dendrogramme à la hauteur h. *)
let rec coupe h = function
  | Feuille s -> [[s]]
  | Fusion (a, b, hh) -> if hh <= h then [noms a @ noms b] else coupe h a @ coupe h b

Terminaison : le variant est le nombre de paquets, qui décroît de à chaque tour et reste positif ; la boucle fait exactement tours. Le != de la dernière ligne est délibéré : c'est l'égalité physique, qui retire les deux paquets fusionnés et eux seuls. Avec &lt;&gt;, deux paquets structurellement égaux — deux feuilles de même nom, ou deux fusions identiques — seraient retirés ensemble, et l'algorithme perdrait des points en silence.

2. Pourquoi et finissent ensemble. Le lien simple ne demande aucune proximité globale : il suffit qu'un point de soit proche d'un point de . Ici , et cette seule paire décide de la fusion, alors que est la plus grande distance interne du paquet obtenu. De proche en proche, la relation « être à moins de » propage l'appartenance le long de la chaîne : c'est l'effet de chaînage. Le lien complet, qui mesure au contraire la paire la plus éloignée, refuse cette fusion à la hauteur et ne l'accepte qu'à .

3. La complexité. La boucle fait tours ; à chaque tour on examine paires, et le calcul du lien d'une paire coûte . Or la somme des sur toutes les paires d'une même partition vaut au plus : un tour coûte donc , et le total . Pour descendre :

On obtient , et pour le lien simple, qui coïncide avec l'arbre couvrant minimal (chapitre chap:graphes-avances) : les fusions du lien simple sont exactement les arêtes que choisit Kruskal, et l'union des paquets est un unir-trouver (chapitre chap:unir).

4. Où couper. Il n'y a pas de règle, et c'est précisément l'avantage revendiqué par le cours : la coupe se décide après avoir vu l'arbre. Trois usages :

Le contraste avec les -moyennes est ici entier : on n'a pas eu à choisir avant de calculer, on n'a pas eu à relancer, et deux exécutions donnent le même arbre. Le prix est le , qui interdit ce procédé sur un million de points — et c'est pour cela que les deux méthodes coexistent.

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.