Spark hedatuz MLflow-rekin

Kaixo, Khabrovskeko bizilagunak. Dagoeneko idatzi genuen bezala, hilabete honetan OTUS-ek bi ikasketa automatikoko ikastaro jarriko ditu martxan aldi berean, alegia oinarria ΠΈ aurreratua. Ildo horretan, material erabilgarria partekatzen jarraitzen dugu.

Artikulu honen helburua gure lehen erabilera esperientziari buruz hitz egitea da MLflow.

Berrikuspenari ekingo diogu MLflow bere jarraipena zerbitzaritik eta azterketaren iterazio guztiak erregistratu. Ondoren, Spark MLflow-ekin konektatzearen esperientzia partekatuko dugu UDF erabiliz.

Testuingurua

Hemen gaude Alfa Osasuna Ikaskuntza automatikoa eta adimen artifiziala erabiltzen ditugu pertsonei beren osasuna eta ongizatea arduratzeko. Horregatik garatzen ditugun datu zientzien produktuen oinarrian daude ikaskuntza automatikoko ereduak, eta horregatik erakarri gintuen MLflow, ikaskuntza automatikoaren bizi-zikloaren alderdi guztiak biltzen dituen kode irekiko plataforma.

MLflow

MLflow-en helburu nagusia ikaskuntza automatikoaren gainean geruza gehigarri bat eskaintzea da, datu-zientzialariek ikaskuntza automatikoko ia edozein liburutegirekin lan egin dezaten (h2o, keras, mlaap, pitorxa, argitu ΠΈ tensorflow), bere lana hurrengo mailara eramanez.

MLflow-ek hiru osagai eskaintzen ditu:

  • Segimendua – grabaketa eta esperimentuen eskaerak: kodea, datuak, konfigurazioa eta emaitzak. Eredu bat sortzeko prozesuaren jarraipena egitea oso garrantzitsua da.
  • Proiektuak – Pakete formatua edozein plataformatan exekutatzeko (adibidez. SageMaker)
  • Ereduak – ereduak hainbat hedapen-tresnetara bidaltzeko formatu komuna.

MLflow (alfabetoan idazteko unean) kode irekiko plataforma bat da, ikaskuntza automatikoaren bizi-zikloa kudeatzeko aukera ematen duena, esperimentazioa, berrerabilpena eta hedapena barne.

MLflow konfiguratzea

MLflow erabiltzeko lehenik eta behin zure Python ingurune osoa konfiguratu behar duzu, horretarako erabiliko dugu PyEnv (Python Mac-en instalatzeko, begiratu Hemen). Honela ingurune birtual bat sortu ahal izango dugu non hura exekutatzeko beharrezkoak diren liburutegi guztiak instalatuko ditugun.

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

Instala ditzagun beharrezko liburutegiak.

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

Oharra: PyArrow erabiltzen dugu UDF bezalako ereduak exekutatzeko. PyArrow eta Numpy-ren bertsioak konpondu behar ziren, azken bertsioak elkarren artean gatazkan zeudelako.

Abiarazi Tracking UI

MLflow Tracking-ek esperimentuak erregistratzeko eta kontsultatzeko aukera ematen digu Python eta REST APIa. Horrez gain, ereduaren artefaktuak non gorde ditzakezu (localhost, Amazon S3, Azure Blob biltegiratzea, Google Cloud Storage edo SFTP zerbitzaria). Alpha Health-en AWS erabiltzen dugunez, gure artefaktuen biltegiratzea S3 izango da.

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

MLflow-ek fitxategien biltegiratze iraunkorra erabiltzea gomendatzen du. Fitxategien biltegiratzea zerbitzariak exekuzio eta esperimentazio metadatuak gordeko ditu. Zerbitzaria abiaraztean, ziurtatu fitxategi iraunkorreko biltegira apuntatzen duela. Hemen esperimenturako besterik gabe erabiliko dugu /tmp.

Gogoratu esperimentu zaharrak egiteko mlflow zerbitzaria erabili nahi badugu, fitxategien biltegian egon behar dutela. Hala ere, hau gabe ere UDFn erabil genitzake, eredurako bidea besterik ez baitugu behar.

Oharra: kontuan izan Tracking UI eta eredu-bezeroak artefaktu-kokapenerako sarbidea izan behar dutela. Hau da, Tracking UI-a EC2 instantzia batean egon arren, MLflow lokalean exekutatzen denean, makinak S3rako sarbide zuzena izan behar du artefaktu-ereduak idazteko.

Spark hedatuz MLflow-rekin
Tracking UI artefaktuak S3 ontzi batean gordetzen ditu

Korrika egiteko ereduak

Jarraipen zerbitzaria martxan jarri bezain laster, modeloak entrenatzen has zaitezke.

Adibide gisa, MLflow adibideko ardoaren aldaketa erabiliko dugu Sklearn.

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

Dagoeneko aipatu dugun bezala, MLflow-ek ereduaren parametroak, metrikak eta artefaktuak erregistratzeko aukera ematen du, iterazioetan nola eboluzionatzen duten jarrai dezazun. Ezaugarri hau oso erabilgarria da, horrela eredurik onena erreproduzitu ahal izango baitugu Jarraipen zerbitzariarekin harremanetan jarriz edo behar den iterazioa zein kode egin duen ulertuz konpromezuen git hash erregistroak erabiliz.

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 hedatuz MLflow-rekin
Ardoaren errepikapenak

Ereduaren zerbitzariaren zatia

