Streamlit https://www.streamlit.io/

Streamlit : Donnez une vie à vos modèles de ML

Streamlit est un framework open-source Python spécialement conçu pour les ingénieurs en machine learning et les Data scientists.  Ce framework permet de créer des applications web qui pourront intégrer aisément des modèles de machine learning et des outils de visualisation de données.

1. Streamlit : Les bases

Contrairement aux autres framework python (Dash, …) pour créer des applications autour de la données, Streamlit permet de créer de belles applications web sans écrire du code HTML. Ce framework permet aussi d’avoir des applications performantes grâce à la mise en cache via une annotation. Bon … place au concret :

L’installation

L’installation de Streamilt se fait facilement via l’installateur de paquet python pip.

pip install streamlit

De plus , il est possible d’exécuter une application demo avec la commande suivante

streamlit hello

Si l’installation s’est bien déroulée, vous devriez avoir une nouvelle fenêtre de votre navigateur qui devra se présenter comme l’image ci-dessous.

Hello Streamlit

Explorer des données avec Streamlit

Nous allons essayer de comprendre pas à pas Streamlit au travers d’un exemple concret. Pour ce faire , nous allons utiliser le jeu de données Uber Pickups in New York City qui contient des données de trajets Uber (et autres véhicules de location) dans la ville de New York.

On importe d’abord les libraires nécessaires

import streamlit as st
import pandas as pd
import numpy as np
import altair as alt
import pydeck as pdk

On ajoute un titre à notre application avec la fonction title de streamlit. Ce qui est assez sympa avec cette librairie c’est quelle supporte nativement la syntaxe markdown que nous allons utiliser pour ajouter une description.

On récupère notre jeu de données et on le charge dans l’application

DATE_TIME = "date/time"
DATA_URL = (
"http://s3-us-west-2.amazonaws.com/streamlit-demo-data/uber-raw-data-sep14.csv.gz"
)

@st.cache(persist=True)
def load_data(nrows):
    data = pd.read_csv(DATA_URL, nrows=nrows)
    lowercase = lambda x: str(x).lower()
    data.rename(lowercase, axis="columns", inplace=True)
    data[DATE_TIME] = pd.to_datetime(data[DATE_TIME])
    return data

data = load_data(500000)

On s’aperçoit qu’il y  a une annotation « @st.cache(persist=True) »  qui permet de mettre en cache et conserver sur le disque les données qui seront chargées. Cela permettra à notre application d’être assez performante après avoir été exécutée une fois.

On ajoute ensuite un slider qu’on utilisera pour choisir une heure précise de la journée qui nous permettra de visualiser les commandes Uber sur une carte.

hour = st.slider("Heure de la journée", 0, 23)

Ce qui nous permet d’avoir ce beau slider ci-dessous que nous allons utiliser comme filtre pour nos différentes visualisations.

Slider streamlit

Ensuite, nous allons utiliser la libraire pydeck afin de pouvoir visualiser les données sur une carte. On utilise alors la fonction « write() » de streamlit afin d’insérer cette carte interactive de pydeck dans notre application.

midpoint = (np.average(data["lat"]), np.average(data["lon"]))
st.write(pdk.Deck(
map_style="mapbox://styles/mapbox/light-v9",
initial_view_state={
"latitude": midpoint[0],
"longitude": midpoint[1],
"zoom": 11,
"pitch": 50,
},
layers=[
pdk.Layer(
"HexagonLayer",
data=data,
get_position=["lon", "lat"],
auto_highlight=True,
radius=100,
elevation_scale=50,
elevation_range=[0, 1000],
pickable=True,
extruded=True,
),
],
))

On obtient nos données sur une carte comme suit :

Carte streamlit

 

Une autre information qu’on pourrai avoir serai la distribution des commandes par minutes.

hist = np.histogram(filtered[DATE_TIME].dt.minute, bins=60, range=(0, 60))[0]
chart_data = pd.DataFrame({"minute": range(60), "pickups": hist})

st.altair_chart(alt.Chart(chart_data)
.mark_area(
interpolate='step-after',
).encode(
x=alt.X("minute:Q", scale=alt.Scale(nice=False)),
y=alt.Y("pickups:Q"),
tooltip=['minute', 'pickups']
), use_container_width=True)

