Spark išplėtimas naudojant MLflow

Sveiki, chabrovskiečiai. Kaip jau rašėme, šį mėnesį OTUS vienu metu pradeda du mašininio mokymosi kursus, būtent bazė и pažengęs. Šiuo atžvilgiu mes ir toliau dalinamės naudinga medžiaga.

Šio straipsnio tikslas – pakalbėti apie mūsų pirmąją naudojimo patirtį MLflow.

Pradėsime peržiūrą MLflow iš savo stebėjimo serverio ir registruokite visas tyrimo iteracijas. Tada pasidalinsime savo patirtimi apie Spark sujungimą su MLflow naudojant UDF.

Kontekstas

Mes esame Alfa sveikata Mes naudojame mašininį mokymąsi ir dirbtinį intelektą, kad įgalintume žmones rūpintis savo sveikata ir gerove. Štai kodėl mašininio mokymosi modeliai yra mūsų kuriamų duomenų mokslo produktų pagrindas, todėl mus patraukė MLflow – atvirojo kodo platforma, apimanti visus mašininio mokymosi ciklo aspektus.

MLflow

Pagrindinis MLflow tikslas yra suteikti papildomą mašininio mokymosi sluoksnį, kuris leistų duomenų mokslininkams dirbti su beveik bet kokia mašininio mokymosi biblioteka (H2o, sunku, mleap, Pitorchas, sklearn и tensorflow), pakelia savo darbą į kitą lygį.

MLflow turi tris komponentus:

  • Sekimo – eksperimentų įrašymas ir užklausos: kodas, duomenys, konfigūracija ir rezultatai. Labai svarbu stebėti modelio kūrimo procesą.
  • Projektai – Pakuotės formatas, skirtas veikti bet kurioje platformoje (pvz. „SageMaker“)
  • modeliai – bendras modelių pateikimo įvairiems diegimo įrankiams formatas.

MLflow (rašymo metu alfa versija) yra atvirojo kodo platforma, leidžianti valdyti mašininio mokymosi gyvavimo ciklą, įskaitant eksperimentavimą, pakartotinį naudojimą ir diegimą.

MLflow nustatymas

Norėdami naudoti MLflow, pirmiausia turite nustatyti visą Python aplinką, kurią naudosime PyEnv (Norėdami įdiegti „Python“ „Mac“, patikrinkite čia). Tokiu būdu galime sukurti virtualią aplinką, kurioje įdiegsime visas jai paleisti reikalingas bibliotekas.

```
pyenv install 3.7.0
pyenv global 3.7.0 # Use Python 3.7
mkvirtualenv mlflow # Create a Virtual Env with Python 3.7
workon mlflow
```

Įdiegsime reikiamas bibliotekas.

```
pip install mlflow==0.7.0 
            Cython==0.29  
            numpy==1.14.5 
            pandas==0.23.4 
            pyarrow==0.11.0
```

Pastaba: „PyArrow“ naudojame tokiems modeliams kaip UDF paleisti. Reikėjo pataisyti PyArrow ir Numpy versijas, nes pastarosios versijos prieštarauja viena kitai.

Paleiskite stebėjimo vartotojo sąsają

MLflow stebėjimas leidžia mums registruoti eksperimentus ir pateikti užklausas naudojant Python ir POILSIO API. Be to, galite nustatyti, kur laikyti modelio artefaktus (localhost, "Amazon" S3, „Azure Blob“ saugykla, "Google" Debesis Sandėliavimo arba SFTP serveris). Kadangi „Alpha Health“ naudojame AWS, mūsų artefaktų saugykla bus S3.

# Running a Tracking Server
mlflow server 
    --file-store /tmp/mlflow/fileStore 
    --default-artifact-root s3://<bucket>/mlflow/artifacts/ 
    --host localhost
    --port 5000

MLflow rekomenduoja naudoti nuolatinę failų saugyklą. Failų saugykla yra vieta, kur serveris saugos paleidimo ir eksperimento metaduomenis. Pradėdami serverį įsitikinkite, kad jis nurodo nuolatinę failų saugyklą. Čia mes tiesiog naudosime eksperimentui /tmp.

Atminkite, kad jei norime naudoti mlflow serverį seniems eksperimentams vykdyti, jie turi būti failų saugykloje. Tačiau net ir be to galėtume juos naudoti UDF, nes mums reikia tik kelio į modelį.

