Spark paplaŔināŔana ar MLflow

Sveiki, Habrovskas iedzÄ«votāji. Kā jau rakstÄ«jām, Å”omēnes OTUS uzsāk uzreiz divus maŔīnmācÄ«bas kursus, proti bāze Šø uzlabotas. Å ajā sakarā mēs turpinām dalÄ«ties ar noderÄ«gu materiālu.

Šī raksta mērķis ir pastāstīt par mūsu pirmo pieredzi, izmantojot MLflow.

Mēs sāksim pārskatÄ«Å”anu MLflow no sava izsekoÅ”anas servera un reÄ£istrēt visas pētÄ«juma iterācijas. Pēc tam mēs dalÄ«simies pieredzē par Spark savienoÅ”anu ar MLflow, izmantojot UDF.

Konteksts

Mes esam ieksa Alfa veselÄ«ba Mēs izmantojam maŔīnmācÄ«Å”anos un mākslÄ«go intelektu, lai dotu cilvēkiem iespēju uzņemties atbildÄ«bu par savu veselÄ«bu un labklājÄ«bu. Tāpēc maŔīnmācÄ«Å”anās modeļi ir mÅ«su izstrādāto datu zinātnes produktu pamatā, un tāpēc mÅ«s piesaistÄ«ja MLflow ā€” atvērtā pirmkoda platforma, kas aptver visus maŔīnmācÄ«Å”anās dzÄ«ves cikla aspektus.

MLflow

MLflow galvenais mērÄ·is ir nodroÅ”ināt papildu slāni maŔīnmācÄ«bai, kas ļautu datu zinātniekiem strādāt ar gandrÄ«z jebkuru maŔīnmācÄ«Å”anās bibliotēku (h2o, keras, mleap, pitors, sklearn Šø tensora plÅ«sma), paceļot viņas darbu uz nākamo lÄ«meni.

MLflow nodroŔina trīs komponentus:

  • IzsekoÅ”ana ā€“ eksperimentu ierakstÄ«Å”ana un pieprasÄ«jumi: kods, dati, konfigurācija un rezultāti. Modeļa izveides procesa uzraudzÄ«ba ir ļoti svarÄ«ga.
  • AKTIVITĀTES ā€“ Iepakojuma formāts, kas darbojas jebkurā platformā (piem. SageMaker)
  • Modeļi ā€“ kopÄ«gs formāts modeļu iesniegÅ”anai dažādiem izvietoÅ”anas rÄ«kiem.

MLflow (rakstÄ«Å”anas laikā alfa versijā) ir atvērtā pirmkoda platforma, kas ļauj pārvaldÄ«t maŔīnmācÄ«Å”anās dzÄ«ves ciklu, tostarp eksperimentÄ“Å”anu, atkārtotu izmantoÅ”anu un izvietoÅ”anu.

MLflow iestatīŔana

Lai izmantotu MLflow, vispirms ir jāiestata visa Python vide, ko mēs izmantosim PyEnv (Lai instalētu Python operētājsistēmā Mac, pārbaudiet Å”eit). Tādā veidā mēs varam izveidot virtuālo vidi, kurā instalēsim visas tās palaiÅ”anai nepiecieÅ”amās bibliotēkas.

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

Instalēsim vajadzīgās bibliotēkas.

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

Piezīme. Mēs izmantojam PyArrow, lai palaistu tādus modeļus kā UDF. PyArrow un Numpy versijas bija jālabo, jo pēdējās versijas konfliktēja viena ar otru.

Palaidiet izsekoŔanas lietotāja saskarni

MLflow izsekoÅ”ana ļauj reÄ£istrēt eksperimentus un veikt vaicājumus, izmantojot Python un ATPÅŖTA API. Turklāt varat noteikt, kur glabāt modeļu artefaktus (localhost, Amazon S3, Azure Blob krātuve, Google Cloud Storage vai SFTP serveris). Tā kā Alpha Health izmantojam AWS, mÅ«su artefaktu krātuve bÅ«s S3.

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

