# Construire une application web pour utiliser un modèle de machine learning Dans cette leçon, vous allez entraîner un modèle de machine learning sur un ensemble de données hors du commun : _les observations d'OVNI au cours du siècle dernier_, provenant de la base de données de NUFORC. Vous apprendrez : - Comment "pickle" un modèle entraîné - Comment utiliser ce modèle dans une application Flask Nous continuerons à utiliser des notebooks pour nettoyer les données et entraîner notre modèle, mais vous pouvez aller plus loin en explorant l'utilisation d'un modèle "dans la nature", pour ainsi dire : dans une application web. Pour ce faire, vous devez construire une application web en utilisant Flask. ## [Quiz avant la leçon](https://ff-quizzes.netlify.app/en/ml/) ## Construire une application Il existe plusieurs façons de créer des applications web pour consommer des modèles de machine learning. Votre architecture web peut influencer la manière dont votre modèle est entraîné. Imaginez que vous travaillez dans une entreprise où le groupe de data science a entraîné un modèle qu'il souhaite que vous utilisiez dans une application. ### Points à considérer Il y a de nombreuses questions à se poser : - **Est-ce une application web ou une application mobile ?** Si vous construisez une application mobile ou devez utiliser le modèle dans un contexte IoT, vous pourriez utiliser [TensorFlow Lite](https://www.tensorflow.org/lite/) et intégrer le modèle dans une application Android ou iOS. - **Où le modèle sera-t-il hébergé ?** Dans le cloud ou localement ? - **Support hors ligne.** L'application doit-elle fonctionner hors ligne ? - **Quelle technologie a été utilisée pour entraîner le modèle ?** La technologie choisie peut influencer les outils que vous devez utiliser. - **Utilisation de TensorFlow.** Si vous entraînez un modèle avec TensorFlow, par exemple, cet écosystème permet de convertir un modèle TensorFlow pour une utilisation dans une application web via [TensorFlow.js](https://www.tensorflow.org/js/). - **Utilisation de PyTorch.** Si vous construisez un modèle avec une bibliothèque comme [PyTorch](https://pytorch.org/), vous avez la possibilité de l'exporter au format [ONNX](https://onnx.ai/) (Open Neural Network Exchange) pour une utilisation dans des applications web JavaScript qui peuvent utiliser le [Onnx Runtime](https://www.onnxruntime.ai/). Cette option sera explorée dans une future leçon pour un modèle entraîné avec Scikit-learn. - **Utilisation de Lobe.ai ou Azure Custom Vision.** Si vous utilisez un système ML SaaS (Software as a Service) tel que [Lobe.ai](https://lobe.ai/) ou [Azure Custom Vision](https://azure.microsoft.com/services/cognitive-services/custom-vision-service/?WT.mc_id=academic-77952-leestott) pour entraîner un modèle, ce type de logiciel offre des moyens d'exporter le modèle pour de nombreuses plateformes, y compris la création d'une API sur mesure à interroger dans le cloud par votre application en ligne. Vous avez également la possibilité de construire une application web Flask complète qui pourrait entraîner le modèle directement dans un navigateur web. Cela peut également être fait en utilisant TensorFlow.js dans un contexte JavaScript. Pour nos besoins, puisque nous avons travaillé avec des notebooks basés sur Python, explorons les étapes nécessaires pour exporter un modèle entraîné depuis un notebook vers un format lisible par une application web construite en Python. ## Outils Pour cette tâche, vous avez besoin de deux outils : Flask et Pickle, tous deux fonctionnant sur Python. ✅ Qu'est-ce que [Flask](https://palletsprojects.com/p/flask/) ? Décrit comme un "micro-framework" par ses créateurs, Flask fournit les fonctionnalités de base des frameworks web en utilisant Python et un moteur de templates pour construire des pages web. Consultez [ce module d'apprentissage](https://docs.microsoft.com/learn/modules/python-flask-build-ai-web-app?WT.mc_id=academic-77952-leestott) pour vous entraîner à construire avec Flask. ✅ Qu'est-ce que [Pickle](https://docs.python.org/3/library/pickle.html) ? Pickle 🥒 est un module Python qui sérialise et désérialise une structure d'objet Python. Lorsque vous "pickle" un modèle, vous sérialisez ou aplatissez sa structure pour une utilisation sur le web. Attention : pickle n'est pas intrinsèquement sécurisé, soyez prudent si vous êtes invité à "un-pickle" un fichier. Un fichier picklé a l'extension `.pkl`. ## Exercice - nettoyer vos données Dans cette leçon, vous utiliserez des données provenant de 80 000 observations d'OVNI, collectées par [NUFORC](https://nuforc.org) (The National UFO Reporting Center). Ces données contiennent des descriptions intéressantes d'observations d'OVNI, par exemple : - **Description longue.** "Un homme émerge d'un faisceau de lumière qui éclaire un champ herbeux la nuit et court vers le parking de Texas Instruments". - **Description courte.** "les lumières nous ont poursuivis". Le fichier [ufos.csv](../../../../3-Web-App/1-Web-App/data/ufos.csv) inclut des colonnes sur la `ville`, l'`état` et le `pays` où l'observation a eu lieu, la `forme` de l'objet et ses `latitude` et `longitude`. Dans le [notebook](../../../../3-Web-App/1-Web-App/notebook.ipynb) inclus dans cette leçon : 1. Importez `pandas`, `matplotlib` et `numpy` comme vous l'avez fait dans les leçons précédentes et importez le fichier ufos. Vous pouvez jeter un œil à un échantillon de l'ensemble de données : ```python import pandas as pd import numpy as np ufos = pd.read_csv('./data/ufos.csv') ufos.head() ``` 1. Convertissez les données ufos en un petit dataframe avec des titres actualisés. Vérifiez les valeurs uniques dans le champ `Country`. ```python ufos = pd.DataFrame({'Seconds': ufos['duration (seconds)'], 'Country': ufos['country'],'Latitude': ufos['latitude'],'Longitude': ufos['longitude']}) ufos.Country.unique() ``` 1. Réduisez maintenant la quantité de données à traiter en supprimant les valeurs nulles et en n'important que les observations entre 1 et 60 secondes : ```python ufos.dropna(inplace=True) ufos = ufos[(ufos['Seconds'] >= 1) & (ufos['Seconds'] <= 60)] ufos.info() ``` 1. Importez la bibliothèque `LabelEncoder` de Scikit-learn pour convertir les valeurs textuelles des pays en nombres : ✅ LabelEncoder encode les données par ordre alphabétique ```python from sklearn.preprocessing import LabelEncoder ufos['Country'] = LabelEncoder().fit_transform(ufos['Country']) ufos.head() ``` Vos données devraient ressembler à ceci : ```output Seconds Country Latitude Longitude 2 20.0 3 53.200000 -2.916667 3 20.0 4 28.978333 -96.645833 14 30.0 4 35.823889 -80.253611 23 60.0 4 45.582778 -122.352222 24 3.0 3 51.783333 -0.783333 ``` ## Exercice - construire votre modèle Vous pouvez maintenant préparer l'entraînement du modèle en divisant les données en groupes d'entraînement et de test. 1. Sélectionnez les trois caractéristiques sur lesquelles vous souhaitez entraîner votre modèle comme vecteur X, et le vecteur y sera le `Country`. Vous voulez pouvoir entrer `Seconds`, `Latitude` et `Longitude` et obtenir un identifiant de pays en retour. ```python from sklearn.model_selection import train_test_split Selected_features = ['Seconds','Latitude','Longitude'] X = ufos[Selected_features] y = ufos['Country'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) ``` 1. Entraînez votre modèle en utilisant la régression logistique : ```python from sklearn.metrics import accuracy_score, classification_report from sklearn.linear_model import LogisticRegression model = LogisticRegression() model.fit(X_train, y_train) predictions = model.predict(X_test) print(classification_report(y_test, predictions)) print('Predicted labels: ', predictions) print('Accuracy: ', accuracy_score(y_test, predictions)) ``` La précision n'est pas mauvaise **(environ 95%)**, ce qui n'est pas surprenant, car `Country` et `Latitude/Longitude` sont corrélés. Le modèle que vous avez créé n'est pas très révolutionnaire, car vous devriez être capable d'inférer un `Country` à partir de sa `Latitude` et `Longitude`, mais c'est un bon exercice pour essayer d'entraîner à partir de données brutes que vous avez nettoyées, exportées, puis utiliser ce modèle dans une application web. ## Exercice - "pickle" votre modèle Il est maintenant temps de _pickle_ votre modèle ! Vous pouvez le faire en quelques lignes de code. Une fois qu'il est _picklé_, chargez votre modèle picklé et testez-le avec un tableau de données contenant des valeurs pour les secondes, la latitude et la longitude. ```python import pickle model_filename = 'ufo-model.pkl' pickle.dump(model, open(model_filename,'wb')) model = pickle.load(open('ufo-model.pkl','rb')) print(model.predict([[50,44,-12]])) ``` Le modèle retourne **'3'**, qui est le code pays pour le Royaume-Uni. Incroyable ! 👽 ## Exercice - construire une application Flask Vous pouvez maintenant construire une application Flask pour appeler votre modèle et retourner des résultats similaires, mais de manière plus visuellement agréable. 1. Commencez par créer un dossier appelé **web-app** à côté du fichier _notebook.ipynb_ où se trouve votre fichier _ufo-model.pkl_. 1. Dans ce dossier, créez trois autres dossiers : **static**, avec un dossier **css** à l'intérieur, et **templates**. Vous devriez maintenant avoir les fichiers et répertoires suivants : ```output web-app/ static/ css/ templates/ notebook.ipynb ufo-model.pkl ``` ✅ Consultez le dossier solution pour voir l'application terminée 1. Le premier fichier à créer dans le dossier _web-app_ est le fichier **requirements.txt**. Comme _package.json_ dans une application JavaScript, ce fichier liste les dépendances nécessaires à l'application. Dans **requirements.txt**, ajoutez les lignes : ```text scikit-learn pandas numpy flask ``` 1. Exécutez maintenant ce fichier en naviguant vers _web-app_ : ```bash cd web-app ``` 1. Dans votre terminal, tapez `pip install` pour installer les bibliothèques listées dans _requirements.txt_ : ```bash pip install -r requirements.txt ``` 1. Vous êtes maintenant prêt à créer trois autres fichiers pour terminer l'application : 1. Créez **app.py** à la racine. 2. Créez **index.html** dans le répertoire _templates_. 3. Créez **styles.css** dans le répertoire _static/css_. 1. Complétez le fichier _styles.css_ avec quelques styles : ```css body { width: 100%; height: 100%; font-family: 'Helvetica'; background: black; color: #fff; text-align: center; letter-spacing: 1.4px; font-size: 30px; } input { min-width: 150px; } .grid { width: 300px; border: 1px solid #2d2d2d; display: grid; justify-content: center; margin: 20px auto; } .box { color: #fff; background: #2d2d2d; padding: 12px; display: inline-block; } ``` 1. Ensuite, complétez le fichier _index.html_ : ```html 🛸 UFO Appearance Prediction! 👽

