Helló, Habrovčanok. Ahogy már írtuk, ebben a hónapban az OTUS két gépi tanulás tanfolyamot indít, nevezetesen és . Ennek kapcsán továbbra is megosztjuk a hasznos anyagokat.
Ennek a cikknek a célja, hogy bemutassa az első tapasztalatainkat a .
témában. Kezdjük a nyomkövető szerverével, és feljegyezzük a kutatás minden iterációját. Ezután megosztjuk a Spark és az MLflow UDF-vel való összekapcsolásának tapasztalatait. Alpha Health
Környezet
1cloud Az MLflow fő célja, hogy egy további réteget biztosítson a gépi tanulás fölött, amely lehetővé teszi az adat tudósok számára, hogy szinte bármely gépi tanulási könyvtárral dolgozzanak (
MLflow
h2o, , , , és Az MLflow három komponenst biztosít:
Nyomkövetés
- – kísérletek rögzítése és lekérdezése: kód, adatok, konfiguráció és eredmények. Nagyon fontos nyomon követni a modell létrehozásának folyamatát. – Csomagolási forma bármely platformon való futtatáshoz (például,
- Projects SageMaker )
- – közös formátum a modellek különböző telepítési eszközökbe való küldésére. Az MLflow (a cikk írásakor alpha verzióban) egy nyílt forráskódú platform, amely lehetővé teszi a gépi tanulás életciklusának kezelését, beleértve a kísérleteket, újrahasználást és telepítést.
Az MLflow beállítása
Az MLflow használatához először be kell állítani az egész Python környezetet, ehhez a
PyEnv ). Így létrehozhatunk egy virtuális környezetet, ahová telepítjük az összes szükséges könyvtárat. ``` pyenv install 3.7.0 pyenv global 3.7.0 # Használja a Python 3.7-et mkvirtualenv mlflow # Hozzon létre egy virtuális környezetet Python 3.7-tel workon mlflow ```
Telepítjük a szükséges könyvtárakat.``` pip install mlflow==0.7.0 Cython==0.29 numpy==1.14.5 pandas==0.23.4 pyarrow==0.11.0 ```
Megjegyzés: a PyArrow-t használjuk olyan modellek futtatására, mint az UDF. A PyArrow és a Numpy verzióját meg kellett javítani, mivel az utolsó verziók konfliktusba kerültek egymással.Megjegyzés: PyArrow-t használunk olyan modellek, mint az UDF futtatására. A PyArrow és a Numpy verziókat ki kellett javítani, mivel a legújabb verziók konfliktusban voltak egymással.
Indítjuk a Tracking UI-t
Az MLflow Tracking lehetővé teszi számunkra, hogy naplózni és lekérdezni tudjuk a kísérleteket Python segítségével, és API. Ezen kívül meghatározhatjuk, hol tároljuk a modell artefaktumokat (localhost, , , vagy ). Mivel az Alpha Health-nél AWS-t használunk, az artefaktumok tárolására az S3-at választjuk.
# Running a Tracking Server
mlflow server
--file-store /tmp/mlflow/fileStore
--default-artifact-root s3://<bucket>/mlflow/artifacts/
--host localhost
--port 5000 Az MLflow javasolja a tartós fájltároló használatát. A fájltároló az a hely, ahol a szerver tárolni fogja a futások és kísérletek metaadatait. A szerver indításakor győződjön meg róla, hogy egy tartós fájltárolóra mutat. Itt a kísérlethez egyszerűen használni fogjuk /tmp.
Ne feledje, hogy ha az mlflow szervert szeretnénk használni régi kísérletek futtatásához, akkor azoknak jelen kell lenniük a fájltárolóban. Azonban enélkül is használhatjuk őket az UDF-ben, mivel csak a modellhez szükséges útvonalra van szükségünk.
Megjegyzés: Vegye figyelembe, hogy a Tracking UI-nak és a modell kliensnek hozzáféréssel kell rendelkeznie az artefaktum helyéhez. Tehát függetlenül attól, hogy a Tracking UI egy EC2 példányban található, a MLflow helyi indításakor a gépnek közvetlen hozzáféréssel kell rendelkeznie az S3-hoz, hogy az artefaktum modellek írását elvégezhesse.

