Le vrai Père Noël utilisera-t-il notre modèle pour la sélection de cadeaux ?
En 2022, nous à iterative.ai fait beaucoup de belles choses. L’un d’eux étant la sortie de MLEM
– un outil open source pour le déploiement de modèles, au cas où vous l’auriez manqué. Et vous l’avez probablement manqué, notre rapport sur les compteurs de téléchargement. Voici un lien vers l’application.
OK, donc cette année de MLEMming se terminera par la mise en place d’un arbre de Noël. Et par « configurer un sapin de Noël », j’entends bien sûr déployer un modèle d’apprentissage automatique dans le cloud. Il semble raisonnable que ce modèle soit un DecisionTreeClassifier
qui classera les noms en classes « gentils » et « coquins ».
Pour former notre arbre, nous avons besoin de quelques données de formation, de préférence un échantillon de la liste réelle du Père Noël. Une recherche rapide sur Google a révélé qu’il n’y avait pas d’échantillons accessibles au public, cependant, un site Web officiel du Père Noël fournit une page pour vérifier votre nom par rapport à cette liste. Alors grattons-en le diable.
Une inspection du réseau et un peu d’analyse DOM plus tard, nous avons cette fonction :
import bs4 as bs4
import requestsdef is_nice(name: str):
resp = requests.post(" data={"KidName": name, "KidName_submit": "yes"})
resp.raise_for_status()
soup = bs4.BeautifulSoup(resp.text, "html.parser")
div = soup.find("div", attrs={"class": "SantaListKidName"})
if div is None:
return None
img = div.find("img", attrs={"alt": "[Naughty or Nice List]"})
if img is None:
return None
img_src = img.attrs["src"]
return img_src.endswith("NiceCheck.png")
Maintenant, nous n’avons besoin que d’une liste de noms à vérifier. N’allons pas loin et utilisons le premier lien d’une recherche Google de « noms les plus populaires csv »
Prenons les 1000 meilleurs noms et vérifions qui est gentil.
import json
import os.path
from collections import Counterimport pandas as pd
from tqdm import tqdm
def scrape_niceness(names, path):
if os.path.exists(path):
with open(path, "r") as f:
data = json.load(f)
else:
data = {}
for name in tqdm(names):
if name in data:
continue
nice = is_nice(name)
data[name] = nice
with open(path, "w") as f:
json.dump(data, f)
def get_names(count=1000):
data = pd.read_csv("baby-names.csv")
counter = Counter(data.name)
return list(dict(counter.most_common(count)).keys())
names = get_names()
scrape_niceness(names, "nice.json")
En attendant les données, préparons notre code d’entraînement. Ça devrait être assez simple :
from sklearn.tree import DecisionTreeClassifierwith open("nice.json", "r") as f:
data = json.load(f)
christmas_tree = DecisionTreeClassifier()
christmas_tree.fit(list(data.keys()), list(data.values()))
Immédiatement nous rencontrons un problème : apparemment les noms ne sont pas des flottants valides !
ValueError: could not convert string to float: 'Jesse'
Eh bien, expliquons à notre machine qu’il s’agit en fait de flottants dotés de la puissance des plongements. Ajoutons une simple étape de prétraitement à notre pipeline de Noël qui transformera les noms en un état caché de ALBERT modèle chargé à partir de.
from transformers import AlbertTokenizer, AlbertModeltokenizer = AlbertTokenizer.from_pretrained('albert-base-v2')
model = AlbertModel.from_pretrained("albert-base-v2")
def pre_process(value: str):
encoded_input = tokenizer(value, return_tensors='pt')
output = model(**encoded_input)
return output.last_hidden_state.squeeze(0)[-1].detach().numpy().reshape(1, 768)
Pendant que nous faisions cela, nous avons été bloqués par le site Web du Père Noël. Il semble que le Père Noël sait ce qu’est un À partir de l’attaque est. Mais cela n’a pas d’importance puisque tous les noms que nous avions vérifiés étaient gentils (même si l’image des noms coquins en fait existe un sur le serveur).
Ok, tout le monde est gentil, alors nous allons jeter quelques chaînes aléatoires comme exemples négatifs pour notre modèle.
Maintenant, entraînons notre arbre et sauvegardons-le avec MLEM
import string
import random
import numpy as npimport mlem
christmas_tree = DecisionTreeClassifier()
with open("nice.json", "r") as f:
data = json.load(f)
data.update(
{
"".join(
random.choice(string.ascii_lowercase)
for _ in range(random.randint(4, 7))
).capitalize(): False
for _ in range(len(data))
}
)
preprocessed = [pre_process(name) for name in tqdm(data)]
christmas_tree.fit(np.stack(preprocessed, axis=1)[0], list(data.values()))
print(christmas_tree.predict(pre_process("Mike"))) # True of course
mdl = mlem.api.save(
christmas_tree,
"christmas_tree",
preprocess=pre_process,
postprocess=post_process,
sample_data="Mike",
)
Nous avons également lancé une petite étape de post-traitement pour obtenir des réponses à partir de nombres de probabilité sans âme.
def post_process(prediction):
if len(prediction.shape) > 1:
return "Nice" if prediction[0][0] < prediction[0][1] else "Naughty"
return "Nice" if prediction[0] else "Naughty"
Enfin, nous pouvons tester le modèle localement. MLEM
nous construira automatiquement une jolie interface Streamlit, en utilisant sample_data
nous avons réussi lorsque nous avons enregistré le modèle :
$ mlem serve streamlit -m christmas_tree
Starting streamlit server...
You can now view your Streamlit app in your browser.
URL: <http://0.0.0.0:80>
Joli!
Pour le renvoyer au Père Noël, nous devons le déployer quelque part. MLEM peut déployer des modèles sur un certain nombre de plates-formes telles que Héroku, Sagemaker et Kubernetes littéralement en une seule commande.
Comme nous voulions quelque chose de spécial pour Noël, nous exporté un modèle dans un docker build
– dossier prêt avec MLEM et déployé le modèle sur voler.io avec flyctl launch
– découvrez le déploiement!
Ça y est …! Le sapin de Noël a été mis en place, alors maintenant nous pouvons tous fêter ça !
Joyeux Noël et bonnes fêtes !