Ngalegaan Spark sareng MLflow

Halo, Khabrovites. Sakumaha urang parantos nyerat, sasih ieu OTUS ngaluncurkeun dua kursus diajar mesin sakaligus, nyaéta dasar и maju. Dina hal ieu, urang terus babagi bahan mangpaat.

Tujuan tina artikel ieu ngobrol ngeunaan pangalaman munggaran urang jeung MLflow.

Urang bakal ngamimitian ulasan MLflow ti server tracking sarta prolog sagala iterasi ulikan. Teras kami bakal ngabagi pangalaman nyambungkeun Spark sareng MLflow nganggo UDF.

Kontéks

Kami asup Kaséhatan Alpha kami nganggo pembelajaran mesin sareng intelijen buatan pikeun nguatkeun jalma pikeun ngurus kaséhatan sareng karaharjaan. Ieu sababna modél pembelajaran mesin aya dina manah produk élmu data anu urang kembangkeun, sareng naha MLflow, platform open source anu nyertakeun sagala aspek siklus kahirupan mesin, narik perhatian urang.

MLflow

Tujuan utama MLflow nyaéta pikeun nyayogikeun lapisan tambahan dina pembelajaran mesin anu ngamungkinkeun para ilmuwan data damel sareng ampir sadaya perpustakaan pembelajaran mesin (h2o, keras, ngalepat, pytorch, sklearn и tensorflow), nyandak karyana ka tingkat salajengna.

MLflow nyadiakeun tilu komponén:

  • tracking - ngarékam sareng pamundut pikeun ékspérimén: kode, data, konfigurasi sareng hasil. Penting pisan pikeun nuturkeun prosés nyiptakeun modél.
  • proyék - Format bungkusan pikeun dijalankeun dina platform naon waé (contona, SageMaker)
  • Models mangrupakeun format umum pikeun ngirimkeun model ka sagala rupa parabot deployment.

MLflow (alfa dina waktos nyerat) mangrupikeun platform open source anu ngamungkinkeun anjeun ngatur siklus kahirupan mesin diajar, kalebet ékspérimén, pamakean deui, sareng panyebaran.

Nyetél MLflow

Pikeun nganggo MLflow, anjeun kedah nyetél sadayana lingkungan Python, pikeun ieu kami bakal dianggo PyEnv (Pikeun masang Python dina Mac, tingali di dieu). Janten urang tiasa nyiptakeun lingkungan virtual dimana urang bakal masang sadaya perpustakaan anu dipikabutuh pikeun ngajalankeun.

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

Pasang perpustakaan anu diperyogikeun.

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

Catetan: Kami nganggo PyArrow pikeun ngajalankeun modél sapertos UDF. Versi PyArrow sareng Numpy kedah dilereskeun sabab vérsi pangénggalna saling bertentangan.

Ngajalankeun Tracking UI

MLflow Tracking ngamungkinkeun urang pikeun log sareng naroskeun ékspérimén sareng Python sareng ngaso API. Salaku tambahan, anjeun tiasa netepkeun dimana nyimpen artefak modél (localhost, Amazon S3, Azure Blob Panyimpenan, Panyimpenan Awan Google atawa server SFTP). Kusabab kami nganggo AWS di Alpha Health, S3 bakal janten gudang pikeun artefak.

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

MLflow nyarankeun ngagunakeun panyimpenan file anu pengkuh. Panyimpen file mangrupikeun tempat server bakal nyimpen metadata jalan sareng ékspérimén. Nalika ngamimitian server, pastikeun éta nunjuk kana panyimpenan file anu pengkuh. Di dieu, demi ékspérimén, urang ngan saukur nganggo /tmp.

Émut yén upami urang hoyong nganggo server mlflow pikeun ngajalankeun percobaan lami, aranjeunna kedah aya dina toko file. Sanajan kitu, sanajan tanpa ieu, urang bakal bisa ngagunakeun éta dina UDF, sabab urang ngan butuh jalur ka model.

Catetan: Émut yén UI Tracking sareng klien modél kedah gaduh aksés ka lokasi artefak. Nyaéta, henteu paduli kanyataan yén Tracking UI aya dina conto EC2, nalika ngajalankeun MLflow sacara lokal, mesin kedah gaduh aksés langsung ka S3 pikeun nyerat modél artefak.

Ngalegaan Spark sareng MLflow
Tracking UI nyimpen artefak dina ember S3

Ngajalankeun Models

Pas server Tracking dijalankeun, anjeun tiasa ngamimitian ngalatih modél.

Salaku conto, urang bakal nganggo modifikasi anggur tina conto MLflow di Sklearn.

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

Sakumaha anu kami nyarios, MLflow ngamungkinkeun anjeun pikeun log in parameter, métrik, sareng artefak modél supados anjeun tiasa ngalacak kumaha aranjeunna berkembang salaku iterasi. Fitur ieu mangpaat pisan, sabab ngamungkinkeun urang pikeun ngahasilkeun deui modél anu pangsaéna ku ngahubungi server Pelacak atanapi ngartos kode mana anu ngalaksanakeun iterasi anu diperyogikeun nganggo log hash git tina commits.

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

Ngalegaan Spark sareng MLflow
iteration anggur

Balik tungtung pikeun modél