Pastaba: atminkite, kad stebėjimo vartotojo sąsaja ir modelio klientas turi turėti prieigą prie artefakto vietos. Tai yra, nepaisant to, kad stebėjimo vartotojo sąsaja yra EC2 egzemplioriuje, kai MLflow veikia vietoje, įrenginys turi turėti tiesioginę prieigą prie S3, kad galėtų rašyti artefaktų modelius.

Spark išplėtimas naudojant MLflow
Stebėjimo vartotojo sąsaja saugo artefaktus S3 segmente

Bėgimo modeliai

Kai tik paleidžiamas stebėjimo serveris, galite pradėti mokyti modelius.

Kaip pavyzdį naudosime vyno modifikaciją iš MLflow pavyzdžio Sklearn.

MLFLOW_TRACKING_URI=http://localhost:5000 python wine_quality.py 
  --alpha 0.9
  --l1_ration 0.5
  --wine_file ./data/winequality-red.csv

Kaip jau aptarėme, MLflow leidžia registruoti modelio parametrus, metriką ir artefaktus, kad galėtumėte stebėti, kaip jie kinta iteracijų metu. Ši funkcija yra labai naudinga, nes tokiu būdu galime atkurti geriausią modelį susisiekę su stebėjimo serveriu arba suprasdami, kuris kodas atliko reikiamą iteraciją, naudodamas įsipareigojimų git maišos žurnalus.

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")

Spark išplėtimas naudojant MLflow
Vyno iteracijos

Modelio serverio dalis

MLflow stebėjimo serveris, paleistas naudojant komandą „mlflow server“, turi REST API, skirtą sekti paleidimus ir įrašyti duomenis į vietinę failų sistemą. Galite nurodyti stebėjimo serverio adresą naudodami aplinkos kintamąjį „MLFLOW_TRACKING_URI“, o MLflow stebėjimo API automatiškai susisieks su stebėjimo serveriu šiuo adresu, kad sukurtų / gautų paleidimo informaciją, žurnalo metriką ir kt.

Šaltinis: Dokumentai// Stebėjimo serverio paleidimas

Norint pateikti modelį su serveriu, mums reikia veikiančio stebėjimo serverio (žr. paleidimo sąsają) ir modelio vykdymo ID.

Spark išplėtimas naudojant MLflow
Vykdyti 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

Norėdami aptarnauti modelius naudojant MLflow aptarnavimo funkciją, mums reikės prieigos prie stebėjimo vartotojo sąsajos, kad gautume informaciją apie modelį tiesiog nurodant --run_id.

Kai modelis susisieks su stebėjimo serveriu, galime gauti naują modelio galinį tašką.

# 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]}

Bėgimo modeliai iš Spark