MLflow iesaka izmantot pastāvÄ«gu failu krātuvi. Failu krātuve ir vieta, kur serveris glabās palaiÅ”anas un eksperimentu metadatus. Startējot serveri, pārliecinieties, vai tas norāda uz pastāvÄ«go failu krātuvi. Å eit mēs vienkārÅ”i izmantosim eksperimentu /tmp.

Atcerieties, ka, ja mēs vēlamies izmantot mlflow serveri veco eksperimentu veikÅ”anai, tiem ir jāatrodas failu krātuvē. Tomēr pat bez tā mēs varētu tos izmantot UDF, jo mums ir nepiecieÅ”ams tikai ceļŔ uz modeli.

PiezÄ«me. Ņemiet vērā, ka izsekoÅ”anas lietotāja saskarnei un modeļa klientam ir jābÅ«t piekļuvei artefakta atraÅ”anās vietai. Tas nozÄ«mē, ka neatkarÄ«gi no tā, ka izsekoÅ”anas lietotāja saskarne atrodas EC2 instancē, lokāli palaižot MLflow, iekārtai ir jābÅ«t tieÅ”ai piekļuvei S3, lai rakstÄ«tu artefaktu modeļus.

Spark paplaŔināŔana ar MLflow
IzsekoŔanas lietotāja saskarne artefaktus glabā S3 segmentā

SkrieŔanas modeļi

Tiklīdz darbojas izsekoŔanas serveris, varat sākt apmācīt modeļus.

Kā piemēru mēs izmantosim vīna modifikāciju no MLflow piemēra Sklearn.

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

Kā mēs jau apspriedām, MLflow ļauj reÄ£istrēt modeļa parametrus, metriku un artefaktus, lai varētu izsekot, kā tie attÄ«stās iterāciju laikā. Å Ä« funkcija ir ārkārtÄ«gi noderÄ«ga, jo tādā veidā mēs varam reproducēt labāko modeli, sazinoties ar izsekoÅ”anas serveri vai saprotot, kurÅ” kods veica nepiecieÅ”amo iterāciju, izmantojot git jaukÅ”anas žurnālus.

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 paplaŔināŔana ar MLflow
Vīna atkārtojumi

Servera daļa modelim

MLflow izsekoÅ”anas serverim, kas palaists, izmantojot komandu ā€œmlflow serverā€, ir REST API, lai izsekotu darbÄ«bas un ierakstÄ«tu datus vietējā failu sistēmā. Varat norādÄ«t izsekoÅ”anas servera adresi, izmantojot vides mainÄ«go ā€œMLFLOW_TRACKING_URIā€, un MLflow izsekoÅ”anas API automātiski sazināsies ar izsekoÅ”anas serveri Å”ajā adresē, lai izveidotu/saņemtu palaiÅ”anas informāciju, žurnāla metriku utt.

Avots: Dokumenti// IzsekoŔanas servera palaiŔana

Lai modelim nodroÅ”inātu ar serveri, mums ir nepiecieÅ”ams darbojoÅ”s izsekoÅ”anas serveris (skatiet palaiÅ”anas saskarni) un modeļa palaiÅ”anas ID.

Spark paplaŔināŔana ar MLflow
Palaist 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

Lai apkalpotu modeļus, izmantojot MLflow apkalpoÅ”anas funkcionalitāti, mums bÅ«s nepiecieÅ”ama piekļuve izsekoÅ”anas lietotāja saskarnei, lai saņemtu informāciju par modeli, vienkārÅ”i norādot --run_id.

Kad modelis sazinās ar izsekoÅ”anas serveri, mēs varam iegÅ«t jaunu modeļa galapunktu.

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

SkrieŔanas modeļi no Spark

