Main

Main.TutoPythonFrontiere History

Hide minor edits - Show changes to output

Changed lines 1-2 from:

!![[Course.CourseRFIDECTutoPython|Retour vers le tutoriel complet]]
to:
!![[Main.TutoPython|Retour vers le tutoriel complet]]
Added lines 1-200:

!![[Course.CourseRFIDECTutoPython|Retour vers le tutoriel complet]]

!! Ressources

[[(Attach:)dataset.py]] fonctions pour générer/afficher des jeux de données jouet.

[[(Attach:)frontiere.py]] fonctions pour tracer une frontière de décision sur des exemples jouet 2D

[[(Attach:)tutoFront.py]] Explication sur un exemple simple du fonctionnement des deux méthodes précédentes.

!! Tracés en 3D, isocontour et fonctionnalités avancées

Soit une fonction de deux variables {$f(w_1,w_2)$}. Si on cherche à apprendre f qui approxime des étiquettes {$y \in \{-1,1\}$}, on va s'intéresser de près à la frontière de décision: dans quelle partie de l'espace décide-t-on 1 et dans quelle partie décide-t-on -1...

Exemple de tracé:

%center% %width=300% [[Attach:plotFrontiere.png|Attach:plotFrontiere.png]]|[-'''Figure 1''' Frontière de décision au sens des moindres carrés entre 2 classes gaussiennes.-]

Obtenir une telle courbe n'est pas trivial, voici la liste des étapes à suivre:
# créer une grille de points pour mailler l'ensemble de l'espace
# évaluer votre modèle sur tous les points de la grille
# en déduire où se trouve la frontière de décision


!!!! 0. Soit un problème de classification binaire

Code du tutoriel joint;
(:source lang=python:)
from frontiere import *
from dataset import *
from ml import *
import matplotlib.pyplot as pl

x,y,xtest,ytest = dataset("gaussian", 100, 100, 0.3) # génération des données

pl.figure(1)
plotset(x,y,1) # affichage des données
(:sourceend:)

%center% %width=300% [[Attach:probleme2D.png | Attach:probleme2D.png]]|[-'''Figure 2''' Problème de classification 2D à deux classes.-]

!!!! 1. Générer une grille de points maillant tout l'espace à décrire

La fonction @@mesh@@ effectue cette opération pour vous: vous donnez x et (optionnellement) la densité du maillage en argument.
Cette fonction permet de générer un maillage couvrant l'ensemble de l'espace de la figure 2:

%center%  %width=300% [[Attach:grille.png|Attach:grille.png]] | [-'''Figure 3''' maillage de l'espace.-]

Code associé:
(:source lang=python:)
 # construction d'une grille réguliere de point sur l'espace 2D
 ngrid = 30              # finesse de la grille
 xgrid = mesh(x,ngrid)    # ou simplement xgrid = mesh(x)

 # affichage de la grille
 pl.figure(2)
 pl.plot(xgrid[:,0],xgrid[:,1],'+') # on voit que l'espace est entièrement couvert
(:sourceend:)

!!!! 3. Evaluer le modèle sur la grille

Sur les données étiquetées, un modèle est appris:

(:source lang=python:)
 # fonction de decision linéaire au sens du perceptron
 w = perceptron(x,y,0.1,1000)
 # OU fonction de décision au sens des moindres carrés
 w = np.linalg.solve((x.T.dot(x)), (x.T.dot(y)))
(:sourceend:)

Le modèle (ici linéaire) est ensuite appliqué sur les points de la grille:

(:source lang=python:)
 # application du modele sur la grille
 ygrid = xgrid.dot(w);
(:sourceend:)

Puis affiché (ATTENTION, il faut afficher un nuage de point en 3D)

(:source lang=python:)
import matplotlib.pyplot as pl
from mpl_toolkits.mplot3d import Axes3D

fig = pl.figure(3)
ax = fig.gca(projection='3d')    # déclarer la 3D
ax.scatter(xgrid[:,0],xgrid[:,1], ygrid) # fonction d'affichage d'un nuage de point
(:sourceend:)

%center% %width=400% [[Attach:evalGrille3D.png|Attach:evalGrille3D.png]]  | [-'''Figure 4''' Evaluation du modèle sur les points de la grille.-]

La figure est en 3D: 2 dimensions {$xgrid_1$} et {$xgrid_2$} pour les données et une dimension {$z=\hat y$} pour l'évaluation du modèle.

!!!! 4. Affichage(s) avancé(s)

Une fois dans cette configuration, plusieurs affichages sont possibles.
# soit on reste en 3D et on trace la fonction de décision (c'est à dire le score pour chaque point de l'espace)
# soit on passe en 2D et on trace la frontière de décision (moins clinquant mais souvent plus parlant)

'''Solution 1:'''

%center% %width=400% [[Attach:surface3D.png|Attach:surface3D.png]]  | [-'''Figure 5''' Evaluation du modèle sur les points de la grille, affichage sous forme de surface + rappel des points d'apprentissage.-]

(:source lang=python:)
import matplotlib.pyplot as pl
from mpl_toolkits.mplot3d import Axes3D


n = np.sqrt(xgrid.shape[0])
xgrid1 = xgrid[:,0:1].reshape((n,n)); # Dim1: retour à une forme de grille
xgrid2 = xgrid[:,1:2].reshape((n,n)); # Dim2: retour à une forme de grille 
ygridS = ygrid.reshape((n,n));        # Eval: retour à une forme de grille 
   
fig = pl.figure(4)
ax = fig.gca(projection='3d')        # déclarer la 3D
ax.plot_surface(xgrid1,xgrid2, ygridS, rstride=1, cstride=1, cmap=cm.coolwarm,
                    linewidth=0, antialiased=False) # tracé de la fonction de décision
                                                    # seuls les 3 premiers args sont obligatoires
ax.scatter(x[np.where(y[:,0]==1),0],x[np.where(y[:,0]==1),1],0,s=10,c='r')  # pts classe 1
ax.scatter(x[np.where(y[:,0]==-1),0],x[np.where(y[:,0]==-1),1],0,s=10,c='b') # pts classe -1
(:sourceend:)


'''Solution 2:'''

On s'intéresse seulement au moment où la surface croise le plan {$z=0$} et on trace un isocontour d'équation {$f(w_1,w_2)=0$}

%center% %width=400% [[Attach:plotFrontiere3D.png|Attach:plotFrontiere3D.png]]  | [-'''Figure 6''' Evaluation du modèle sur les points de la grille, affichage de l'isocontour {$f(w_1,w_2)=0$}.-]


Code correspondant:

(:source lang=python:)
import matplotlib.pyplot as pl

n = np.sqrt(xgrid.shape[0])
xgrid1 = xgrid[:,0:1].reshape((n,n)); # Dim1: retour à une forme de grille
xgrid2 = xgrid[:,1:2].reshape((n,n)); # Dim2: retour à une forme de grille 
ygridS = ygrid.reshape((n,n));        # Eval: retour à une forme de grille 
   
fig = pl.figure(5)
indC1,buf = np.where(y==1)
indC2,buf = np.where(y==-1)
pl.plot(x[indC1,0], x[indC1,1], 'r+')
pl.plot(x[indC2,0], x[indC2,1], 'b+')
pl.contour(xgrid1,xgrid2,ygridS,[0])  # comme pour un tracé 3D mais on ajoute l'isocontour qui nous intéresse
(:sourceend:)

----

>>block bgcolor=#ffbbbb<<
!!! (pas vraiment une) Application

On souhaite dans cet exercice tracer des courbes en 3D {$f(x,y)$} puis la
dessiner dans la question.


On souhaite créer la fonction {$f(x,y) = x^2 + y^2$}, pour {$x \in [1,3]$}
et {$y \in [-1,1]$}. Afin d'exploiter les vecteurs et matrices d'Octave, on
discrétise cet espace en n'en sélectionnant que 5 valeurs par axe~:
(:source lang=python:)
 x = np.array([  1.0000    1.5000    2.0000    2.5000    3.0000 ]) # définir l'axe des x
 y = np.array([ -1.00000  -0.50000  0.00000  0.50000  1.00000]) # définir l'axe des y

 xgrid, ygrid = np.meshgrid(x, y) # création des combinaisons
(:sourceend:)
Résultat :

 xgrid =                                        ygrid =
  1.0000  1.5000  2.0000  2.5000  3.0000    -1.00000  -1.00000  -1.00000  -1.00000  -1.00000
  1.0000  1.5000  2.0000  2.5000  3.0000    -0.50000  -0.50000  -0.50000  -0.50000  -0.50000
  1.0000  1.5000  2.0000  2.5000  3.0000      0.00000  0.00000  0.00000  0.00000  0.00000
  1.0000  1.5000  2.0000  2.5000  3.0000      0.50000  0.50000  0.50000  0.50000  0.50000
  1.0000  1.5000  2.0000  2.5000  3.0000      1.00000  1.00000  1.00000  1.00000  1.00000

Création de la fonction f:
(:source lang=python:)
 f = xgrid * xgrid + ygrid * ygrid
(:sourceend:)


Pour pouvoir tracer {$f$} en 3D, la variable f doit avoir les mêmes dimensions que xgrid et ygrid.

(:source lang=python:)
import matplotlib.pyplot as pl
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

fig = pl.figure(1)
ax = fig.gca(projection='3d')
ax.plot_surface(xgrid1,xgrid2, ygridS)
# ou pour faire plus joli
# ax.plot_surface(xgrid, ygrid, f, rstride=1, cstride=1, cmap=cm.coolwarm,
#                    linewidth=0, antialiased=False)

fig = pl.figure(2)

pl.contour(xgrid, ygrid, f) # affiche les courbes de niveau de f
(:sourceend:)
>><<