1. (* KNN version simple *)
  2.  
  3. let nb_cl = 3;; (* nombre de classes ; de 0 à nb_cl - 1 *)
  4.  
  5. let data = [| (* ensemble d'entrainement *)
  6. ([| 149. ; 304. |], 0);
  7. ([| 207. ; 346. |], 0);
  8. ([| 79. ; 155. |], 0);
  9. ([| 257. ; 287. |], 0);
  10. ([| 499. ; 86. |], 0);
  11. ([| 432. ; 309. |], 0);
  12. ([| 498. ; 343. |], 0);
  13. ([| 356. ; 178. |], 0);
  14. ([| 401. ; 224. |], 0);
  15. ([| 75. ; 119. |], 0);
  16. ([| 334. ; 338. |], 0);
  17. ([| 374. ; 242. |], 0);
  18. ([| 608. ; 378. |], 1);
  19. ([| 310. ; 496. |], 1);
  20. ([| 610. ; 485. |], 1);
  21. ([| 544. ; 298. |], 1);
  22. ([| 550. ; 483. |], 1);
  23. ([| 670. ; 227. |], 1);
  24. ([| 719. ; 237. |], 1);
  25. ([| 673. ; 386. |], 1);
  26. ([| 319. ; 359. |], 1);
  27. ([| 560. ; 252. |], 1);
  28. ([| 395. ; 250. |], 1);
  29. ([| 299. ; 529. |], 1);
  30. ([| 449. ; 533. |], 1);
  31. ([| 463. ; 387. |], 1);
  32. ([| 265. ; 324. |], 1);
  33. ([| 716. ; 429. |], 1);
  34. ([| 481. ; 371. |], 1);
  35. ([| 502. ; 280. |], 1);
  36. ([| 428. ; 623. |], 1);
  37. ([| 355. ; 424. |], 1);
  38. ([| 796. ; 301. |], 2);
  39. ([| 938. ; 430. |], 2);
  40. ([| 507. ; 320. |], 2);
  41. ([| 519. ; 336. |], 2);
  42. ([| 573. ; 269. |], 2);
  43. ([| 557. ; 198. |], 2);
  44. ([| 761. ; 285. |], 2);
  45. ([| 829. ; 434. |], 2);
  46. ([| 522. ; 182. |], 2);
  47. ([| 766. ; 105. |], 2);
  48. ([| 803. ; 124. |], 2);
  49. ([| 884. ; 420. |], 2);
  50. ([| 769. ; 235. |], 2);
  51. ([| 912. ; 151. |], 2);
  52. ([| 833. ; 387. |], 2);
  53. |];;
  54.  
  55. (* distance entre deux points *)
  56. let dist pt1 pt2 =
  57. let n = Array.length pt1 in
  58. let n2 = Array.length pt2 in
  59. assert (n = n2);
  60. let s = ref 0. in
  61. for i = 0 to (n - 1) do
  62. s := !s +. (pt1.(i) -. pt2.(i)) ** 2.
  63. done;
  64. sqrt !s;;
  65.  
  66. (* classifieur knn *)
  67. let classifie k data pt =
  68. (* k : nb de plus proches voisins à considérer *)
  69. (* data : ensemble d'entrainement *)
  70. (* pt : le point à classer *)
  71. assert (k <= Array.length data); (* programmation defensive *)
  72. let n = Array.length data in
  73. (* tableau des couples (distance, classe) *)
  74. let distances_cl = Array.make n (0., 0) in
  75. for i = 0 to n - 1 do
  76. let pt2, cl = data.(i) in
  77. distances_cl.(i) <- (dist pt pt2, cl)
  78. done;
  79. (* tri par distance croissante *)
  80. Array.sort (fun (d1,c1) (d2,c2) -> if d1 < d2 then -1 else 1) distances_cl;
  81. (* tableau des compteurs *)
  82. let compteurs = Array.make nb_cl 0 in
  83. let maxi = ref 0 in
  84. let cmaxi = ref 0 in
  85. let egalite = ref true in
  86. for i = 0 to k - 1 do
  87. let dist, c = distances_cl.(i) in
  88. compteurs.(c) <- compteurs.(c) + 1;
  89. if compteurs.(c) > !maxi then begin
  90. maxi := compteurs.(c); cmaxi := c; egalite := false
  91. end else if compteurs.(c) = !maxi then
  92. egalite := true
  93. done;
  94. if !egalite then -1 else !cmaxi
  95. ;;
  96.  
  97. (* K_Meilleurs *)
  98.  
  99. (* structure de données pour stocker les k meilleurs *)
  100.  
  101. type k_meilleurs = { nmax : int; mutable nb : int; mutable voisins : (float array * float * int) list}
  102. (* nmax : nombre maximal de point à conserver *)
  103. (* nb : nombre de points conservés *)
  104. (* voisins : liste des points conservés, triés par distance décroissante, accompagnés de leur classe *)
  105.  
  106. let creerKM k = { nmax = k; nb = 0; voisins = [] };;
  107.  
  108. let ajouterKM km (pt,dist,c) =
  109. let rec inserer (pt, dist, c) l = match l with
  110. | [] -> [(pt, dist, c)]
  111. | (pt2, dist2, c2) :: ll -> if dist < dist2 then (pt2, dist2, c2) :: (inserer (pt, dist, c) ll) else (pt, dist, c) :: l
  112. in
  113. if km.nb < km.nmax then begin (* il reste de la place ! *)
  114. km.voisins <- inserer (pt, dist, c) km.voisins;
  115. km.nb <- km.nb + 1
  116. end else (* c'est plein ! *)
  117. (* faut-il garder le point ? qui prend alors la place de la tête de liste *)
  118. let _,dmax,_ = List.hd km.voisins in
  119. if dist <= dmax then
  120. km.voisins <- inserer (pt, dist,c) (List.tl km.voisins)
  121. ;;
  122.  
  123. (* classifieur knn optimisé *)
  124. let classifieKM k data pt =
  125. (* k : nb de plus proches voisins à considérer *)
  126. (* data : ensemble d'entrainement *)
  127. (* pt : le point à classer *)
  128. assert (k <= Array.length data); (* programmation defensive *)
  129. let km = creerKM k in
  130. let n = Array.length data in
  131. for i = 0 to n - 1 do
  132. let pt2, cl = data.(i) in
  133. ajouterKM km (pt2, dist pt pt2, cl)
  134. done;
  135. (* tableau des compteurs *)
  136. let compteurs = Array.make nb_cl 0 in
  137. let maxi = ref 0 in
  138. let cmaxi = ref 0 in
  139. let egalite = ref true in
  140. let traite_meilleur (pt, dist, c) =
  141. compteurs.(c) <- compteurs.(c) + 1;
  142. if compteurs.(c) > !maxi then begin
  143. maxi := compteurs.(c); cmaxi := c; egalite := false
  144. end else if compteurs.(c) = !maxi then
  145. egalite := true
  146. in List.iter traite_meilleur km.voisins;
  147. if !egalite then -1 else !cmaxi
  148. ;;
  149.  
  150.  
  151.  
  152. let pts = [| [|500.;345.|]; [|550.;300.|] |] in
  153. let ks = [|1;2;3;4;5|] in
  154. for i = 0 to Array.length pts - 1 do
  155. for j = 0 to Array.length ks - 1 do
  156. Printf.printf "%d " (classifieKM ks.(j) data pts.(i))
  157. done; print_newline ()
  158. done;;
  159.  
  160.  
  161.  
  162.  
  163.  
  164. (* couleurs associées aux classes / zones*)
  165. let cz0 = Graphics.rgb 50 250 50;;
  166. let cp0 = Graphics.rgb 35 175 35;;
  167. let cz1 = Graphics.rgb 250 50 50;;
  168. let cp1 = Graphics.rgb 175 35 35;;
  169. let cz2 = Graphics.rgb 50 50 250;;
  170. let cp2 = Graphics.rgb 35 35 175;;
  171.  
  172. let set_color_of_classe cl z =
  173. let couleur =
  174. match cl with
  175. | 0 -> if z then cz0 else cp0
  176. | 1 -> if z then cz1 else cp1
  177. | 2 -> if z then cz2 else cp2
  178. | _ -> Graphics.white
  179. in
  180. Graphics.set_color couleur;;
  181.  
  182. (* affichage d'un ensemble d'entraînement *)
  183. let affichage_points data =
  184. Graphics.set_line_width 3;
  185. for i = 0 to Array.length data - 1 do
  186. let coord, cl = data.(i) in
  187. set_color_of_classe cl false;
  188. Graphics.draw_rect (int_of_float coord.(0)-1) (int_of_float coord.(1)-1) 3 3
  189. done;;
  190.  
  191. (* classifie tous les points de l'image *)
  192. let classifie_zone k data =
  193. for x = 0 to 999 do
  194. for y = 0 to 699 do
  195. if x mod 10 = 0 && y mod 10 = 0 then begin
  196. let cl = classifie k data [|float_of_int x; float_of_int y|] in
  197. set_color_of_classe cl true;
  198. Graphics.draw_rect (x-1) (y-1) 3 3
  199. end
  200. done
  201. done;;
  202.  
  203.  
  204. (* Affichage *)
  205.  
  206. Graphics.open_graph " 1000x700" ; (* ouverture de la fenetre graphique *)
  207.  
  208. affichage_points data;;
  209.  
  210. Graphics.read_key ();; (* attente d'une saisie clavier *)
  211.  
  212. classifie_zone 3 data;;
  213.  
  214. affichage_points data;;
  215.  
  216. Graphics.read_key ();;