Se lancer dans l’Auto-ML avec AutoGluon

Qu’est-ce que l’Auto-ML ?

L’AutoML (ou Machine Learning Automatisé) consiste à automatiser le processus d’apprentissage inhérent à toute solution de Machine learning. L’AutoML va donc gérer et produire (en arrière boutique et sans intervention d’un Datascientiste) le pipeline complet de modélisation de l’ensemble de données brutes jusqu’au modèle abouti déployable. Cett approche est proposée comme une solution elle-même d’intelligence artificielle qui permet de simplifier et accélérer cette phase de modélisation. C’est du moins sa promesse ! voyons ce que cela donne …

L’idée est donc de permettre aux non-experts de concevoir et utiliser des modèles et des techniques d’apprentissage automatique sans avoir à devenir au préalable un expert dans ce domaine.

La réalité est toute autre car si ces solutions d’AutoML fonctionne pas trop mal (nous allons le voir ici avec AutoGluon), dans la réalité la patte de l’artiste (le DataScientiste) reste indispensable pour ajuster les données au préalable et les affiner.

Néanmoins – et à l’heure actuelle – ces solutions ont au moins pour vertu de démocratiser le machine Learning en le rendant plus accessible. Ne négligeons donc pas son apport pédagogique, et puis nous en sommes au début et il parait évident que ce type de solution se profilent comme l’avenir de l’IA.

AutoGluon

Pour commencer dans l’AutoML nous allons utiliser AutoGluon.

AutoGluon est une librairie très récente Open-Source publiée par Amazon. Il est vrai que j’aurai pu commencer plus simple en utilisant un outil plus graphique comme Dataiku (qui fera certainement l’objet d’un article ultérieur) … mais je voulais garder la comparaison possible par rapport au travail Python/scikit-learn effectué précédemment (Cf. articles).

En allant sur le site d’AutoGluon on comprend très vite son utilité :

  • Rapide prototypage de Modèles de ML en quelques lignes
  • Profiter de l’ajustement automatique des hyperparamètres, de la sélection de modèle / recherche d’architecture et du traitement des données.
  • Utilisation automatique des techniques de Deep Learning.
  • Amélioration des modèles et des pipelines de données existants

De plus AutoGuon est personnalisable … alors pourquoi s’en priver ?

Tout d’abord installons les librairies Python d’AutoGluon (avec PIP et sans GPU):

pip install --upgrade mxnet
pip install autogluon

AutoGluon vs Titanic

Commençons par déclarer les librairies :

import autogluon as ag
import pandas as pd
from autogluon import TabularPrediction as task

Puis récupérons le dataset du titanic (Kaggle) :

train_data = task.Dataset(file_path="../datasources/titanic/train.csv")
print(train_data.head())
Loaded data from: ../datasources/titanic/train.csv | Columns = 12 / 12 | Rows = 891 -> 891

   PassengerId  Survived  Pclass  \
0            1         0       3   
1            2         1       1   
2            3         1       3   
3            4         1       1   
4            5         0       3   

                                                Name     Sex   Age  SibSp  \