Nepaisant to, kad stebėjimo serveris yra pakankamai galingas, kad galėtų aptarnauti modelius realiu laiku, mokyti juos ir naudotis serverio funkcijomis (šaltinis: mlflow // dokumentai // modeliai # vietiniai), „Spark“ naudojimas (paketinis arba srautinis perdavimas) yra dar galingesnis sprendimas dėl platinimo.

Įsivaizduokite, kad tiesiog atlikote mokymą neprisijungę ir pritaikėte išvesties modelį visiems savo duomenims. Čia šviečia Spark ir MLflow.

Įdiekite PySpark + Jupyter + Spark

Šaltinis: Pradėkite PySpark – Jupyter

Norėdami parodyti, kaip taikome MLflow modelius „Spark“ duomenų rėmeliams, turime nustatyti „Jupyter“ bloknotus, kad jie veiktų kartu su „PySpark“.

Pradėkite įdiegdami naujausią stabilią versiją Apache Spark:

cd ~/Downloads/
tar -xzf spark-2.4.3-bin-hadoop2.7.tgz
mv ~/Downloads/spark-2.4.3-bin-hadoop2.7 ~/
ln -s ~/spark-2.4.3-bin-hadoop2.7 ~/spark̀

Įdiekite PySpark ir Jupyter virtualioje aplinkoje:

pip install pyspark jupyter

Nustatykite aplinkos kintamuosius:

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"

Nusprendęs notebook-dir, savo užrašų knygeles galime laikyti norimame aplanke.

„Jupyter“ paleidimas iš „PySpark“.

Kadangi sugebėjome sukonfigūruoti Jupiterį kaip PySpark tvarkyklę, dabar galime paleisti Jupyter nešiojamąjį kompiuterį PySpark kontekste.

(mlflow) afranzi:~$ pyspark
[I 19:05:01.572 NotebookApp] sparkmagic extension enabled!
[I 19:05:01.573 NotebookApp] Serving notebooks from local directory: /Users/afranzi/Projects/notebooks
[I 19:05:01.573 NotebookApp] The Jupyter Notebook is running at:
[I 19:05:01.573 NotebookApp] http://localhost:8888/?token=c06252daa6a12cfdd33c1d2e96c8d3b19d90e9f6fc171745
[I 19:05:01.573 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 19:05:01.574 NotebookApp]

    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://localhost:8888/?token=c06252daa6a12cfdd33c1d2e96c8d3b19d90e9f6fc171745

Spark išplėtimas naudojant MLflow

Kaip minėta aukščiau, MLflow suteikia S3 modelio artefaktų registravimo funkciją. Kai tik turime pasirinktą modelį savo rankose, turime galimybę jį importuoti kaip UDF naudodami modulį mlflow.pyfunc.

import mlflow.pyfunc

model_path = 's3://<bucket>/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)

Spark išplėtimas naudojant MLflow
PySpark – vyno kokybės prognozių pateikimas

Iki šiol kalbėjome apie tai, kaip naudoti PySpark su MLflow, vyno kokybės prognozėmis visame vyno duomenų rinkinyje. O kas, jei jums reikia naudoti Python MLflow modulius iš Scala Spark?

Tai taip pat išbandėme padaliję „Spark“ kontekstą tarp „Scala“ ir „Python“. Tai yra, mes užregistravome MLflow UDF Python ir panaudojome jį iš Scala (taip, galbūt ne geriausias sprendimas, bet tai, ką turime).

Scala Spark + MLflow

Prie šio pavyzdžio pridėsime Toree branduolys į esamą Jupiterį.

Įdiekite Spark + Toree + Jupyter

pip install toree
jupyter toree install --spark_home=${SPARK_HOME} --sys-prefix
jupyter kernelspec list
```
```
Available kernels:
  apache_toree_scala    /Users/afranzi/.virtualenvs/mlflow/share/jupyter/kernels/apache_toree_scala
  python3               /Users/afranzi/.virtualenvs/mlflow/share/jupyter/kernels/python3
```

Kaip matote iš pridedamo bloknoto, UDF dalijasi „Spark“ ir „PySpark“. Tikimės, kad ši dalis bus naudinga tiems, kurie mėgsta „Scala“ ir nori gamyboje įdiegti mašininio mokymosi modelius.

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.<locals>.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       |
+-----------+--------+-----------+---------+-----------+

Kitas žingsnis

Nors rašymo metu MLflow yra Alpha versijoje, ji atrodo gana daug žadanti. Vien galimybė paleisti kelias mašininio mokymosi sistemas ir jas naudoti iš vieno galutinio taško pakelia rekomendacijų sistemas į kitą lygį.

Be to, MLflow suartina duomenų inžinierius ir duomenų mokslo specialistus, tarp jų sudarydama bendrą sluoksnį.

Po šio MLflow tyrimo esame įsitikinę, kad judėsime į priekį ir naudosime jį savo Spark vamzdynams ir rekomendacijų sistemoms.

Būtų malonu sinchronizuoti failų saugyklą su duomenų baze, o ne su failų sistema. Tai turėtų suteikti mums kelis galutinius taškus, kurie gali naudoti tą pačią failų saugyklą. Pavyzdžiui, naudokite kelis atvejus Presto и Atėnė su tuo pačiu Glue metastore.

Apibendrinant, norėčiau padėkoti MLFlow bendruomenei už tai, kad mūsų darbas su duomenimis tapo įdomesnis.

Jei žaidžiate su MLflow, nedvejodami parašykite mums ir papasakokite, kaip jį naudojate, o juo labiau, jei naudojate gamyboje.

Sužinokite daugiau apie kursus:
Mašininis mokymasis. Bazinis kursas
Mašininis mokymasis. Išplėstinis kursas

Skaityti daugiau:

Šaltinis: www.habr.com

Добавить комментарий