A Tracking UI az artefaktumokat egy S3 vödörben tárolja
Modellek indítása
Amint a Tracking-szerver működik, elkezdhetjük a modellek tanítását.
Példaként a bor MLflow példájának módosítását fogjuk alkalmazni .
MLFLOW_TRACKING_URI=http://localhost:5000 python wine_quality.py
--alpha 0.9
--l1_ration 0.5
--wine_file ./data/winequality-red.csvAhogy már említettük, az MLflow lehetővé teszi a paraméterek, metrikák és modell artefaktumok naplózását, hogy nyomon követhessük, hogyan fejlődnek iterációk során. Ez a funkció rendkívül hasznos, mivel így képesek vagyunk reprodukálni a legjobb modellt, akár a Tracking-szerverhez fordulva, akár a git commitok logját felhasználva megérteni, hogy melyik kód hajtotta végre a szükséges iterációt.
with mlflow.start_run():
... model ...
mlflow.log_param("source", wine_path)
mlflow.log_param("alpha", alpha)
mlflow.log_param("l1_ratio", l1_ratio)
mlflow.log_metric("rmse", rmse)
mlflow.log_metric("r2", r2)
mlflow.log_metric("mae", mae)
mlflow.set_tag('domain', 'wine')
mlflow.set_tag('predict', 'quality')
mlflow.sklearn.log_model(lr, "model") 
Bor iterációk
A modell szerveroldala
A tracking server MLflow, launched using the command "mlflow server", has a REST API for tracking runs and recording data in the local file system. You can specify the address of the tracking server using the environment variable "MLFLOW_TRACKING_URI" and the MLflow tracking API will automatically connect to the tracking server at this address to create/retrieve run information, log metrics, etc.
Forrás:
To provide the model with a server, we will need a running tracking server (see the launch interface) and the model's Run ID.