Server tracking MLflow diluncurkeun sareng paréntah "server mlflow" ngagaduhan API REST pikeun ngalacak jalan sareng nyerat data kana sistem file lokal. Anjeun tiasa netepkeun alamat pangladén pelacak nganggo variabel lingkungan "MLFLOW_TRACKING_URI" sareng API pelacak MLflow bakal otomatis ngahubungi pangladén pelacak di alamat ieu pikeun nyiptakeun / kéngingkeun inpormasi jalan, métrik log, jsb.

sumber: Docs // Ngajalankeun server tracking

Pikeun nyadiakeun model kalawan server a, urang kudu ngajalankeun server tracking (tingali panganteur peluncuran) jeung Run ID model.

Ngalegaan Spark sareng MLflow
Jalankeun 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

Pikeun ngalayanan modél nganggo fungsionalitas MLflow serve, urang peryogi aksés ka UI Tracking pikeun kéngingkeun inpormasi ngeunaan modél ku ngan saukur nangtukeun --run_id.

Sakali modél ngahubungi Server Pelacak, urang tiasa nampi titik akhir modél énggal.

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

Ngajalankeun model ti Spark

Sanaos kanyataan yén server Tracking cukup kuat pikeun ngalayanan modél sacara real waktos, ngalatih aranjeunna sareng nganggo fungsionalitas server (sumber: mlflow // docs // models #local), ngagunakeun Spark (angkatan atanapi streaming) mangrupikeun solusi anu langkung kuat kusabab distribusina.

Bayangkeun yén anjeun nembé ngalaksanakeun latihan offline teras nerapkeun modél kaluaran ka sadaya data anjeun. Ieu dimana Spark sareng MLflow asalna sorangan.

Pasang PySpark + Jupyter + Spark

sumber: Ngamimitian PySpark - Jupyter

Pikeun nunjukkeun kumaha urang nerapkeun modél MLflow kana kerangka data Spark, urang kedah nyetél notebook Jupyter pikeun damel sareng PySpark.

Mimitian ku masang versi stabil panganyarna Apache bitu:

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̀

Pasang PySpark sareng Jupyter dina lingkungan virtual:

pip install pyspark jupyter

Nyetél variabel lingkungan:

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"

Sanggeus dihartikeun notebook-dir, urang bakal tiasa nyimpen buku catetan urang dina folder nu dipikahoyong.

Ngajalankeun Jupyter ti PySpark

Kusabab urang tiasa nyetél Jupiter salaku supir PySpark, urang ayeuna tiasa ngajalankeun notebook Jupyter dina kontéks PySpark.

(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

Ngalegaan Spark sareng MLflow

Sakumaha didadarkeun di luhur, MLflow nyadiakeun fungsi logging model artefak di S3. Pas urang boga model dipilih di leungeun urang, urang boga kasempetan pikeun ngimpor salaku UDF ngagunakeun 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)

Ngalegaan Spark sareng MLflow
PySpark - Ngaramal kualitas anggur

Nepi ka titik ieu, urang geus ngobrol ngeunaan kumaha carana make PySpark kalawan MLflow ku ngajalankeun prediksi kualitas anggur dina sakabéh dataset anggur. Tapi kumaha upami anjeun kedah nganggo modul Python MLflow ti Scala Spark?

Kami ogé nguji ieu ku ngabagi kontéks Spark antara Scala sareng Python. Hartina, urang didaptarkeun MLflow UDF di Python, sarta dipaké ti Scala (enya, meureun moal solusi pangalusna, tapi naon urang kudu).

Scala Spark + MLflow

Pikeun conto ieu, urang bakal nambahan Toree Kernel kana Jupiter aya.

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

Sakumaha anjeun tiasa tingali tina notebook anu napel, UDF dibagi antara Spark sareng PySpark. Kami ngarepkeun bagian ieu bakal mangpaat pikeun anu resep Scala sareng hoyong nyebarkeun modél pembelajaran mesin pikeun produksi.

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

Léngkah-léngkah salajengna

Sanaos MLflow aya dina Alpha dina waktos nyerat, éta katingalina ngajangjikeun. Ngan ukur tiasa ngajalankeun sababaraha kerangka pembelajaran mesin sareng dianggo tina hiji titik tungtung nyandak sistem anu nyarankeun ka tingkat salajengna.

Salaku tambahan, MLflow ngahijikeun insinyur Data sareng Ilmuwan Data, nempatkeun lapisan umum di antara aranjeunna.

Saatos éksplorasi MLflow ieu, kami yakin bakal teraskeun sareng nganggo éta pikeun pipa Spark sareng sistem anu nyarankeun.

Éta langkung saé pikeun nyinkronkeun panyimpen file sareng pangkalan data tinimbang sistem file. Ieu kedah masihan kami sababaraha titik tungtung anu tiasa nganggo pangsa file anu sami. Contona, make sababaraha instansi Presto и pundah kalawan metastore Lem sarua.

Nyimpulkeun, abdi hoyong ngucapkeun hatur nuhun ka komunitas MLFlow pikeun ngajantenkeun padamelan urang kalayan data langkung narik.

Lamun maén kalawan MLflow, ngarasa Luncat ka nulis ka kami sarta ngabejaan urang kumaha anjeun make eta, komo deui lamun make eta dina produksi.

Diajar langkung seueur ngeunaan kursus:
pembelajaran mesin. Kursus dasar
pembelajaran mesin. tangtu maju

Maca deui:

sumber: www.habr.com

Tambahkeun komentar