0                            Braund, Mr. Owen Harris    male  22.0      1   
1  Cumings, Mrs. John Bradley (Florence Briggs Th...  female  38.0      1   
2                             Heikkinen, Miss. Laina  female  26.0      0   
3       Futrelle, Mrs. Jacques Heath (Lily May Peel)  female  35.0      1   
4                           Allen, Mr. William Henry    male  35.0      0   

   Parch            Ticket     Fare Cabin Embarked  
0      0         A/5 21171   7.2500   NaN        S  
1      0          PC 17599  71.2833   C85        C  
2      0  STON/O2. 3101282   7.9250   NaN        S  
3      0            113803  53.1000  C123        S  
4      0            373450   8.0500   NaN        S  

Regardons de plus près le dataset (qui ressemble, mais qui n’est pas un dataframe Pandas) :

print("Détail sur la colonne survivant: \n", train_data['Survived'].describe())
Détail sur la colonne survivant: 
 count    891.000000
mean       0.383838
std        0.486592
min        0.000000
25%        0.000000
50%        0.000000
75%        1.000000
max        1.000000
Name: Survived, dtype: float64

Maintenant entraînons directement le modèle sur les données brutes. On voit ici l’interet de l’AutoML. Pas besoin de:

  • Segmenter le jeu de données
  • Préparer les données
  • Choisir un modèle de Machine Learning
  • … et encore moins besoin d’affiner les hyperparamètres!
dir = 'models'
label_col = 'Survived'
predictor = task.fit(train_data=train_data, label=label_col, output_directory=dir)

Quand on lance la commande précédente, AutoGluon se met au travail … les lignes défilent alors comme ci-dessous. On peut alors voir les étapes de travail que l’on effectuait manuellement s’opérer

Beginning AutoGluon training ...
AutoGluon will save models to models/
Train Data Rows:    891
Train Data Columns: 12
Preprocessing data ...
Here are the first 10 unique label values in your data:  [0 1]
AutoGluon infers your prediction problem is: binary  (because only two unique label-values observed)
If this is wrong, please specify `problem_type` argument in fit() instead (You may specify problem_type as one of: ['binary', 'multiclass', 'regression'])

Selected class <--> label mapping:  class 1 = 1, class 0 = 0
Feature Generator processed 891 data points with 33 features
Original Features:
	int features: 4
	object features: 5
	float features: 2
Generated Features:
	int features: 22
All Features:
	int features: 26
	object features: 5
	float features: 2
	Data preprocessing and feature engineering runtime = 0.34s ...
AutoGluon will gauge predictive performance using evaluation metric: accuracy
To change this, specify the eval_metric argument of fit()
AutoGluon will early stop models using evaluation metric: accuracy
/opt/anaconda3/lib/python3.7/imp.py:342: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working
  return _load(spec)
Fitting model: RandomForestClassifierGini ...
	0.8268	 = Validation accuracy score
	0.81s	 = Training runtime
	0.12s	 = Validation runtime

...

Fitting model: weighted_ensemble_k0_l1 ...
	0.8547	 = Validation accuracy score
	0.39s	 = Training runtime
	0.0s	 = Validation runtime
AutoGluon training complete, total runtime = 13.3s ...

Que s’est-il passé lors de l’entraintement (avec fit()) ?

On est dans un problème de classification binaire (survivant ou pas). AutoGluon déduit automatiquement que la mesure de performance appropriée est la précision. Il analyse et déduit ainsi le type de chaque entité (c’est-à-dire quelles colonnes contiennent des nombres continus par rapport à aux catégories discrètes). AutoGluon a également gérer des problèmes de données manquantes et la mise à l’échelle des valeurs des fonctionnalités. Voilà qui simplifie la vie n’est-ce pas ?

Dans l’exemple ci-dessus, nous n’avons pas spécifié de données de validation distinctes. AutoGluon choisit donc automatiquement un découpage aléatoire des données pour l’entrainement. Les données utilisées pour la validation sont séparées des données d’apprentissage et sont utilisées pour déterminer les modèles et les valeurs d’hyperparamètre qui produisent les meilleurs résultats. Et oui ! l’idée est ne pas utiliser qu’un seul algorithme/modèle … pour cela Autogluon teste plusieurs modèles et les assemble pour garantir des performances prédictives optimales.

La solution va donc essayer différents types de modèles (dont des modèles de deep learning) et choisir le meilleur tout en ajustant les hyperparamètres les mieux adaptés à) chacun.

Regardons maintenant les prédictions de ce modèle :

predictor = task.load(dir) # Nécéssaire seulement si le modèle n'avait pas été chargé au préalable
y_train = train_data[label_col]
x_train_data = train_data.drop(labels=[label_col],axis=1) 
y_train_pred = predictor.predict(x_train_data)
print("Predictions:  ", y_train_pred)
Predictions:   [0 1 1 1 0 0 0 0 1 1 1 1 0 ...
 0 0 1 0 1 1 1 1 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 1
 0 1 0]

Et sa performance dans tout ça ? facile utilisons la méthode evaluate_predictions()

