(* KNN version simple *) let nb_cl = 3;; (* nombre de classes ; de 0 à nb_cl - 1 *) let data = [| (* ensemble d'entrainement *) ([| 149. ; 304. |], 0); ([| 207. ; 346. |], 0); ([| 79. ; 155. |], 0); ([| 257. ; 287. |], 0); ([| 499. ; 86. |], 0); ([| 432. ; 309. |], 0); ([| 498. ; 343. |], 0); ([| 356. ; 178. |], 0); ([| 401. ; 224. |], 0); ([| 75. ; 119. |], 0); ([| 334. ; 338. |], 0); ([| 374. ; 242. |], 0); ([| 608. ; 378. |], 1); ([| 310. ; 496. |], 1); ([| 610. ; 485. |], 1); ([| 544. ; 298. |], 1); ([| 550. ; 483. |], 1); ([| 670. ; 227. |], 1); ([| 719. ; 237. |], 1); ([| 673. ; 386. |], 1); ([| 319. ; 359. |], 1); ([| 560. ; 252. |], 1); ([| 395. ; 250. |], 1); ([| 299. ; 529. |], 1); ([| 449. ; 533. |], 1); ([| 463. ; 387. |], 1); ([| 265. ; 324. |], 1); ([| 716. ; 429. |], 1); ([| 481. ; 371. |], 1); ([| 502. ; 280. |], 1); ([| 428. ; 623. |], 1); ([| 355. ; 424. |], 1); ([| 796. ; 301. |], 2); ([| 938. ; 430. |], 2); ([| 507. ; 320. |], 2); ([| 519. ; 336. |], 2); ([| 573. ; 269. |], 2); ([| 557. ; 198. |], 2); ([| 761. ; 285. |], 2); ([| 829. ; 434. |], 2); ([| 522. ; 182. |], 2); ([| 766. ; 105. |], 2); ([| 803. ; 124. |], 2); ([| 884. ; 420. |], 2); ([| 769. ; 235. |], 2); ([| 912. ; 151. |], 2); ([| 833. ; 387. |], 2); |];; (* distance entre deux points *) let dist pt1 pt2 = let n = Array.length pt1 in let n2 = Array.length pt2 in assert (n = n2); let s = ref 0. in for i = 0 to (n - 1) do s := !s +. (pt1.(i) -. pt2.(i)) ** 2. done; sqrt !s;; (* classifieur knn *) let classifie k data pt = (* k : nb de plus proches voisins à considérer *) (* data : ensemble d'entrainement *) (* pt : le point à classer *) assert (k <= Array.length data); (* programmation defensive *) let n = Array.length data in (* tableau des couples (distance, classe) *) let distances_cl = Array.make n (0., 0) in for i = 0 to n - 1 do let pt2, cl = data.(i) in distances_cl.(i) <- (dist pt pt2, cl) done; (* tri par distance croissante *) Array.sort (fun (d1,c1) (d2,c2) -> if d1 < d2 then -1 else 1) distances_cl; (* tableau des compteurs *) let compteurs = Array.make nb_cl 0 in let maxi = ref 0 in let cmaxi = ref 0 in let egalite = ref true in for i = 0 to k - 1 do let dist, c = distances_cl.(i) in compteurs.(c) <- compteurs.(c) + 1; if compteurs.(c) > !maxi then begin maxi := compteurs.(c); cmaxi := c; egalite := false end else if compteurs.(c) = !maxi then egalite := true done; if !egalite then -1 else !cmaxi ;; (* K_Meilleurs *) (* structure de données pour stocker les k meilleurs *) type k_meilleurs = { nmax : int; mutable nb : int; mutable voisins : (float array * float * int) list} (* nmax : nombre maximal de point à conserver *) (* nb : nombre de points conservés *) (* voisins : liste des points conservés, triés par distance décroissante, accompagnés de leur classe *) let creerKM k = { nmax = k; nb = 0; voisins = [] };; let ajouterKM km (pt,dist,c) = let rec inserer (pt, dist, c) l = match l with | [] -> [(pt, dist, c)] | (pt2, dist2, c2) :: ll -> if dist < dist2 then (pt2, dist2, c2) :: (inserer (pt, dist, c) ll) else (pt, dist, c) :: l in if km.nb < km.nmax then begin (* il reste de la place ! *) km.voisins <- inserer (pt, dist, c) km.voisins; km.nb <- km.nb + 1 end else (* c'est plein ! *) (* faut-il garder le point ? qui prend alors la place de la tête de liste *) let _,dmax,_ = List.hd km.voisins in if dist <= dmax then km.voisins <- inserer (pt, dist,c) (List.tl km.voisins) ;; (* classifieur knn optimisé *) let classifieKM k data pt = (* k : nb de plus proches voisins à considérer *) (* data : ensemble d'entrainement *) (* pt : le point à classer *) assert (k <= Array.length data); (* programmation defensive *) let km = creerKM k in let n = Array.length data in for i = 0 to n - 1 do let pt2, cl = data.(i) in ajouterKM km (pt2, dist pt pt2, cl) done; (* tableau des compteurs *) let compteurs = Array.make nb_cl 0 in let maxi = ref 0 in let cmaxi = ref 0 in let egalite = ref true in let traite_meilleur (pt, dist, c) = compteurs.(c) <- compteurs.(c) + 1; if compteurs.(c) > !maxi then begin maxi := compteurs.(c); cmaxi := c; egalite := false end else if compteurs.(c) = !maxi then egalite := true in List.iter traite_meilleur km.voisins; if !egalite then -1 else !cmaxi ;; let pts = [| [|500.;345.|]; [|550.;300.|] |] in let ks = [|1;2;3;4;5|] in for i = 0 to Array.length pts - 1 do for j = 0 to Array.length ks - 1 do Printf.printf "%d " (classifieKM ks.(j) data pts.(i)) done; print_newline () done;; (* couleurs associées aux classes / zones*) let cz0 = Graphics.rgb 50 250 50;; let cp0 = Graphics.rgb 35 175 35;; let cz1 = Graphics.rgb 250 50 50;; let cp1 = Graphics.rgb 175 35 35;; let cz2 = Graphics.rgb 50 50 250;; let cp2 = Graphics.rgb 35 35 175;; let set_color_of_classe cl z = let couleur = match cl with | 0 -> if z then cz0 else cp0 | 1 -> if z then cz1 else cp1 | 2 -> if z then cz2 else cp2 | _ -> Graphics.white in Graphics.set_color couleur;; (* affichage d'un ensemble d'entraînement *) let affichage_points data = Graphics.set_line_width 3; for i = 0 to Array.length data - 1 do let coord, cl = data.(i) in set_color_of_classe cl false; Graphics.draw_rect (int_of_float coord.(0)-1) (int_of_float coord.(1)-1) 3 3 done;; (* classifie tous les points de l'image *) let classifie_zone k data = for x = 0 to 999 do for y = 0 to 699 do if x mod 10 = 0 && y mod 10 = 0 then begin let cl = classifie k data [|float_of_int x; float_of_int y|] in set_color_of_classe cl true; Graphics.draw_rect (x-1) (y-1) 3 3 end done done;; (* Affichage *) Graphics.open_graph " 1000x700" ; (* ouverture de la fenetre graphique *) affichage_points data;; Graphics.read_key ();; (* attente d'une saisie clavier *) classifie_zone 3 data;; affichage_points data;; Graphics.read_key ();;