Les premiers pas
En général, un problème d'apprentissage prend en compte un ensemble de n échantillons de données et tente ensuite de prédire les propriétés de données inconnues. Si chaque échantillon est constitué de plusieurs nombres et, par exemple, d'une entrée multidimensionnelle (c'est-à-dire de données multivariées), on dit qu'il possède plusieurs attributs ou caractéristiques.
Vous pouvez séparer les problèmes d'apprentissage en quelques grandes catégories :
- Apprentissage supervisé, dans lequel les données sont accompagnées d'attributs supplémentaires que nous souhaitons prédire. Ce problème peut être soit :
- Classification : Les échantillons appartiennent à deux ou plusieurs classes et nous voulons apprendre à partir de données déjà étiquetées comment prédire la classe des données non étiquetées. Un exemple de problème de classification serait l'exemple de reconnaissance de chiffres manuscrits, dans lequel le but est d'attribuer chaque vecteur d'entrée à l'une d'un nombre fini de catégories discrètes. Une autre façon de considérer la classification est de la considérer comme une forme discrète (par opposition à continue) d'apprentissage supervisé où l'on dispose d'un nombre limité de catégories et où, pour chacun des n échantillons fournis, on essaie de les étiqueter avec la bonne catégorie ou classe.
- Régression : Si la sortie souhaitée se compose d'une ou plusieurs variables continues, la tâche est alors appelée régression. Un exemple de problème de régression serait la prédiction de la longueur d'un saumon en fonction de son âge et de son poids.
- Apprentissage non supervisé, dans lequel les données d'apprentissage se composent d'un ensemble de vecteurs d'entrée x sans aucune valeur cible correspondante. L'objectif de tels problèmes peut être de découvrir des groupes d'exemples similaires dans les données, ce qu'on appelle l'unité d'allocation, ou de déterminer la distribution des données dans l'espace d'entrée, ce qu'on appelle l'estimation de la densité, ou de projeter les données d'un espace à haute dimension vers deux ou trois dimensions à des fins de visualisation.
Ensemble d'entraînement et ensemble de test
L'apprentissage automatique consiste à apprendre certaines propriétés d'un ensemble de données et à les appliquer à de nouvelles données. C'est pourquoi une pratique courante dans l'apprentissage automatique pour évaluer un algorithme consiste à diviser les données disponibles en deux ensembles, l'un que nous appelons l'ensemble d'entraînement sur lequel nous apprenons les propriétés des données et l'autre que nous appelons l'ensemble de test sur lequel nous testons ces propriétés.
Chargement d'un exemple d'ensemble de données
scikit-learn est fourni avec quelques ensembles de données standard, par exemple les ensembles de données iris et digits pour la classification et l'ensemble de données prix des maisons à Boston pour la régression.
Dans ce qui suit, nous démarrons un interpréteur Python à partir de l'interpréteur de commande, puis chargeons les ensembles de données iris et digits. Notre convention de notation est que $ désigne le prompt de l'interpréteur de commande tandis que >>> désigne le prompt de l'interpréteur Python :
$ python >>> from sklearn import datasets >>> iris = datasets.load_iris() >>> digits = datasets.load_digits() |
Un ensemble de données est un objet de type dictionnaire contenant toutes les données et certaines métadonnées sur les données. Ces données sont entreposées dans le membre .data, étant un tableau n_samples, n_features. Dans le cas d'un problème supervisé, une ou plusieurs variables de réponse sont entreposées dans le membre .target.
Par exemple, dans le cas de l'ensemble de données digits, digits.data donne accès aux fonctionnalités pouvant être utilisées pour classer les échantillons digits :
>>> print(digits.data) [[ 0. 0. 5. ..., 0. 0. 0.] [ 0. 0. 0. ..., 10. 0. 0.] [ 0. 0. 0. ..., 16. 9. 0.] ..., [ 0. 0. 1. ..., 6. 0. 0.] [ 0. 0. 2. ..., 12. 0. 0.] [ 0. 0. 10. ..., 12. 1. 0.]] |
et digits.target donne la vérité fondamentale pour l'ensemble de données de chiffres, c'est-à-dire le nombre correspondant à chaque image de chiffre que nous essayons d'apprendre :
>>> digits.target array([0, 1, 2, ..., 8, 9, 8]) |
Forme des tableaux de données
Les données sont toujours un tableau en 2 dimensions de forme (n_samples, n_features), bien que les données d'origine puissent avoir une forme différente. Dans le cas des chiffres, chaque échantillon d'origine est une image de forme (8, 8) et peut être consulté à l'aide de :
>>> digits.images[0] array([[ 0., 0., 5., 13., 9., 1., 0., 0.], [ 0., 0., 13., 15., 10., 15., 5., 0.], [ 0., 3., 15., 2., 0., 11., 8., 0.], [ 0., 4., 12., 0., 0., 8., 8., 0.], [ 0., 5., 8., 0., 0., 9., 8., 0.], [ 0., 4., 11., 0., 1., 12., 7., 0.], [ 0., 2., 14., 5., 10., 12., 0., 0.], [ 0., 0., 6., 13., 10., 0., 0., 0.]]) |
L'exemple simple de cet ensemble de données illustre comment, à partir du problème initial, on peut façonner les données pour les utiliser dans scikit-learn.
Apprentissage et prédiction
Dans le cas de l'ensemble de données de chiffres, la tâche consiste à prédire, à partir d'une image, quel chiffre elle représente. On nous donne des échantillons de chacune des 10 classes possibles (les chiffres de zéro à neuf) sur lesquels nous ajustons un estimateur pour pouvoir prédire les classes auxquelles appartiennent les échantillons invisibles.
Dans scikit-learn, un estimateur pour la classification est un objet Python implémentant les méthodes fit(X, y) et predict(T).
Un exemple d'estimateur est la classe sklearn.svm.SVC implémentant la classification des vecteurs de support. Le constructeur d'un estimateur prend comme arguments les paramètres du modèle, mais pour le moment, nous considérerons l'estimateur comme une boîte noire :
>>> from sklearn import svm >>> clf = svm.SVC(gamma=0.001, C=100.) |
Choix des paramètres du modèle
Dans cet exemple, nous définissons manuellement la valeur de gamma. Il est possible de trouver automatiquement de bonnes valeurs pour les paramètres en utilisant des outils tels que la recherche de grille et la validation croisée.
Nous appelons notre instance d'estimateur clf, car il s'agit d'un classificateur. Il doit maintenant être ajusté au modèle, c'est-à-dire qu'il doit apprendre du modèle. Cela se fait en passant notre ensemble d'apprentissage à la méthode fit. Comme ensemble d'apprentissage, utilisons toutes les images de notre ensemble de données à l'exception de la dernière. Nous sélectionnons cet ensemble d'apprentissage avec la syntaxe Python [:-1], qui produit un nouveau tableau contenant toutes les entrées de digits.data sauf la dernière :
>>> clf.fit(digits.data[:-1], digits.target[:-1]) SVC(C=100.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.001, kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False) |
Vous pouvez maintenant prédire de nouvelles valeurs. En particulier, nous pouvons demander au classificateur quel est le chiffre de notre dernière image dans l'ensemble de données de chiffres, que nous n'avons pas utilisé pour entraîner le classificateur :
>>> clf.predict(digits.data[-1]) array([8]) |
L'image correspondante est la suivante :
Comme vous pouvez le constater, il s'agit d'une tâche difficile : les images sont de mauvaise résolution. Êtes-vous d'accord avec le classificateur ?
Persistance du modèle
Il est possible de sauvegarder un modèle dans scikit en utilisant le modèle de persistance intégré de Python, à savoir pickle :
>>> from sklearn import svm >>> from sklearn import datasets >>> clf = svm.SVC() >>> iris = datasets.load_iris() >>> X, y = iris.data, iris.target >>> clf.fit(X, y) SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, degree=3, gamma=0.0, kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False) >>> import pickle >>> s = pickle.dumps(clf) >>> clf2 = pickle.loads(s) >>> clf2.predict(X[0]) array([0]) >>> y[0] 0 |
Dans le cas spécifique de scikit, il peut être plus intéressant d'utiliser le remplacement de pickle par joblib (joblib.dump et joblib.load), étant plus efficace sur les mégadonnées, mais ne peut pickler que sur le disque et non sur une chaîne de caractères :
>>> from sklearn.externals import joblib >>> joblib.dump(clf, 'filename.pkl') |
Plus tard, vous pouvez recharger le modèle pickle (éventuellement dans un autre processus Python) avec :
>>> clf = joblib.load('filename.pkl') |
Remarque
joblib.dump renvoie une liste de noms de fichiers. Chaque tableau numpy individuel contenu dans l'objet clf est sérialisé en tant que fichier séparé sur le système de fichiers. Tous les fichiers doivent être dans le même dossier lors du rechargement du modèle avec joblib.load.
Notez que pickle présente certains problèmes de sécurité et de maintenabilité.