Proširenje Spark-a uz MLflow

Pozdrav, stanovnici Khabrovsk. Kao što smo već pisali, ovaj mjesec OTUS pokreće dva tečaja strojnog učenja odjednom, naime baza и Napredna. U tom smislu nastavljamo dijeliti korisne materijale.

Svrha ovog članka je govoriti o našem prvom iskustvu korištenja MLflow.

Počinjemo s pregledom MLflow sa svog poslužitelja za praćenje i zabilježi sve iteracije studije. Zatim ćemo podijeliti naše iskustvo povezivanja Sparka s MLflowom pomoću UDF-a.

Kontekst

Mi smo u Alfa zdravlje Koristimo strojno učenje i umjetnu inteligenciju kako bismo osnažili ljude da preuzmu kontrolu nad svojim zdravljem i dobrobiti. Zato su modeli strojnog učenja u srcu proizvoda znanosti o podacima koje razvijamo i zato nas je privukao MLflow, platforma otvorenog koda koja pokriva sve aspekte životnog ciklusa strojnog učenja.

MLflow

Glavni cilj MLflowa je osigurati dodatni sloj povrh strojnog učenja koji bi omogućio znanstvenicima da rade s gotovo svakom bibliotekom strojnog učenja (h2o, keras, mleap, pitorka, sklearn и tensorflow), dižući svoj rad na višu razinu.

MLflow nudi tri komponente:

  • Praćenje – snimanje i zahtjevi za eksperimente: kod, podaci, konfiguracija i rezultati. Praćenje procesa izrade modela vrlo je važno.
  • Projekti – Format pakiranja za rad na bilo kojoj platformi (npr. SageMaker)
  • Modeli – zajednički format za podnošenje modela različitim alatima za implementaciju.

MLflow (u alfa verziji u vrijeme pisanja) platforma je otvorenog koda koja vam omogućuje upravljanje životnim ciklusom strojnog učenja, uključujući eksperimentiranje, ponovnu upotrebu i implementaciju.

Postavljanje MLflow

Da biste koristili MLflow, morate prvo postaviti cijelo Python okruženje, za ovo ćemo koristiti PyEnv (da biste instalirali Python na Mac, pogledajte ovdje). Na taj način možemo stvoriti virtualno okruženje u koje ćemo instalirati sve biblioteke potrebne za njegovo pokretanje.

```
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
```

Instalirajmo potrebne biblioteke.

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

Napomena: koristimo PyArrow za pokretanje modela kao što je UDF. Trebalo je popraviti verzije PyArrowa i Numpyja jer su potonje bile u sukobu jedna s drugom.

Pokrenite korisničko sučelje za praćenje

MLflow Tracking nam omogućuje da bilježimo i postavljamo upite eksperimentima pomoću Pythona i OSTALO API. Osim toga, možete odrediti gdje pohraniti artefakte modela (localhost, Amazon S3, Azure Blob pohrana, Google Cloud Storage ili SFTP poslužitelj). Budući da koristimo AWS u Alpha Healthu, naše skladište artefakata bit će S3.

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

MLflow preporučuje korištenje trajne pohrane datoteka. Pohrana datoteka mjesto je na kojem će poslužitelj pohraniti metapodatke o izvođenju i eksperimentu. Prilikom pokretanja poslužitelja, provjerite pokazuje li na trajnu pohranu datoteka. Ovdje ćemo jednostavno koristiti za eksperiment /tmp.

Imajte na umu da ako želimo koristiti mlflow poslužitelj za pokretanje starih eksperimenata, oni moraju biti prisutni u pohrani datoteka. No, i bez toga bismo ih mogli koristiti u UDF-u, jer nam treba samo put do modela.

Napomena: imajte na umu da korisničko sučelje za praćenje i klijent modela moraju imati pristup lokaciji artefakta. To jest, bez obzira na činjenicu da se korisničko sučelje za praćenje nalazi u EC2 instanci, kada se MLflow izvodi lokalno, stroj mora imati izravan pristup S3 za pisanje modela artefakata.

Proširenje Spark-a uz MLflow
UI za praćenje pohranjuje artefakte u S3 kantu

Trčanje modela

Čim se poslužitelj za praćenje pokrene, možete započeti s obukom modela.

Kao primjer koristit ćemo modifikaciju vina iz primjera MLflow u Sklearn.

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

Kao što smo već spomenuli, MLflow vam omogućuje bilježenje parametara modela, metrike i artefakata kako biste mogli pratiti kako se razvijaju tijekom iteracija. Ova je značajka iznimno korisna jer na taj način možemo reproducirati najbolji model kontaktiranjem poslužitelja za praćenje ili razumijevanjem koji je kod izvršio potrebnu iteraciju pomoću git hash zapisa obveza.

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

Proširenje Spark-a uz MLflow
Vinske iteracije

Serverski dio za model

