Cette page fait partie du cours de polytech PeiP1 et 2 Bio

10. Mise en pratique : SVM

10.1. Introduction

Les SVM (Support Vector Machines) où Machines à Vecteur de Support sont en fait un classifieur linéaire dit à large marge.

On rappelle que le classifieur permet de séparer (classer) des données lorsque l'on connaît déjà les classes existantes. On parle alors de classification Supervisée par opposition à la classification Non Supervisée pour laquelle on ne connaît pas le nombre de classes.

10.2. Le cadre théorique

Voici deux liens concernant des éléments théoriques liés aux SVM :

L'utilisation d'un kernel (qui est une fonction) permet de modifier l'espace initial des données et de les transposer dans un espace d'ordre supérieur :


SVM Linéaire sans Kernel


SVM Linéaire avec Kernel $x^2$

Le problème des SVM et qu'elles dépendent de beaucoup de paramètres et que la recherche des meilleurs paramètres (ceux qui donnent la meilleure prédiction) peut demander beaucoup de temps. On pourra, afin de les rechercher, utiliser la classe GridSearchCV du paquet sklearn.model_selection.

10.3. Application aux Iris de Fisher

10.3.1. Apprentissage et validation

On essaye d'appliquer le classifieur SVM aux iris de Fisher afin de prédire, à partir des données des sépales ou pétales, à quelle espèce appartient l'iris : Setosa, Versicolor, Virginica .

Dans le cadre de l'apprentissage, on a tendance à séparer les données en deux sous-ensembles :

On se trouve confronté ici à un dilemme du même type que celui ci:

Tout ceci n'est qu'une affaire de point de vue car dans le cas où on prend la totalité des données, il est évident que de nouvelles données viendront s'ajouter par la suite qui confirmeront ou infirmeront le modèle d'apprentissage.

10.3.2. Résolution

Pour résoudre notre problèmen on utilise la classe SVC (C-Support Vector Classification) du paquet svm.

svm_iris.py

  1. #####################################################################
  2. # Exemple d'utilisation de SVM
  3. # Utilisation des données des iris de Fisher
  4. #####################################################################
  5.  
  6.  
  7. #####################################################################
  8. # import des librairies
  9. #####################################################################
  10. from sklearn.datasets import load_iris
  11. from sklearn.model_selection import train_test_split
  12. from sklearn.svm import SVC
  13. from sklearn.metrics import accuracy_score
  14. import matplotlib.pyplot as plt
  15. from mpl_toolkits.mplot3d import Axes3D
  16. import pandas as pd
  17. import numpy as np
  18. import sys
  19.  
  20. #
  21. # Définition de chaines pour l'affichage
  22. #
  23. line = "=" * 50
  24. separator = "\n" * 2
  25.  
  26.  
  27. #####################################################################
  28. # Données
  29. #####################################################################
  30.  
  31. #
  32. # On charge les données depuis sklearn
  33. # On obtient un sklearn.utils.Bunch
  34. #
  35. iris = load_iris()
  36.  
  37. #
  38. # Affiche les différents champs
  39. #
  40. iris_keys = iris.keys()
  41. for k in iris_keys:
  42.   print(line)
  43.   print(k)
  44.   print(iris[k])
  45.  
  46.  
  47. #
  48. # On transforme les données en DataFrame de pandas
  49. # afin de pouvoir les manipuler plus simplement
  50. #
  51. df = pd.DataFrame(data = np.c_[ iris['data'], iris['target'] ],
  52.   columns= iris['feature_names'] + ['target'])
  53.  
  54. #
  55. # On renomme les colonnes pour les manipuler plus
  56. # simplement
  57. # (inPlace=True évite de faire une copie du DataFrame)
  58. #
  59. df.rename( columns = {
  60.   'sepal length (cm)': 'sepal_length' ,
  61.   'sepal width (cm)': 'sepal_width',
  62.   'petal length (cm)': 'petal_length',
  63.   'petal width (cm)': 'petal_width'},
  64.   inplace=True )
  65.  
  66. #
  67. # On garde toutes les propriétés sauf la cible pour effectuer
  68. # le calcul de la SVM
  69. #
  70. variables_du_modele = df.columns.drop(['target'])
  71.  
  72. #
  73. # y est le vecteur de sortie à prédire
  74. #
  75. y = df.target
  76.  
  77. #
  78. # X est une matrice des données en entrées
  79. #
  80. X = df[ variables_du_modele ]
  81.  
  82. #####################################################################
  83. # Séparation des données
  84. # - données d'apprentissage X_a, y_a
  85. # - données de validation X_v, y_v
  86. #####################################################################
  87.  
  88. #
  89. # On crée deux jeux de données à partir de (X,y)
  90. # - le jeu d'apprentissage X_a, y_a (70% des individus)
  91. # - le jeu de test (X_v, y_v) qui permettra de vérifier
  92. #       la prédiction (30% des individus)
  93. #
  94. X_a, X_v, y_a, y_v = train_test_split(X, y, test_size=0.30)
  95.  
  96. #####################################################################
  97. # Classifieur
  98. #####################################################################
  99.  
  100. #
  101. # création du classifieur
  102. #
  103. classifier = SVC(C=0.05, kernel='linear', gamma='auto')
  104.  
  105. #
  106. # calcul sur ensemble d'apprentissage
  107. #
  108. print(line)
  109. print(" Classification sur ensemble d'apprentissage")
  110. print(line)
  111.  
  112. classifier.fit(X_a, y_a)
  113.  
  114. #####################################################################
  115. # Prédiction
  116. # sur le jeu de validation
  117. #####################################################################
  118.  
  119. print(line)
  120. print("Prédiction")
  121. print(line)
  122. y_v_prime = classifier.predict(X_v)
  123. print("précision=", accuracy_score(y_v, y_v_prime) )
  124. print( str(classifier) )
  125.  
  126. #####################################################################
  127. # graphique des données
  128. #####################################################################
  129.  
  130. #
  131. # On travaille à présent sur toutes les données et on compare
  132. # la prédiction
  133. #
  134. y_prime =  classifier.predict(X)
  135. fig = plt.figure()
  136. axes = fig.add_subplot(111, projection='3d')
  137. plt.title("Résultats Classification SVM")
  138. axe1 = X['sepal_length']
  139. axe2 = X['sepal_width']
  140. axes.scatter(axe1, axe2, y.tolist(), c=y_prime, cmap=plt.cm.jet)
  141.  
  142. plt.show()
  143.  
  144.  
  145.  

Exercice 10.1

Tester la solution précédente avec d'autres kernels comme :

classifier = SVC(C=0.006, kernel='rbf', gamma='scale')

ou

classifier = SVC(C=1.0, kernel='poly', gamma='auto', degree=7)

Qu'obtient-on comme résultat ?

10.4. Mise en application

Exercice 10.2

Utiliser le jeu de données breast_cancer de Scikit-Learn et tenter de créer une SVM qui permet de différencier tumeurs malignes des tumeurs bénignes.