logo

Un exemple avec pygame

Exercice 1 : prédiction sur 2 critères

L'objectif de cet exercice est de prédire la couleur d'un point par rapport à ses coordonnées avec un algorithme K-NN.

Pour cela nous allons générer un ensemble de données où chaque donnée est composée de deux coordonnées et d'une couleur.

Voici une fonction qui permet de générer un ensemble de données :

from random import *

def generer_groupe():
    g=[]
    for a in range(randint(10,30)):
        g.append([randint(0,400),randint(0,300),"red"])
    for a in range(randint(10,30)):
        g.append([randint(0,400),randint(0,300),"green"])
    return g

  1. Que va renvoyer la fonction generer_groupe ?
  2. Dans quels intervalles se trouvent les coordonnées des données générées ?

Partie I

Ecrire une fonction distance2 qui renvoie la distance au carré entre 2 points connaissant leurs coordonnées.

Voir une solution

Ecrire une fonction liste_distance_groupe de paramètres (x, y, groupe) où x et y sont des coordonnées et groupe, un ensemble de données, qui renvoie un tableau de listes [d, color] où d est la distance avec le point (x,y) et color est la couleur pour chaque donnée.

Voir une solution

Ecrire une fonction k_proches_voisins de paramètres (k, liste) où k est le nombres de voisins plus proches et liste est le tableau générer par la fonction liste_distance_groupe, qui renvoie les k distances les plus petites et leur couleur associée.

Voir une solution

Partie II

Ecrire une fonction prediction de paramètres (x, y, k, groupe) définis précédemment qui renvoie la prédiction de lacouleur ("red" ou "green") du point de coordonnées x et y.

Voir une solution

Exercice 2 : prédiction sur 3 critères

Modifier les fonctions (si nécessaire) pour avoir un ensemble de données avec une troisième couleur "blue".

Voir une solution

Pour aller plus loin : avec une interface graphique PYGAME

Voici le code permettant d'obtenir cela :

from random import *
from math import sqrt
from pygame import *
 
 
def generer_groupe():
    g=[]
    for a in range(randint(15,30)):
        g.append([randint(0,400),randint(0,300),"red"])
    for a in range(randint(15,30)):
        g.append([randint(0,400),randint(0,300),"green"])
    for a in range(randint(15,30)):
        g.append([randint(0,400),randint(0,300),"blue"])
    return g
s=generer_groupe()
 
def distance2(x1,y1,x2,y2):
    return (x1-x2)**2+(y1-y2)**2
 
def liste_distance_groupe(x,y,groupe):
    l=[]
    for a in groupe:
        l.append([distance2(x,y,a[0],a[1]),a[2]])
    return l
d=liste_distance_groupe(100,100,s)
 
def k_proches_voisins(k,liste):
    liste_classee=sorted(liste, key=lambda x: x[0])
    return liste_classee[:k]
 
def prediction(x,y,k,groupe):
    global t
    d=liste_distance_groupe(x,y,groupe)
    t=k_proches_voisins(k,d)
    red=0
    green=0
    for a in t:
        if a[1]=="red":
            red+=1
        if a[1]=="green":
            green+=1
    blue=k - red -green
    if red > green and red > blue:
        return "red"
    elif green > red and green > blue:
        return "green"
    elif blue > red and blue > green:
        return "blue"
    else:
        return "pas de prediction"
 
 
#variables pygame
width = 640
height = 300
init()
display.set_caption('Algorithme KNN')
mafont = font.SysFont("monospace", 20)
screen = display.set_mode((width, height))
clock = time.Clock()
running = True
x=0
y=0
r=0
p=""
#k=int(input("k= "))
k=7
while running:
    draw.rect(screen,(0,0,0),Rect(0,0,640,400))
    draw.circle(screen, (0,100,100),(x,y), r)
    red = (155,0,0)
    green = (0, 155,0)
    blue= (0, 0, 155)
    
    for a in s:
        if a[2]=="red":
                    #screen.set_at((a[0], a[1]), (0,0,0))
            draw.circle(screen, (255,0,0),(a[0], a[1]), 2)
        elif a[2]=="blue":
                    #screen.set_at((a[0], a[1]), (0,0,0))
            draw.circle(screen, (0,0,255),(a[0], a[1]), 2)
        else:
                    #screen.set_at((a[0], a[1]), (255,255,255))
            draw.circle(screen, (0,255,0),(a[0], a[1]), 2)
    for events in event.get():
        if events.type == QUIT:
            running = False
            quit()
        if events.type == MOUSEBUTTONDOWN:
            if events.button == 1:   #Si clic gauche
                #On change les coordonnées du perso
                if 420 < events.pos[0] < 470 and 40 < events.pos[1] < 65 and k>1:
                    k-=1
                    r=0
                if 540 < events.pos[0] < 590 and 40 < events.pos[1] < 65:
                    k+=1
                    r=0
                if events.pos[0] < 400:
                    x=events.pos[0]
                    y=events.pos[1]
                    p=prediction(x,y,k,s)
                    r=int(sqrt(t[k-1][0])+1)
    
                    
    
    text = mafont.render("k="+str(k),True,(0, 255, 0))
    screen.blit(text,(485, 40))
    draw.rect(screen,(100,100,100),Rect(420,40,50,25))
    text2 = mafont.render("-1",True,(128, 0, 0))
    screen.blit(text2,(430, 40))
    draw.rect(screen,(100,100,100),Rect(540,40,50,25))
    text3 = mafont.render("+1",True,(128, 0, 0))
    screen.blit(text3,(550, 40))
    text4 = mafont.render("prédiction : "+p,True,(255, 255, 255))
    screen.blit(text4,(420, 70))
    
    display.flip()

Analyser et tester ce code.