Poslužitelj za praćenje MLflow, pokrenut pomoću naredbe "mlflow server", ima REST API za praćenje pokreta i pisanje podataka u lokalni datotečni sustav. Možete navesti adresu poslužitelja za praćenje pomoću varijable okruženja “MLFLOW_TRACKING_URI” i API za praćenje MLflow automatski će kontaktirati poslužitelj za praćenje na ovoj adresi kako bi stvorio/primio informacije o pokretanju, metriku dnevnika itd.

Izvor: Dokumenti// Pokretanje poslužitelja za praćenje

Da bismo modelu pružili poslužitelj, potreban nam je aktivan poslužitelj za praćenje (pogledajte sučelje za pokretanje) i Run ID modela.

Proširenje Spark-a uz MLflow
Pokreni 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

Za posluživanje modela pomoću funkcije posluživanja MLflow, trebat ćemo pristup korisničkom sučelju za praćenje kako bismo primali informacije o modelu jednostavnim navođenjem --run_id.

Nakon što model kontaktira poslužitelj za praćenje, možemo dobiti novu krajnju točku modela.

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

Modeli za trčanje iz Spark

Unatoč činjenici da je poslužitelj za praćenje dovoljno moćan da opslužuje modele u stvarnom vremenu, obučite ih i koristite funkcionalnost poslužitelja (izvor: mlflow // dokumenti // modeli # lokalno), korištenje Spark-a (batch ili streaming) još je moćnije rješenje zbog njegove distribucije.

Zamislite da ste jednostavno odradili obuku izvan mreže i zatim primijenili izlazni model na sve svoje podatke. Ovdje Spark i MLflow blistaju.

Instalirajte PySpark + Jupyter + Spark

Izvor: Započnite s PySparkom - Jupyter

Da bismo pokazali kako primjenjujemo MLflow modele na Spark podatkovne okvire, moramo postaviti Jupyter prijenosna računala da rade zajedno s PySparkom.

Započnite instaliranjem najnovije stabilne verzije 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̀

Instalirajte PySpark i Jupyter u virtualnom okruženju:

pip install pyspark jupyter

Postavite varijable okruženja:

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"

Utvrdivši notebook-dir, svoje bilježnice možemo pohraniti u željenu mapu.

Pokretanje Jupytera iz PySparka

Budući da smo uspjeli konfigurirati Jupiter kao PySpark upravljački program, sada možemo pokrenuti Jupyter prijenosno računalo u kontekstu PySparka.

(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

Proširenje Spark-a uz MLflow

Kao što je gore spomenuto, MLflow pruža značajku za bilježenje artefakata modela u S3. Čim imamo odabrani model u našim rukama, imamo priliku uvesti ga kao UDF pomoću modula 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)

Proširenje Spark-a uz MLflow
PySpark - Iznos predviđanja kvalitete vina

Do ove točke smo razgovarali o tome kako koristiti PySpark s MLflowom, izvodeći predviđanja kvalitete vina na cijelom skupu podataka o vinu. Ali što ako trebate koristiti Python MLflow module iz Scala Spark?

Testirali smo i ovo razdvajanjem Spark konteksta između Scale i Pythona. Odnosno, registrirali smo MLflow UDF u Pythonu, a koristili ga iz Scale (da, možda nije najbolje rješenje, ali ono što imamo).

Scala Spark + MLflow

Za ovaj primjer ćemo dodati Toree Kernel u postojeći Jupiter.

Instalirajte 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
```

Kao što možete vidjeti iz priložene bilježnice, UDF dijele Spark i PySpark. Nadamo se da će ovaj dio biti koristan onima koji vole Scalu i žele primijeniti modele strojnog učenja u proizvodnji.

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

Sljedeći koraci

Iako je MLflow u vrijeme pisanja ovog teksta u Alpha verziji, izgleda prilično obećavajuće. Samo mogućnost pokretanja višestrukih okvira strojnog učenja i njihove upotrebe s jedne krajnje točke podiže sustave preporuka na višu razinu.

Osim toga, MLflow zbližava podatkovne inženjere i stručnjake za podatkovnu znanost, postavljajući zajednički sloj između njih.

Nakon ovog istraživanja MLflowa, uvjereni smo da ćemo krenuti naprijed i koristiti ga za naše Spark cjevovode i sustave preporuka.

Bilo bi lijepo sinkronizirati pohranu datoteka s bazom podataka umjesto datotečnim sustavom. To bi nam trebalo dati više krajnjih točaka koje mogu koristiti istu pohranu datoteka. Na primjer, koristite više instanci Odmah и Atina s istim Glue metastoreom.

Ukratko, želio bih zahvaliti zajednici MLFlow što je naš rad s podacima učinio zanimljivijim.

Ako se igrate s MLflowom, nemojte se ustručavati pisati nam i reći nam kako ga koristite, a još više ako ga koristite u proizvodnji.

Saznajte više o tečajevima:
Strojno učenje. Osnovni tečaj
Strojno učenje. Napredni tečaj

Čitaj više:

Izvor: www.habr.com

Dodajte komentar