According to the number of seconds, latitude and longitude, which country is likely to have reported seeing a UFO?

{{ prediction_text }}

``` Regardez le templating dans ce fichier. Notez la syntaxe "mustache" autour des variables qui seront fournies par l'application, comme le texte de prédiction : `{{}}`. Il y a aussi un formulaire qui envoie une prédiction à la route `/predict`. Enfin, vous êtes prêt à construire le fichier Python qui pilote la consommation du modèle et l'affichage des prédictions : 1. Dans `app.py`, ajoutez : ```python import numpy as np from flask import Flask, request, render_template import pickle app = Flask(__name__) model = pickle.load(open("./ufo-model.pkl", "rb")) @app.route("/") def home(): return render_template("index.html") @app.route("/predict", methods=["POST"]) def predict(): int_features = [int(x) for x in request.form.values()] final_features = [np.array(int_features)] prediction = model.predict(final_features) output = prediction[0] countries = ["Australia", "Canada", "Germany", "UK", "US"] return render_template( "index.html", prediction_text="Likely country: {}".format(countries[output]) ) if __name__ == "__main__": app.run(debug=True) ``` > 💡 Astuce : lorsque vous ajoutez [`debug=True`](https://www.askpython.com/python-modules/flask/flask-debug-mode) en exécutant l'application web avec Flask, tout changement que vous apportez à votre application sera immédiatement reflété sans avoir besoin de redémarrer le serveur. Attention ! Ne pas activer ce mode dans une application en production. Si vous exécutez `python app.py` ou `python3 app.py`, votre serveur web démarre localement, et vous pouvez remplir un court formulaire pour obtenir une réponse à votre question brûlante sur les lieux où les OVNI ont été observés ! Avant de faire cela, examinez les parties de `app.py` : 1. Tout d'abord, les dépendances sont chargées et l'application démarre. 1. Ensuite, le modèle est importé. 1. Enfin, index.html est rendu sur la route d'accueil. Sur la route `/predict`, plusieurs choses se produisent lorsque le formulaire est envoyé : 1. Les variables du formulaire sont collectées et converties en un tableau numpy. Elles sont ensuite envoyées au modèle et une prédiction est retournée. 2. Les pays que nous voulons afficher sont re-rendus sous forme de texte lisible à partir de leur code pays prédit, et cette valeur est renvoyée à index.html pour être rendue dans le template. Utiliser un modèle de cette manière, avec Flask et un modèle picklé, est relativement simple. La partie la plus difficile est de comprendre la forme des données qui doivent être envoyées au modèle pour obtenir une prédiction. Tout dépend de la manière dont le modèle a été entraîné. Celui-ci nécessite trois points de données pour obtenir une prédiction. Dans un cadre professionnel, vous pouvez voir à quel point une bonne communication est nécessaire entre les personnes qui entraînent le modèle et celles qui le consomment dans une application web ou mobile. Dans notre cas, c'est une seule personne : vous ! --- ## 🚀 Défi Au lieu de travailler dans un notebook et d'importer le modèle dans l'application Flask, vous pourriez entraîner le modèle directement dans l'application Flask ! Essayez de convertir votre code Python dans le notebook, peut-être après avoir nettoyé vos données, pour entraîner le modèle directement dans l'application sur une route appelée `train`. Quels sont les avantages et les inconvénients de cette méthode ? ## [Quiz après la leçon](https://ff-quizzes.netlify.app/en/ml/) ## Révision et auto-apprentissage Il existe de nombreuses façons de construire une application web pour consommer des modèles de machine learning. Faites une liste des façons dont vous pourriez utiliser JavaScript ou Python pour construire une application web exploitant le machine learning. Pensez à l'architecture : le modèle doit-il rester dans l'application ou vivre dans le cloud ? Si c'est le cas, comment y accéder ? Dessinez un modèle architectural pour une solution web appliquée au machine learning. ## Devoir [Essayez un modèle différent](assignment.md) --- **Avertissement** : Ce document a été traduit à l'aide du service de traduction automatique [Co-op Translator](https://github.com/Azure/co-op-translator). Bien que nous nous efforcions d'assurer l'exactitude, veuillez noter que les traductions automatisées peuvent contenir des erreurs ou des inexactitudes. Le document original dans sa langue d'origine doit être considéré comme la source faisant autorité. Pour des informations critiques, il est recommandé de recourir à une traduction professionnelle réalisée par un humain. Nous déclinons toute responsabilité en cas de malentendus ou d'interprétations erronées résultant de l'utilisation de cette traduction.