Neskatoties uz to, ka izsekoÅ”anas serveris ir pietiekami jaudÄ«gs, lai apkalpotu modeļus reāllaikā, apmācÄ«tu tos un izmantotu servera funkcionalitāti (avots: mlflow // dokumenti // modeļi # lokāli), Spark izmantoÅ”ana (paketē vai straumÄ“Å”ana) ir vēl jaudÄ«gāks risinājums izplatÄ«Å”anas dēļ.

Iedomājieties, ka jÅ«s vienkārÅ”i veicāt apmācÄ«bu bezsaistē un pēc tam lietojāt izvades modeli visiem saviem datiem. Å eit spÄ«d Spark un MLflow.

Instalējiet PySpark + Jupyter + Spark

Avots: Darba sākÅ”ana PySpark ā€” Jupyter

Lai parādītu, kā mēs izmantojam MLflow modeļus Spark datu rāmjiem, mums ir jāiestata Jupyter piezīmjdatori, lai tie darbotos kopā ar PySpark.

Sāciet ar jaunākās stabilās versijas instalÄ“Å”anu 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Ģ€

Instalējiet PySpark un Jupyter virtuālajā vidē:

pip install pyspark jupyter

Iestatiet vides mainīgos:

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"

Noteicis notebook-dir, mēs varam saglabāt savas piezīmju grāmatiņas vēlamajā mapē.

Jupyter palaiŔana no PySpark

Tā kā mēs varējām konfigurēt Jupiteru kā PySpark draiveri, tagad mēs varam palaist Jupyter piezīmjdatoru PySpark kontekstā.

(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 paplaŔināŔana ar MLflow

Kā minēts iepriekÅ”, MLflow nodroÅ”ina funkciju modeļa artefaktu reÄ£istrÄ“Å”anai S3. TiklÄ«dz izvēlētais modelis ir mÅ«su rokās, mums ir iespēja to importēt kā UDF, izmantojot moduli 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 paplaŔināŔana ar MLflow
PySpark ā€” vÄ«na kvalitātes prognozes

LÄ«dz Å”im mēs esam runājuÅ”i par to, kā izmantot PySpark ar MLflow, veicot vÄ«na kvalitātes prognozes visā vÄ«na datu kopā. Bet ko darÄ«t, ja jums ir jāizmanto Python MLflow moduļi no Scala Spark?

Mēs arī to pārbaudījām, sadalot Spark kontekstu starp Scala un Python. Tas ir, mēs reģistrējām MLflow UDF programmā Python un izmantojām to no Scala (jā, iespējams, tas nav labākais risinājums, bet tas, kas mums ir).

Scala Spark + MLflow

Å im piemēram mēs pievienosim Toree kodols esoÅ”ajā Jupiterā.

Instalējiet 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
```

Kā redzat pievienotajā piezÄ«mju grāmatiņā, UDF tiek koplietots starp Spark un PySpark. Mēs ceram, ka Ŕī daļa bÅ«s noderÄ«ga tiem, kam patÄ«k Scala un kuri vēlas ražoÅ”anā izmantot maŔīnmācÄ«Å”anās modeļus.

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

Nākamās darbības

Lai gan rakstÄ«Å”anas laikā MLflow ir Alpha versijā, tas izskatās diezgan daudzsoloÅ”i. Tikai iespēja palaist vairākas maŔīnmācÄ«Å”anās ietvaras un patērēt tās no viena galapunkta paceļ ieteikumu sistēmas uz nākamo lÄ«meni.

Turklāt MLflow tuvina datu inženierus un datu zinātnes speciālistus, veidojot tiem kopīgu slāni.

Pēc Ŕīs MLflow izpētes esam pārliecināti, ka virzÄ«simies uz priekÅ”u un izmantosim to saviem Spark cauruļvadiem un ieteikumu sistēmām.

BÅ«tu jauki failu krātuvi sinhronizēt ar datu bāzi, nevis failu sistēmu. Tam vajadzētu iegÅ«t vairākus galapunktus, kas var izmantot vienu un to paÅ”u failu krātuvi. Piemēram, izmantojiet vairākus gadÄ«jumus Presto Šø Athena ar to paÅ”u Glue metastore.

Rezumējot, es vēlos pateikties MLFlow kopienai, kas padarīja mūsu darbu ar datiem interesantāku.

Ja spēlējaties ar MLflow, nevilcinieties un pastāstiet mums, kā to izmantojat, un vēl jo vairāk, ja to izmantojat ražoÅ”anā.

Uzzini vairāk par kursiem:
MaŔīnmācība. Pamatkurss
MaŔīnmācība. Padziļināts kurss

Lasīt vairāk:

Avots: www.habr.com

Pievieno komentāru