MLflow jarraipenaren zerbitzariak, "mlflow server" komandoa erabiliz abiarazitako, REST API bat du exekuzioak jarraitzeko eta fitxategi-sistema lokalean datuak idazteko. Jarraipen-zerbitzariaren helbidea zehaztu dezakezu "MLFLOW_TRACKING_URI" ingurune-aldagaia erabiliz eta MLflow-ren jarraipenaren APIa automatikoki jarriko da harremanetan jarraipen-zerbitzariarekin helbide honetan, abiarazte-informazioa, erregistro-neurriak eta abar sortzeko/jasotzeko.

Iturria: Dokumentuak// Jarraipen-zerbitzari bat exekutatzen

Ereduari zerbitzari bat emateko, martxan dagoen jarraipen-zerbitzari bat (ikus abiarazteko interfazea) eta ereduaren Run IDa behar ditugu.

Spark hedatuz MLflow-rekin
Exekutatu 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

MLflow zerbitzuaren funtzionalitatea erabiliz ereduak hornitzeko, Jarraipeneko UI-rako sarbidea beharko dugu ereduari buruzko informazioa jasotzeko, besterik gabe, zehaztuz. --run_id.

Eredua Jarraipen zerbitzariarekin harremanetan jartzen denean, ereduaren amaiera-puntu berri bat lor dezakegu.

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

Spark-eko modeloak martxan

Jarraipen zerbitzaria ereduak denbora errealean zerbitzatzeko nahikoa indartsua izan arren, entrenatu eta zerbitzariaren funtzionaltasuna erabili (iturria: mlflow // docs // ereduak # local), Spark erabiltzea (batch edo streaming) are irtenbide indartsuagoa da banaketa dela eta.

Imajinatu prestakuntza lineaz kanpo egin duzula eta, ondoren, irteera-eredua zure datu guztiei aplikatu diezula. Hau da Spark eta MLflow distira.

Instalatu PySpark + Jupyter + Spark

Iturria: Hasi PySpark - Jupyter

Spark datu-markoetan MLflow ereduak nola aplikatzen ditugun erakusteko, Jupyter koadernoak konfiguratu behar ditugu PySpark-ekin batera lan egiteko.

Hasi azken bertsio egonkorra instalatzen 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Μ€

Instalatu PySpark eta Jupyter ingurune birtualean:

pip install pyspark jupyter

Konfiguratu ingurune-aldagaiak:

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"

Zehaztuta notebook-dir, nahi dugun karpetan gorde ditzakegu gure koadernoak.

PySpark-etik Jupyter abiarazten

Jupiter PySpark kontrolatzaile gisa konfiguratu ahal izan genuenez, orain Jupyter koadernoa exekutatu dezakegu PySpark-en testuinguruan.

(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 hedatuz MLflow-rekin

Arestian esan bezala, MLflow-ek S3-n ereduaren artefaktuak erregistratzeko funtzio bat eskaintzen du. Aukeratutako eredua esku artean izan bezain laster, modulua erabiliz UDF gisa inportatzeko aukera dugu. 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 hedatuz MLflow-rekin
PySpark - Ardoaren kalitatearen iragarpenak ateratzea

Orain arte, PySpark MLflow-ekin nola erabili hitz egin dugu, ardoaren kalitatearen iragarpenak ardoaren datu-multzo osoan exekutatzen. Baina zer gertatzen da Scala Spark-eko Python MLflow moduluak erabili behar badituzu?

Hau ere probatu dugu Spark testuingurua Scala eta Python artean banatuz. Hau da, MLflow UDF Python-en erregistratu dugu, eta Scalatik erabili dugu (bai, agian ez da irtenbiderik onena, baina daukaguna).

Scala Spark + MLflow

Adibide honetarako gehituko dugu Toree Kernel dagoen Jupiterren sartu.

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

Erantsitako koadernoan ikus dezakezun bezala, UDF Spark eta PySpark-en artean partekatzen da. Zati hau Scala maite dutenentzat eta ekoizpenean ikaskuntza automatikoko ereduak zabaldu nahi dituztenentzat erabilgarria izatea espero dugu.

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

Hurrengo urratsak

Idazteko unean MLflow Alpha bertsioan dagoen arren, nahiko itxaropentsua dirudi. Ikaskuntza automatikoko hainbat esparru exekutatu eta amaierako puntu bakar batetik kontsumitzeko gaitasunak gomendio sistemak hurrengo mailara eramaten ditu.

Horrez gain, MLflow-ek Data Engineers eta Data Science espezialistak hurbiltzen ditu, haien artean geruza komun bat ezarriz.

MLflow-en esplorazio honen ondoren, ziur gaude aurrera egingo dugula eta Spark kanalizazioetarako eta gomendio-sistemetarako erabiliko dugula.

Fitxategien biltegiratzea datu-basearekin sinkronizatzea ondo legoke fitxategi sistemarekin ordez. Honek fitxategien biltegiratze bera erabil dezaketen amaiera-puntu anitz eman beharko liguke. Adibidez, erabili hainbat instantzia Presto ΠΈ Athena Glue metadenda berarekin.

Laburbilduz, eskerrak eman nahi nizkioke MLFlow komunitateari gure lana datuekin interesgarriagoa egiteagatik.

MLflow-ekin jolasten ari bazara, ez izan zalantzarik idatzi eta kontatu nola erabiltzen duzun, eta are gehiago ekoizpenean erabiltzen baduzu.

Ikastaroei buruzko informazio gehiago:
Ikaskuntza automatikoa. Oinarrizko ikastaroa
Ikaskuntza automatikoa. Ikastaro aurreratua

Irakurri gehiago:

Iturria: www.habr.com

Gehitu iruzkin berria