Run ID
# Serve a sklearn model through 127.0.0.0:5005
MLFLOW_TRACKING_URI=http://0.0.0.0:5000 mlflow sklearn serve
--port 5005
--run_id 0f8691808e914d1087cf097a08730f17
--model-path model To serve models using the MLflow serve functionality, we need access to the Tracking UI to obtain information about the model simply by specifying --run_id.
Once the model is connected to the Tracking server, we can obtain a new endpoint for the model.
# Query Tracking Server Endpoint
curl -X POST
http://127.0.0.1:5005/invocations
-H 'Content-Type: application/json'
-d '[
{
"fixed acidity": 3.42,
"volatile acidity": 1.66,
"citric acid": 0.48,
"residual sugar": 4.2,
"chloridessssss": 0.229,
"free sulfur dsioxide": 19,
"total sulfur dioxide": 25,
"density": 1.98,
"pH": 5.33,
"sulphates": 4.39,
"alcohol": 10.8
}
]'
> {"predictions": [5.825055635303461]}Running models from Spark
Although the Tracking server is powerful enough to serve models in real-time, training, and using the serve functionality (source: ), applying Spark (batch or streaming) is an even more powerful solution due to its distributed nature.
Imagine that you just performed training offline and then applied the resulting model to all your data. This is where Spark and MLflow can shine.
Installing PySpark + Jupyter + Spark
Forrás:
To show how we apply MLflow models to Spark dataframes, we need to set up collaboration between Jupyter notebooks and PySpark.
Start by installing the latest stable version :
cd ~/Downloads/
tar -xzf spark-2.4.3-bin-hadoop2.7.tgz
mv ~/Downloads/spark-2.4.3-bin-hadoop2.7 ~/\nln -s ~/spark-2.4.3-bin-hadoop2.7 ~/spark`Install PySpark and Jupyter in a virtual environment:
pip install pyspark jupyterSet environment variables:
export SPARK_HOME=~/spark
export PATH=$SPARK_HOME/bin:$PATH
export PYSPARK_DRIVER_PYTHON=jupyter
export PYSPARK_DRIVER_PYTHON_OPTS="notebook --notebook-dir=${HOME}/Projects/notebooks" Defining notebook-dir, we will be able to store our notebooks in the desired folder.
Launching Jupyter from PySpark
Since we managed to set up Jupyter as the PySpark driver, we can now launch Jupyter notebook in the context of PySpark.
(mlflow) afranzi:~$ pyspark
[I 19:05:01.572 NotebookApp] sparkmagic kiterjesztés engedélyezve!
[I 19:05:01.573 NotebookApp] Jegyzetfüzetek kiszolgálása a helyi könyvtárból: /Users/afranzi/Projects/notebooks
[I 19:05:01.573 NotebookApp] A Jupyter Jegyzetfüzet a következő címen fut:
[I 19:05:01.573 NotebookApp] http://localhost:8888/?token=c06252daa6a12cfdd33c1d2e96c8d3b19d90e9f6fc171745
[I 19:05:01.573 NotebookApp] Használja a Control-C billentyűkombinációt a szerver leállításához és az összes kernel leállításához (két alkalommal a megerősítés kihagyásához).
[C 19:05:01.574 NotebookApp]
Másolja/beilleszti ezt az URL-t a böngészőjébe, amikor először csatlakozik,
hogy bejelentkezzen egy tokennel:
http://localhost:8888/?token=c06252daa6a12cfdd33c1d2e96c8d3b19d90e9f6fc171745 
Ahogy azt már említettük, az MLflow lehetőséget biztosít a modell artefaktumainak S3-ba való naplózására. Amint megvan a kiválasztott modell, lehetőségünk nyílik arra, hogy importáljuk azt UDF-ként a következő modul segítségével: mlflow.pyfunc.
import mlflow.pyfunc
model_path = 's3:///mlflow/artifacts/1/0f8691808e914d1087cf097a08730f17/artifacts/model'
wine_path = '/Users/afranzi/Projects/data/winequality-red.csv'
wine_udf = mlflow.pyfunc.spark_udf(spark, model_path)
df = spark.read.format("csv").option("header", "true").option('delimiter', ';').load(wine_path)
columns = [ "fixed acidity", "volatile acidity", "citric acid",
"residual sugar", "chlorides", "free sulfur dioxide",
"total sulfur dioxide", "density", "pH",
"sulphates", "alcohol"
]
df.withColumn('prediction', wine_udf(*columns)).show(100, False) 
PySpark – Bor-minőség előrejelzések kimenete
Eddig arról beszéltünk, hogyan tudjuk használni a PySparkot az MLflow-val, míg az összes boradat készletén a minőség előrejelzése zajlik. De mi a teendő, ha a Python MLflow modulokat Scala Spark-ból szeretnénk használni?
Teszteltük ezt, megosztva a Spark kontextust Scala és Python között. Tehát regisztráltuk az MLflow UDF-et Pythonban, és használtuk Scala-ból (igen, nem a legjobb megoldás, de ez van).
Scala Spark + MLflow
Ehhez a példához hozzáadjuk a a meglévő Jupiterhez.
Spark + Toree + Jupyter telepítése
pip install toree
jupyter toree install --spark_home=${SPARK_HOME} --sys-prefix
jupyter kernelspec list
```
```
Elérhető kernellel:
apache_toree_scala /Users/afranzi/.virtualenvs/mlflow/share/jupyter/kernels/apache_toree_scala
python3 /Users/afranzi/.virtualenvs/mlflow/share/jupyter/kernels/python3
```Ahogy az a csatolt notebookból látszik, az UDF-et együtt használják Spark és PySpark. Reméljük, hogy ez a rész hasznos lesz azok számára, akik szeretik a Scalát és szeretnék telepíteni a gépi tanulási modelleket a gyakorlatban.
import org.apache.spark.sql.functions.col
import org.apache.spark.sql.types.StructType
import org.apache.spark.sql.{Column, DataFrame}
import scala.util.matching.Regex
val FirstAtRe: Regex = "^_".r
val AliasRe: Regex = "[\s_.:@]+".r
def getFieldAlias(field_name: String): String = {
FirstAtRe.replaceAllIn(AliasRe.replaceAllIn(field_name, "_"), "")
}
def selectFieldsNormalized(columns: List[String])(df: DataFrame): DataFrame = {
val fieldsToSelect: List[Column] = columns.map(field =>
col(field).as(getFieldAlias(field))
)
df.select(fieldsToSelect: _*)
}
def normalizeSchema(df: DataFrame): DataFrame = {
val schema = df.columns.toList
df.transform(selectFieldsNormalized(schema))
}
FirstAtRe = ^_
AliasRe = [s_.:@]+
getFieldAlias: (field_name: String)String
selectFieldsNormalized: (columns: List[String])(df: org.apache.spark.sql.DataFrame)org.apache.spark.sql.DataFrame
normalizeSchema: (df: org.apache.spark.sql.DataFrame)org.apache.spark.sql.DataFrame
Out[1]:
[s_.:@]+
In [2]:
val winePath = "~\/Research\/mlflow-workshop\/examples\/wine_quality\/data\/winequality-red.csv"
val modelPath = "\/tmp\/mlflow\/artifactStore\/0\/96cba14c6e4b452e937eb5072467bf79\/artifacts\/model"
winePath = ~\/Research\/mlflow-workshop\/examples\/wine_quality\/data\/winequality-red.csv
modelPath = \/tmp\/mlflow\/artifactStore\/0\/96cba14c6e4b452e937eb5072467bf79\/artifacts\/model
Out[2]:
\/tmp\/mlflow\/artifactStore\/0\/96cba14c6e4b452e937eb5072467bf79\/artifacts\/model
In [3]:
val df = spark.read
.format("csv")
.option("header", "true")
.option("delimiter", ";")
.load(winePath)
.transform(normalizeSchema)
df = [fixed_acidity: string, volatile_acidity: string ... 10 more fields]
Out[3]:
[fixed_acidity: string, volatile_acidity: string ... 10 more fields]
In [4]:
%%PySpark
import mlflow
from mlflow import pyfunc
model_path = "\/tmp\/mlflow\/artifactStore\/0\/96cba14c6e4b452e937eb5072467bf79\/artifacts\/model"
wine_quality_udf = mlflow.pyfunc.spark_udf(spark, model_path)
spark.udf.register("wineQuality", wine_quality_udf)
Out[4]:
<function spark_udf..predict at 0x1116a98c8>
In [6]:
df.createOrReplaceTempView("wines")
In [10]:
%%SQL
SELECT
quality,
wineQuality(
fixed_acidity,
volatile_acidity,
citric_acid,
residual_sugar,
chlorides,
free_sulfur_dioxide,
total_sulfur_dioxide,
density,
pH,
sulphates,
alcohol
) AS prediction
FROM wines
LIMIT 10
Out[10]:
+-------+------------------+
|quality| prediction|
+-------+------------------+
| 5| 5.576883967129615|
| 5| 5.50664776916154|
| 5| 5.525504822954496|
| 6| 5.504311247097457|
| 5| 5.576883967129615|
| 5|5.5556903912725755|
| 5| 5.467882654744997|
| 7| 5.710602976324739|
| 7| 5.657319539336507|
| 5| 5.345098606538708|
+-------+------------------+
In [17]:
spark.catalog.listFunctions.filter('name like "%wineQuality%").show(20, false)
+-----------+--------+-----------+---------+-----------+
|name |database|description|className|isTemporary|
+-----------+--------+-----------+---------+-----------+
|wineQuality|null |null |null |true |
+-----------+--------+-----------+---------+-----------+
Következő lépések
Bár a cikk írásának idején az MLflow alfa verzióban van, ígéretesnek tűnik. Az egyetlen lehetőség, hogy több gépi tanulási keretrendszert futtathatunk és használhatunk egyetlen végpontból, új szintre emeli az ajánlási rendszereket.
Továbbá, az MLflow közel hozza a Data mérnököket és az adatelemző szakembereket, létrehozva köztük egy közös réteget.
Az MLflow ezen kutatása után biztosak vagyunk benne, hogy tovább fogunk lépni és használni fogjuk azt a Spark pipelinjeinkben és ajánlórendszerekben.
Jó lenne, ha az adattárhelyzést az adatbázissal szinkronizálnánk a fájlrendszer helyett. Így több végpontot kellene kapnunk, amelyek ugyanazt az adattárhelyzést használják. Például több példány használata. és ugyanazzal a Glue metastore-val.
Összefoglalva, szeretnénk köszönetet mondani az MLFlow közösségnek, hogy érdekesebbé teszik a munkánkat az adatokkal.
Ha játszol az MLflow-val, ne habozz írni nekünk és mesélni, hogyan használod, és különösen, ha éles környezetben is használod.
Tudd meg többet a kurzusokról:
Tovább olvasva:
Forrás: habr.com