if st.checkbox("Voir les données brutes", False):
    st.subheader("Données brutes par minute entre %i:00 et %i:00" % (hour, (hour + 1) % 24))
    st.write(data)

Le code source est disponible à cette adresse https://raw.githubusercontent.com/lilstipher/demo-uber-nyc-pickups/master/appNoML.py et vous pouvez l’exécuter directement avec la commande suivante :

pip install --upgrade streamlit
streamlit run https://raw.githubusercontent.com/lilstipher/demo-uber-nyc-pickups/master/appNoML.py

Ainsi, on a ce graphique qui nous présente la distribution des commandes par minutes dont l’intervalle d’heure dépend du slider.

altair

2. Streamlit : Insérez vos modèles de ML

Ce serait assez intéressant qu’on fasse une prédiction des commandes en fonction de l’heure de la journée et de la zone dans la ville de New York. Pour ce faire, j’ai entrainé deux modèles de machine learning. Le premier me permettra de créer d’effectuer un clustering sur les données gps afin de créer des zones dans la ville qui seront numérotée de 0 à 39. Le deuxième me permettra de prédire la demande dans une zone donnée (avec le numéro de la zone et l’heure).

Ainsi, dans streamlit on ajoute des zones de saisie pour entrer les coordonnées gps et l’heure.Pour la zone de saisie de l’heure, on utilise la fonction time_input() de streamlit. Ensuite, pour récupérer les coordonnées gps on utilise deux zones de saisie (latitude et longitude) en utilisant la fonction number_input() . Afin de s’assurer que les données gps soit fiables, on limite les intervalles de choix pour se limiter uniquement  à la ville de NYC et ses alentours.

st.subheader("Prédition de la demande")
timeOfTheDay= st.time_input("Choisir l'heure", datetime.time(8, 45,00))
st.write('Heure:', timeOfTheDay)
st.markdown("Renseignez vos coordonnées GPS")
## latitude
latitude= st.number_input("Choisir la latitude ", min_value=data['lat'].min(),max_value=data['lat'].max())
longitude= st.number_input("Choisir la longitude ", min_value=data['lon'].min(),max_value=data['lon'].max())
st.write('Vos coordonnées GPS (latitude,longitude) : ', (latitude,longitude))

Et ça donne ça

streamlit text input

On définit les fonctions qui nous permettrons de charger nos modèles et effectuer d’autres traitements et on load le modèle !

@st.cache(persist=True)
def load_models():
    model = {}
    nb_pickupsModel=''
    with open('models/kmeansNYCUber.pickle', 'rb') as file:
        model['kmeansNYCUber_model'] = pickle.load(file)

    with open('models/nb_pickupsModel.pickle', 'rb') as file:
        model['nb_pickupsModel'] = pickle.load(file)
    return model
def secondTime(t):
    seconds = (t.hour * 60 + t.minute) * 60 + t.second
    return seconds
model = load_models()

Il reste à mettre en place notre pipeline pour prédire les commandes en fonction de la position gps et de l’heure (n’oubliez pas d’importer pickle et datetime !)

gps = {'lat': [latitude], 'lon': [longitude]}
clusterNo= int(model['kmeansNYCUber_model'].predict(pd.DataFrame(data=gps)))
heureEnSec = secondTime(timeOfTheDay)

time_cluster = {'time': [heureEnSec], 'cluster': [clusterNo]}
pickups = model['nb_pickupsModel'].predict(pd.DataFrame(data=time_cluster))

st.write('La demande prédite dans cette zone à cette heure est de', int(pickups))

streamlit texte prédiction

On a donc notre application streamlit qui utilise maintenant plusieurs modèles de Machine learning !

Vous pouvez accéder au projet complet sur github !

https://github.com/lilstipher/demo-uber-nyc-pickups

Si vous rencontrez un problème avec l’utilisation de streamlit vous pouvez écrire un commentaire, je vous répondrai dans les plus bref délais !

1 réflexion sur “Streamlit : Donnez une vie à vos modèles de ML”

  1. Bonjour, j’essaie de déployer une webapp via streamlit et j’ai l’erreur ‘ValueError: signal only works in main thread of the main interpreter’
    J’ai scrappé des données via Scrapy puis j’essaie de récupérer le fichier et de les mettre sous forme de df sur mon app streamlit , quand j’exécute mon script sur vs code cela fonctionne mais pas lorsque j’essaie de déployer en local via streamlit.

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.