perf = predictor.evaluate_predictions(y_true=y_train, y_pred=y_train_pred, auxiliary_metrics=True)
Evaluation: accuracy on test data: 0.961841
Evaluations on test data:
{
    "accuracy": 0.9618406285072951,
    "accuracy_score": 0.9618406285072951,
    "balanced_accuracy_score": 0.954702329594478,
    "matthews_corrcoef": 0.919374313148082,
    "f1_score": 0.9618406285072951
}
Detailed (per-class) classification report:
{
    "0": {
        "precision": 0.9541446208112875,
        "recall": 0.9854280510018215,
        "f1-score": 0.9695340501792115,
        "support": 549
    },
    "1": {
        "precision": 0.9753086419753086,
        "recall": 0.9239766081871345,
        "f1-score": 0.9489489489489489,
        "support": 342
    },
    "accuracy": 0.9618406285072951,
    "macro avg": {
        "precision": 0.9647266313932981,
        "recall": 0.954702329594478,
        "f1-score": 0.9592414995640801,
        "support": 891
    },
    "weighted avg": {
        "precision": 0.9622681844904067,
        "recall": 0.9618406285072951,
        "f1-score": 0.9616326981918379,
        "support": 891
    }
}

Nous avons une performance de 96% sur les données d’entraînement, c’est pas mal mais ça ne veut pas dire grand chose. Pour voir si notre modèle est performant nous allons bien sur le confronter au jeu de test Kaggle et soumettre le résultat de la prédiction afin de voir notre score.

Soumettons notre modèle à Kaggle

Nous allons pour cela récupérer le jeu de test sur le site Kaggle et utiliser la prédiction de notre modèle :

test_data = task.Dataset(file_path='../datasources/titanic/test.csv')
print(test_data.head())
predictor = task.load(dir) # Nécéssaire seulement si le modèle n'avait pas été chargé au préalable
y_pred = predictor.predict(test_data)
print("Predictions:  ", y_pred)
Predictions:   [0 1 0 0 1 0 1 0 1 0 0 0 1 0 1 1 0 0 0 1 0 1 1 1 1 0 1 0 0 0 0 0 1 1 1 0 1
 1 0 1 0 0 0 1 1 0 0 0 1 1 0 0 1 1 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 0 0 0
 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 1 1 0 1 0 0 0 1 0 1 0 1 0 0 0 1 0 0 0 0 0 0
 1 1 1 1 0 0 1 0 1 1 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0
 0 0 1 0 0 1 0 0 1 1 0 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 0 1 1 0 1
 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 1 1 1 1 0 0 1 0 1 0 0 0 0 1 0 0 1 0 1 0 1 0
 1 0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0 1
 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
 1 0 0 0 0 0 0 0 1 1 1 1 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 0 0
 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 0 0 1 1 0 1 0 0 0 1 0
 0 1 0 0 1 1 1 0 0 0 0 0 1 1 0 1 0 0 0 0 0 1 1 0 1 1 0 1 0 0 1 0 1 0 0 0 0
 0 1 1 1 1 0 0 1 0 0 0]

Maintenant formatons les données prédisent pour que kaggle puisse étudier notre résultat :

final = pd.DataFrame()
for i in range(len(test_data)):
    row = {'PassengerId' : str(test_data['PassengerId'][i]) , 'Survived' : str(y_pred[i])}
    final = final.append(row , ignore_index=True)
final.to_csv("result.csv", columns=["PassengerId", "Survived"], index=False)

… Suspence !!!

Ouch ! après soumission sur kaggle on obtient un score de 0.55980

Conclusion

C’est pas terrible quand même (56%) mais cela prouve une chose. Ces outils (AutoML) ne sont pas magique. C’est vrai j’aurai pu personnalisé le comportement de AutoGluon mais alors quid du coté Automatique ? AU delà du résultat je trouve que ce type d’outil possède à minima deux vertus. La première est pédagogique bien sur, la seconde, elle, est de permettre un prototypage rapide.

Pour moi cela prouve aussi une chose c’est que la connaissance des données (et donc par corollaire sa préparation) est une étape cruciale dans tout projet de Machine Learning. Data Scientistes, rassurez-vous, votre boulot n’est pas – encore – en danger. Par contre il est intéressant de constater comme ces outils masquent de plus en plus les aspects techniques au profit d’une meilleure connaissance métier.

Partager cet article

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.