Azure Machine Learning et Python: Apprentissage régulier et automatisé avec Scikit-learn
Bonjour,
Julien Moreau-Mathis nous propose aujourd'hui un deuxième article sur Python et Machine Learning.
Pour faire plus amples connaissances, Julien est étudiant à l’école IN’TECH INFO, une école d’informatique et est actuellement en alternance (Master) au sein de la Division DX (Developer Experience) de Microsoft France. A l’origine, Julien nous viens du monde de la 3D où il contribue au projet Babylon.js, à l’initiative de mes collègues David Catuhe (@deltakosh), David Rousset (@davrous), Pierre Lagarde (@pierlag) et Michel Rousseau (@rousseau_michel). Il a ainsi pu créer Community Play 3D, ce qui lui a donné l’occasion de rencontrer et de côtoyer d’autres personnes de DX. Il travaille ainsi aujourd’hui avec mon autre collègue Benjamin Guinebertière (@benjguin) sur le sujet du Machine Learning.
Un grand merci à Julien pour cette contribution ;-)
Je vous souhaite une bonne lecture de son billet.
:-) Benjamin
________________________________________
Introduction
Rappelez-vous, Azure Machine Learning permet d’exécuter des scripts Python et utilise le back-end Anaconda 2.1. Cet article montre comment prédire le prix d’un appartement en fonction d’une surface inconnue. Prédiction en utilisant Azure Machine Learning avec Python pour les deux phases, apprentissage et prédiction, en utilisant la librairie “scikit-learn” disponible dans le back-end Anaconda 2.1. De plus, comment rendre ces deux phases automatiques et utilisables en production seulement avec Python et Azure Machine Learning.
Azure Machine Learning
Azure Machine Learning, ou Azure ML , est un service Azurede Microsoftqui nous permet d’accéder au monde du Machine Learning. C’est un service basé sur le Cloud dans Azure qui permet la création de systèmes puissants et automatiques d’analyse prédictive avec des possibilités de déploiement rapide. Azure ML propose un studio en ligne (Machine Learning Studio) pour s’entraîner et expérimenter :)
Note : Quelques références
Rappels sur le Machine Learning Rappels sur Azure ML
Screenshot d’un modèle d’exemple dans le studio Azure ML
Le screenshot ci-dessus présente l’interface du studio avec un exemple fourni par défaut. Nous y trouvons un graphe dans lequel nous pouvons ajouter des éléments paramétrables et ainsi créer nos propres expérimentations ML.
Dans les éléments qui sont disponibles, il y en a un particulier qui attire notre attention. Il s’agit de l’élément “Execute Python Script” qui nous permet d’exécuter nos propres scripts Python pour ajouter une couche de personnalisation et tout ça dans le Cloud !
Note : Azure ML permet également d’exécuter des scripts R.
Plus d’informations sur les langages R et Python. Utilisation de R dans Azure ML.
Python et Machine Learning
Plusieurs librairies pour Machine Learning sont disponibles dans l’écosystème Python. On peut trouver PyBrain, MlPy mais aussi Scikit-learn.
Scikit-learnou Sklearn est très réputé surtout pour être simple, puissant et fait pour opérer avec les librairies NumPyet SciPytrès utilisées et connues de la communauté Python. De ce fait, il permet d’interagir avec “Matplotlib” qui est une librairie Python pour la visualisation de données ( plotting).
Azure ML & Python
Azure ML permet d’exécuter des scripts Python et met à disposition des librairies préalablement installées. Dans ces librairies on peut trouver :
- NumPy : librairie pour les calculs scientifiques
- Pandas: librairie d’analyse et de structure de données
- Scikit-learn
- Liste des librairies installées
Le but est de pouvoir pousser notre expérimentation ML en utilisant Sklearn et ainsi prédire nos résultats.
L’avantage d’utiliser Azure ML réside dans la puissance de calcul et la possibilité de déployer facilement et rapidement des Web Services. Ainsi, nous sommes capables de mettre rapidement à disposition des applications un modèle prédictif testable. Pour tester, nous disposons d’exemples en C#, R et même Python.
Cas d’étude
En reprenant l’exemple “immo ”du cours MVA disponible ici, le but est de le reproduire en utilisant Sklearn.
Dans ce cours MVA, nous cherchons à prédire un prix pour une surface d’appartement donnée. Nous distinguons la phase d’entraînement et la phase de prédiction. La phase d’entraînement se fait grâce aux outils déjà présents dans Azure ML et un fichier CSV contenant les données de référence (surface et prix).
Dans notre cas d’étude, les données sont écrites dans une base de données Azure SQL. Notre expérimentation doit se connecter à la base de données pour récupérer les données de référence, lancer la phase d’entraînement puis prédire un prix pour une surface donnée via un Web Service.
De plus, nous voulons que notre expérimentation d’entraînement puisse ré-apprendre avec de nouvelles données supplémentaires écrites dans la base de données et nous voulons pouvoir re-déclencher la phase d’entraînement grâce à un Web Service. Pour plus d’optimisation, nous voulons enregistrer les modèles de prédiction issus de la phase d’entraînement et n’utiliser que le meilleur modèle dans la phase de prédiction.
Où récupérer les données immo
Les données de référence sont disponibles sur le cours MVA sous forme de fichier CSV. De plus, je vous invite à suivre ce tutoriel.
Expérimentation d’entraînement
Ici, l’expérimentation d’entraînement est un Web Service et se décompose en plusieurs parties :
- Lire les données depuis la base de données.
- Exécuter un script Python avec Sklearn qui prend en entrée les données issues de la base de données.
- Ecrire le modèle de prédiction et le coefficient d’estimation issus du script Python dans une autre table de la base de données.
Expérimentation de prédiction
L’expérimentation de prédiction est un Web Service aussi et se décompose de la façon suivante :
- Lecture des données en sortie de l’expérimentation d’entraînement.
- Exécuter un script Python avec Sklearn qui prend en entrée depuis le Web Service une surface donnée et qui va prédire son prix associé.
Création de l’expérimentation d’entraînement
Lire dans la base de données Azure SQL
Les données de référence sont écrites dans la table immo de la base de données.
Pour lire les données de la table immo dans la base de données, nous ajoutons un élément de la liste dans le graphe appelé Reader.
Le Reader permet de lire et transformer les données issues d’une base de données en un dataset par une simple requête SQL.
Ajout d’un reader
Après avoir rempli les informations de connexion et la requête SQL, nous pouvons tester la connexion et la requête en cliquant sur “Run”.
Pour visualiser le dataset en sortie, il nous suffit de faire un clic droit sur le connecteur puis “Visualize”.
Ajouter un script Python
Tout comme le Reader, il nous suffit de glisser/déposer un élément de la liste dans le graphe.
La fonction azureml_main est la fonction exécutée par Azure ML lors de l’exécution du script. Les arguments dataframe1 et dataframe2 de la fonction correspondent aux deux datasets en entrée du script (input1 et input2) et peuvent être vides.
dataframe1 et dataframe2 sont des instances DataFrame de pandas et nous pouvons y accéder comme un dictionnaire classique :
surface = dataframe1 [ "surface "]
prix = dataframe1 [ "prix "]
OU
import pandas as pd
surface = pd.DataFrame ( dataframe1, columns= [ "surface" ])
prix = pd.DataFrame ( dataframe1, columns= [ "prix" ])
Entraînement avec Sklearn et régression linéaire
Les deux principes clés de Sklearn sont “fit” et “predict”.
- “fit” permet d’ajuster la fonction de prédiction en prenant deux paramètres : les données de référence et les résultats associés. Ici les données de référence sont les surfaces et les résultats sont les prix.
- “predict” permet de prédire un résultat en prenant en entrée une donnée de référence non connue, donc une surface.
Fit avec Sklearn et immo
Il s’agit ici d’importer Sklearn et d’ajuster la fonction de prédiction avec surface en fonction de prix grâce un modèle de régression linéaire pour l’exemple.
from sklearn import linear_model
lr = linear_model.LinearRegression ()
import pandas as pd
surface = pd.DataFrame ( dataframe1, columns= [ "surface" ])
prix = pd.DataFrame ( dataframe1, columns= [ "prix" ])
# Ajuster le modèle
lr.fit ( surface , prix )
# print le résulat de la prédiction pour une surface de 100m2
print( lr.predict ( 100 ))
Pour récupérer le coefficient estimé, autrement dit la précision de la prédiction, il nous suffit d’accéder à la propriété “coef_”. Cette valeur nous sert à déterminer le meilleur modèle issu de la phase d’entraînement.
#Estimated coefficient, contenu dans [0, 1000]
coef = lr.coef_
Enregistrer le modèle en sortie du script
Dans notre expérimentation, nous voulons enregistrer en sortie du script le résultat de la phase d’adaptation. Pour cela, il suffit simplement de sérializer l’objet “lr” et d’écrire par la suite le résultat de la sérialization dans une nouvelle table immo_model dans la base de données Azure SQL.
#dump de l’objet "lr" avec pickle
import pickle
result = pickle.dumps ( lr )
#print le résultat du dump
print( result )
Définir le dataset en sortie du script Python
Pour envoyer un dataset en sortie d’un script Python, il s’agit d’utiliser pandas. La fonction azureml_main retourne un dataset de type pandas.DataFrame de la manière suivante :
import pandas as pd
ret = pd.DataFrame ([ result ], columns= [ "result" ])
ret [ "coef" ] = pd.DataFrame ( lr.coef_, columns= [ "coef" ])
return ret,
Pour visualiser le résultat en sortie du script, il nous suffit de faire un clic droit sur le connecteur et cliquer sur “Visualize”.
Script complet
def azureml_main ( dataframe1 = None, dataframe2 = None):
from sklearn import linear_model
import pandas as pd
import pickle
surface = pd.DataFrame ( dataframe1, columns= [ "surface" ])
prix = pd.DataFrame ( dataframe1, columns= [ "prix" ])
lr = linear_model.LinearRegression ()
lr.fit ( surface , prix )
result = pickle.dumps ( lr )
ret = pd.DataFrame ([ result ], columns= [ "result" ])
ret [ "coef" ] = pd.DataFrame ( lr.coef_, columns= [ "coef" ])
return ret,
Ecrire la sortie dans la base de données Azure SQL
Dans l’expérimentation de prédiction, la méthode est de récupérer le résultat du dump de “lr” puis de le reconstruire pour récupérer l’intégralité de notre objet. Pour le récupérer il s’agit d’enregistrer le résultat dans la base de données, dans la table immo_model.
Pour écrire dans la base de données, il nous suffit de glisser/déposer un élément de type “Writer” et de remplir les informations liées à la connexion vers la base de données.
Création de l’expérimentation de prédiction
L’expérimentation de prédiction est sensiblement la même que celle d’entraînement.
Le Reader récupère la ligne qui a le meilleur coefficient estimé dans la table immo_model. Le script Python reconstruit l’objet “lr” grâce à Pickle, prend en entrée une surface inconnue (Enter Data) et inscrit le résultat de la prédiction en sortie (le prix prédit).
Le script Python aura en input1 la surface à prédire et en input2 le résultat le plus récent de la partie entraînement lu depuis la base de données. Pour définir la structure de données en input1, il s’agit de définir Enter Data comme étant au format CSV.
Note : Enter Data peut contenir une valeur (ici 25) qui sera utilisée pour les tests avec “Run”
Recharger l’objet “lr” et prédiction
Pour récupérer l’objet “lr” il s’agit de désérializer l’objet avec pickle.loads(string) .
import pickle
lr = pickle.loads ( dataframe2 [ "lr "][ 0 ])
Une fois l’objet désérializé, on peut accéder à ses méthodes.
import pandas as pd
#Transforme la surface donnée en dataset
given_surface = pd.DataFrame ( dataframe1, columns= [ "surface "])
#Prédire le prix en fonction de la surface donnée
prediction = lr.predict ( given_surface )
lr.predict renvoie un tableau de résultats et prend en entrée un tableau de données. Une fois la prédiction faite, il nous suffit de retourner le résultat en sortie du script.
import pandas as pd
ret = pd.DataFrame ( prediction, columns= [ "result" ])
return ret,
Script complet
def azureml_main ( dataframe1 = None, dataframe2 = None):
import pickle
import pandas as pd
lr = pickle.loads ( dataframe2 [ "lr "][ 0 ])
given_surface = pd.DataFrame ( dataframe1, columns= [ "surface "])
prediction = lr.predict ( given_surface )
ret = pd.DataFrame ( prediction, columns= [ "result" ])
return ret,
Tester la prédiction avec un Web Service
Créer un Web Service ici permet à un client d’accéder à l’expérimentation de prédiction et prédire un prix en fournissant une surface inconnue.
Pour ajouter un Web Service à l’expérimentation, il s’agit d’ajouter les deux éléments “Input” et “Output” de la catégorie Web Service. Dans notre cas, l’Input est connectée à input1 sur le script Python et l’Output à la sortie du script Python. L’Input remplacera dans ce cas-ci l’élément Enter Data et l’Output renverra le dataset en sortie du script Python.
Note : L’élément Enter Data définit le format des données à fournir pour l’Input du Web Service. Il est donc nécessaire de le laisser dans l’expérimentation.
Une fois le couple Input/Output connecté, il nous suffit de cliquer sur “Publish Web Service”.
Une fois le Web Service créé, toutes les informations de connexion nous sont fournies. Pour tester le Web Service et prédire un prix, cliquer sur “Test”.
Le résultat suivant montre la prédiction pour 25 m2 qui est quasi égale à la valeur de référence dans la base de données.
Appel du Web Service côté client
Les appels du Web Service peuvent se faire via C# , R et Python. La documentation est accessible en cliquant sur le lien “REQUEST/RESPONSE”. La documentation fournit l’URL vers le Web Service et un exemple de code pour les trois langages.
Lien vers le script
Le processus suivit par le script Python est le suivant :
- Définir le format JSON pour la requête (data)
- Envoyer la requête en fournissant l’API Key et l’URL du Web Service
- Récupérer la réponse et la désézialiser
- Récupérer les informations sur la prédiction en parcourant l’objet JSON renvoyé par le Web Service.
Gestion du meilleur modèle de prédiction
Afin de récupérer le meilleur modèle de prédiction, nous choisissons arbitrairement de n’utiliser que le dernier modèle ayant un coefficient estimé supérieur ou égal à 0.8. Afin d’identifier facilement le dernier modèle utilisable dans la base de données, nous ajoutons un flag “flag_use” dans la table immo_model.
De ce fait, la requête SQL de l’élément Reader dans l’expérimentation d’entraînement
SELECT TOP 1 lr
FROM immo_model as IM
ORDER BY IM.coef DESC
devient
SELECT TOP 1 lr
FROM immo_model as IM
WHERE IM.flag_use = 1
Après cette modification, chaque modèle de prédiction ajouté dans la base de données doit être vérifié. C’est-à-dire :
- Si le coefficient d’estimation >= 0.8, alors ajouter le modèle avec “flag_use = 1” et modifier les autres modèles avec “flag_use = 0”.
- Si le coefficient d’estimation < 0.8, alors ajouter le modèle avec “flag_use = 0”
Création du Web Service de la partie entraînement
Le processus de ré-apprentissage transforme l’expérimentation d’entraînement en un Web Service. On situe l’Input et l’Output au niveau du script Python.
Une fois la partie Web Service mise en place, l’élément Writer est grisé et ne sera jamais exécuté si le ré-apprentissage se fait par un appel au Web Service.
Note: Le Writer est exécuté si l’apprentissage est déclenché depuis le studio.
Pour re-déclencher l’apprentissage, il s’agit ici d’utiliser un script Python côté client qui récupère le dump de “lr” et qui écrit le résultat dans la base de données grâce à PyODBC.
Installer PyODBC et requêter la base de données Azure SQL
pip install pyodbc
Pour se connecter à la base de données avec PyODBC, nous devons fournir une chaîne de connexion (connection string) qui est la suivante :
connection = pyodbc . connect ( """DRIVER={SQL Server};
SERVER=server_adress;
DATABASE=database_name;
UID=username;
PWD=password """)
Le processus
Le processus décrit trois étapes :
- (1) déclencher l’expérimentation d’entraînement
- (2) récupérer le dump de “lr” et son coefficient estimé qui lui est associé
- (3) écrire le dump de “lr” (toujours sous forme d’une chaîne de caractères), le coefficient et le flag d’utilisation dans la base de données avec PyODBC
Ecriture avec PyODBC
Déroulement de l’écriture dans la base de données :
- Connexion à la base de données (pyodbc.connect)
- Création d’un curseur pour requêter la base de données (cursor)
- Vérifier le coefficient d’estimation du nouveau modèle de prédiction. Si >= 0.8 alors modifier (UPDATE) tous les modèles existants avec “flag_use = 0”
- Exécution d’une requête INSERT INTO avec “lr”, “coef” et “flag_use” en paramètres
- commit () pour informer le serveur de ne pas annuler les requêtes
import pyodbc
def write_to_database ( result ):
connection = pyodbc . connect (""" DRIVER={SQL Server};<br> SERVER=server_adress;<br> DATABASE=database_name;<br> UID=username;<br> PWD=password """)
cursor = connection.cursor ()
val =result [ "Results" ][ "learn_output" ][ "value" ][ "Values" ][ 0 ]
lr = val [ 0 ]
coef = float( val [ 1 ])
flag_use = True if ( coef >= 0.8 ) else False
if flag_use :
cursor.execute ( "UPDATE immo_model SET flag_use = 0;" )
cursor.execute (" INSERT INTO immo_model VALUES(?, ?, ?); "<br> , lr, coef, flag_use )
cursor.commit ()
Définir l’expérimentation d’entraînement comme étant un Web Service
Pour transformer l’expérimentation d’entraînement en Web Service, l’astuce tient à définir l’Input comme étant vide et donc ajouter un élément “Enter Data” sans données particulières (cf. capture d’écran ci-dessous).
Le JSON du script Python côté client définira donc la colonne “None” mais avec une valeur nulle.
Le JSON devient le suivant :
data = {
"Inputs ": {
"learn_input ": {
"ColumnNames": [ "None "],
"Values ": [ [ ""], ]
},<br> },
"GlobalParameters ": {<br> }
}
Script Python complet (lien vers le script)
Requête :
Ecriture dans la base de données :
Optimiser l’entraînement : créer un WebJob
L’utilisation des WebJobs dans Azure est très simple. Une fois notre Web App créée dans Azure, il suffit d’ajouter un package sous forme d’un fichier zip contenant notre fichier Python à exécuter dans la liste des WebJobs.
Créer un WebJob ici nous permet d’automatiser la phase d’apprentissage. Par exemple, si la base de données est constamment mise à jour, nous pouvons ajouter un WebJob qui sera exécuté toutes les heures afin d’améliorer le modèle de prédiction.
Note: Ajouter des librairies compilées ( .pyd ) au WebJob nécessite que ces librairies soient compilées dans leur version 32 bits.
PyODBC n’est pas disponible par défaut dans l’environnement présent sur Azure. C’est pourquoi nous devons ajouter le fichier “ pyodbc.pyd ” à la racine du dossier contenant notre script Python à exécuter. Lien vers la librairie PyODBC Python 3.4 version 32 bits .
Ajouter un WebJob qui s’exécutera de façon récurrente :
Configurer le WebJob afin qu’il s’exécute toutes les heures à partir de maintenant :
Conclusion
Nous avons vu dans cet article comment créer les deux phases, d’entraînement et de prédiction, en utilisant la librairie scikit-learn dans des script Pythons personnalisés.
De plus, ce cas d’étude montre un cas concret d’utilisation de Azure Machine Learning ne serait-ce que par la rapidité de développement et la mise en production rapide des Web Services.
Comments
- Anonymous
October 01, 2015
Merci, juste une question Comment peut-on intégrer des librairies comme from geopy.geocoders import Nominatim dans un script Python dans une boite AML ?