Table des matières

Tutoriel : Utilisation d'un classifieur SVR pour la prédiction des mouvements imaginés

Introduction

Le classifieur SVR (Support Vector Regression) est une variante très efficace de la SVM (Support Vector Machine) utilisée pour la régression. Nous allons cependant pouvoir l'utiliser dans un cas de classification à quatre classes comme nous le verrons lors de ce tutoriel.

L'idée d'utiliser un classifieur SVR nous est venue du tutoriel proposé par la FBCSP toolbox dans lequel son utilisation donne de bons résultats.

Ce tutoriel va donc viser à expliquer comment utiliser un classifieur SVR pour la détection des mouvements imaginés des mains, des pieds et de la langue (en exploitant le dataset BCI Competition 2008 2a).

Principe général de fonctionnement

Les classifieurs SVR reposent sur un principe assez particulier pour déterminer une classe discrète : il nécessite de réaliser, pour chaque essai du dataset, une classification par classe. Pour un cas à quatre classe comme présentement, il nous faudra, pour chaque essai du dataset, itérer afin de récupérer les valeurs de régression pour les classe “main droite”, “main gauche”, “pieds” et “langue”.

La classe finale de chaque essai est déterminée en déterminant le minimum des différentes valeurs pour chaque classe. Il sera donc nécessaire de stocker pour chaque essai l'ensemble des valeurs, par exemple dans un tableau de taille [nb_essais,nb_classes].

Utilisation d'un classifieur SVR

Pour ce tutoriel, nous nous baserons sur les données récupérées du dataset BCI Competition 2008 2a.

Étape 1 : Création des tableaux de récupération des données de régression

La première étape consiste à définir le nombre de classes du problème considéré, récupérer le tableau contenant les indices des différentes classes et enfin établir un tableau qui recueillera les données de régression pour chaque essai.

Ceci est réalisable grâce au fragment de code suivant :

n_classes = 4
y_classes_unique = np.unique(y_train)
y_test_predicted = np.zeros((y_test.shape[0], n_classes), dtype=float)

Étape 2 : Obtention des valeurs de régression pour chaque classe de chaque essai

Pour obtenir les valeurs de régression pour chaque classe, on boucle sur le tableau des classes.

Pour chacune de celles-ci, on transforme le tableau contenant les labels de chaque classe en mettant 0 si le label correspond à la classe actuellement étudiée et 1 sinon.

On définit ensuite un classifieur SVR avec la classe Classifier de FBCSP toolbox (dans le cas présent).

Enfin, on entraîne le classifieur avec la méthode predict() et avec les données qu'on souhaite utiliser pour l'entraînement (si le classifieur n'a pas été entraîné) couplées au tableau de labels précédemment modifié.

Ensuite on met dans le tableau de recueil des données, à l'emplacement de la classe en cours d'étude, la valeur de régression issue de la méthode predict().

 for j in range(n_classes):
 
        cls_of_interest = y_classes_unique[j]
 
        select_class_labels = lambda cls, y_labels: [0 if y == cls else 1 for y in y_labels]
 
        y_train_cls = np.asarray(select_class_labels(cls_of_interest, y_train))
 
        classifier_type = SVR(gamma='auto')
        classifier = Classifier(classifier_type)
 
        classifier.fit(x_features_train, np.asarray(y_train_cls, dtype=float))
 
        y_test_predicted[:, j] = classifier.predict(x_features_test)

Étape 3 : Détermination des labels finaux

Pour déterminer la classe finalement prédite par notre algorithme, il suffit de prendre, pour chaque essai, la position (et donc la classe) pour laquelle la valeur de régression déterminée par le classifieur SVR est minimale.

Ceci peut s'opérer de la manière suivante :

y_test_predicted_multi = np.asarray([np.argmin(y_test_predicted[i,:]) for i in range(y_test_predicted.shape[0])]) 

Ainsi, la variable y_test_predicted_multi contient maintenant les labels prédits pour chaque essai. Il faut cependant se méfier car pour certains dataset un offset est appliqué (c'est-à-dire que les classes de ce dataset commencent par un nombre différent de 0, par exemple 1).

Or, cette méthode considère que la première classe correspond au nombre 0. Il sera donc nécessaire dans ces cas de rajouter l'offset à la variable y_test_predicted_multi (étant une matrice numpy, cela aura pour effet d'ajouter 1 à toutes ses cases).

Par exemple, dans le cas du dataset BCI Competition 2008 2a, il sera nécessaire de rajouter la valeur 1 à la variable y_test_predicted_multi. On aura donc besoin de la ligne suivante à la place de celle décrite précédemment :

offset = 1
y_test_predicted_multi = np.asarray([np.argmin(y_test_predicted[i,:]) for i in range(y_test_predicted.shape[0])]) + offset