Kupanua Spark na MLflow

Halo, wakaazi wa Khabrovsk. Kama tulivyoandika tayari, mwezi huu OTUS inazindua kozi mbili za kujifunza kwa mashine mara moja, yaani msingi ΠΈ imeendelea. Katika suala hili, tunaendelea kushiriki nyenzo muhimu.

Madhumuni ya makala hii ni kuzungumza juu ya uzoefu wetu wa kwanza kutumia MLflow.

Tutaanza ukaguzi MLflow kutoka kwa seva yake ya ufuatiliaji na uandikishe marudio yote ya utafiti. Kisha tutashiriki uzoefu wetu wa kuunganisha Spark na MLflow kwa kutumia UDF.

Muktadha

Tuko ndani Afya ya Alpha Tunatumia kujifunza kwa mashine na akili ya bandia ili kuwawezesha watu kuchukua udhibiti wa afya na ustawi wao. Ndiyo maana miundo ya kujifunza kwa mashine ndiyo kiini cha bidhaa za sayansi ya data tunazotengeneza, na ndiyo sababu tulivutiwa na MLflow, mfumo huria ambao unashughulikia vipengele vyote vya mzunguko wa maisha wa kujifunza mashine.

MLflow

Lengo kuu la MLflow ni kutoa safu ya ziada juu ya ujifunzaji wa mashine ambayo ingeruhusu wanasayansi wa data kufanya kazi na karibu maktaba yoyote ya kujifunza mashine (h2o, keri, mleap, pytochi, fahamu ΠΈ tensorflow), akiipeleka kazi yake katika ngazi inayofuata.

MLflow hutoa vipengele vitatu:

  • Kufuatilia - kurekodi na maombi ya majaribio: kanuni, data, usanidi na matokeo. Kufuatilia mchakato wa kuunda mfano ni muhimu sana.
  • Miradi - Umbizo la ufungaji ili kuendeshwa kwenye jukwaa lolote (k.m. SageMaker)
  • Mifano ya - muundo wa kawaida wa kuwasilisha mifano kwa zana mbalimbali za kupeleka.

MLflow (katika alpha wakati wa kuandika) ni jukwaa huria ambalo hukuruhusu kudhibiti mzunguko wa maisha wa kujifunza kwa mashine, ikijumuisha majaribio, utumiaji upya na utumiaji.

Inaweka MLflow

Ili kutumia MLflow unahitaji kwanza kusanidi mazingira yako yote ya Python, kwa hili tutatumia PyEnv (kusakinisha Python kwenye Mac, angalia hapa) Kwa njia hii tunaweza kuunda mazingira ya kawaida ambapo tutasakinisha maktaba zote muhimu ili kuiendesha.

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

Wacha tusakinishe maktaba zinazohitajika.

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

Kumbuka: Tunatumia PyArrow kuendesha miundo kama vile UDF. Matoleo ya PyArrow na Numpy yalihitaji kurekebishwa kwa sababu matoleo ya mwisho yalikinzana.

Zindua UI ya Kufuatilia

Ufuatiliaji wa MLflow huturuhusu kuingia na kuuliza majaribio kwa kutumia Python na WALIOBAKI API. Kwa kuongeza, unaweza kuamua mahali pa kuhifadhi mabaki ya mfano (localhost, Amazon S3, Hifadhi ya Azure Blob, Google Cloud Uhifadhi au Seva ya SFTP) Kwa kuwa tunatumia AWS katika Alpha Health, hifadhi yetu ya vizalia vya programu itakuwa S3.

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

MLflow inapendekeza kutumia hifadhi endelevu ya faili. Hifadhi ya faili ndipo seva itahifadhi metadata inayoendeshwa na ya majaribio. Unapoanzisha seva, hakikisha inaelekeza kwenye hifadhi ya faili inayoendelea. Hapa kwa jaribio tutatumia tu /tmp.

Kumbuka kwamba ikiwa tunataka kutumia seva ya mlflow kuendesha majaribio ya zamani, lazima ziwepo kwenye hifadhi ya faili. Walakini, hata bila hii tunaweza kuzitumia katika UDF, kwani tunahitaji tu njia ya mfano.

Kumbuka: Kumbuka kwamba UI ya Ufuatiliaji na mteja wa mfano lazima wapate ufikiaji wa eneo la vizalia vya programu. Hiyo ni, bila kujali ukweli kwamba UI ya Kufuatilia inakaa katika mfano wa EC2, wakati wa kuendesha MLflow ndani ya nchi, mashine lazima iwe na ufikiaji wa moja kwa moja kwa S3 ili kuandika miundo ya vizalia vya programu.

Kupanua Spark na MLflow
Kufuatilia UI huhifadhi vizalia vya programu kwenye ndoo ya S3

Mifano zinazoendesha

Mara tu seva ya Ufuatiliaji inapofanya kazi, unaweza kuanza kufunza miundo.

Kama mfano, tutatumia urekebishaji wa divai kutoka kwa mfano wa MLflow katika Sklearn.

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

Kama tulivyojadili tayari, MLflow hukuruhusu kurekodi vigezo vya muundo, vipimo na vizalia vya programu ili uweze kufuatilia jinsi vinabadilika baada ya kurudiwa. Kipengele hiki ni muhimu sana kwa sababu kwa njia hii tunaweza kutoa muundo bora zaidi kwa kuwasiliana na seva ya Ufuatiliaji au kuelewa ni msimbo gani ulifanya marudio yanayohitajika kwa kutumia kumbukumbu za git hash za ahadi.

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

Kupanua Spark na MLflow
Marudio ya mvinyo

Sehemu ya seva kwa mfano

Seva ya ufuatiliaji wa MLflow, iliyozinduliwa kwa kutumia amri ya "mlflow server", ina REST API ya kufuatilia uendeshaji na kuandika data kwa mfumo wa faili wa ndani. Unaweza kubainisha anwani ya seva ya ufuatiliaji kwa kutumia tofauti ya mazingira "MLFLOW_TRACKING_URI" na API ya ufuatiliaji wa MLflow itawasiliana kiotomatiki na seva ya ufuatiliaji katika anwani hii ili kuunda/kupokea maelezo ya uzinduzi, kumbukumbu za vipimo, n.k.

Chanzo: Hati// Inaendesha seva ya ufuatiliaji

Ili kutoa modeli na seva, tunahitaji seva ya ufuatiliaji inayoendesha (angalia kiolesura cha uzinduzi) na Kitambulisho cha Run cha modeli.

Kupanua Spark na MLflow
Kitambulisho cha kukimbia

# 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

Ili kutoa miundo kwa kutumia utendaji wa huduma ya MLflow, tutahitaji ufikiaji wa UI ya Ufuatiliaji ili kupokea maelezo kuhusu muundo huo kwa kubainisha tu. --run_id.

Mara tu modeli inapowasiliana na seva ya Ufuatiliaji, tunaweza kupata mwisho wa muundo mpya.

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

Kukimbia mifano kutoka Spark

Licha ya ukweli kwamba seva ya Kufuatilia ina nguvu ya kutosha kutumikia mifano kwa wakati halisi, ifunze na utumie utendaji wa seva (chanzo: mlflow // hati // mifano # ya ndani), matumizi ya Spark (bechi au utiririshaji) ni suluhisho lenye nguvu zaidi kwa sababu ya usambazaji.

Fikiria kuwa ulifanya mafunzo nje ya mtandao na kisha ukatumia kielelezo cha matokeo kwenye data yako yote. Hapa ndipo Spark na MLflow huangaza.

Weka PySpark + Jupyter + Spark

Chanzo: Anza PySpark - Jupyter

Ili kuonyesha jinsi tunavyotumia miundo ya MLflow kwenye fremu za data za Spark, tunahitaji kusanidi madaftari ya Jupyter ili kufanya kazi pamoja na PySpark.

Anza kwa kusakinisha toleo la hivi punde thabiti 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Μ€

Sakinisha PySpark na Jupyter katika mazingira ya kawaida:

pip install pyspark jupyter

Weka vigezo vya mazingira:

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"

Baada ya kuamua notebook-dir, tunaweza kuhifadhi madaftari yetu kwenye folda inayotakiwa.

Inazindua Jupyter kutoka PySpark

Kwa kuwa tuliweza kusanidi Jupiter kama kiendeshi cha PySpark, sasa tunaweza kuendesha daftari la Jupyter katika muktadha wa 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

Kupanua Spark na MLflow

Kama ilivyoelezwa hapo juu, MLflow hutoa kipengele cha mabaki ya mfano wa ukataji miti katika S3. Mara tu tunapokuwa na modeli iliyochaguliwa mikononi mwetu, tuna fursa ya kuiagiza kama UDF kwa kutumia 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)

Kupanua Spark na MLflow
PySpark - Inatoa utabiri wa ubora wa divai

Hadi kufikia hatua hii, tumezungumza kuhusu jinsi ya kutumia PySpark na MLflow, kuendesha utabiri wa ubora wa divai kwenye hifadhidata nzima ya divai. Lakini vipi ikiwa unahitaji kutumia moduli za Python MLflow kutoka Scala Spark?

Tulijaribu hii pia kwa kugawa muktadha wa Spark kati ya Scala na Python. Hiyo ni, tulisajili MLflow UDF huko Python, na tukaitumia kutoka Scala (ndio, labda sio suluhisho bora, lakini tuliyo nayo).

Scala Spark + MLflow

Kwa mfano huu tutaongeza Toree Kernel kwenye Jupiter iliyopo.

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

Kama unavyoona kutoka kwa daftari iliyoambatishwa, UDF inashirikiwa kati ya Spark na PySpark. Tunatumahi kuwa sehemu hii itakuwa ya manufaa kwa wale wanaopenda Scala na wanataka kupeleka miundo ya kujifunza kwa mashine katika uzalishaji.

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

Hatua zifuatazo

Ingawa MLflow iko katika toleo la Alpha wakati wa uandishi, inaonekana ya kuahidi sana. Uwezo pekee wa kuendesha mifumo mingi ya kujifunza kwa mashine na kuzitumia kutoka sehemu moja ya mwisho huchukua mifumo ya wapendekezaji hadi ngazi inayofuata.

Kwa kuongezea, MLflow huleta Wahandisi wa Data na wataalamu wa Sayansi ya Data karibu zaidi, ikiweka safu ya kawaida kati yao.

Baada ya uchunguzi huu wa MLflow, tuna uhakika kwamba tutasonga mbele na kuitumia kwa mabomba yetu ya Spark na mifumo ya wapendekezaji.

Itakuwa nzuri kusawazisha hifadhi ya faili na hifadhidata badala ya mfumo wa faili. Hii inapaswa kutupa vidokezo vingi ambavyo vinaweza kutumia hifadhi sawa ya faili. Kwa mfano, tumia matukio mengi Presto ΠΈ Athena na metastore ya Gundi sawa.

Kwa muhtasari, ningependa kusema asante kwa jumuiya ya MLFlow kwa kufanya kazi yetu na data kuvutia zaidi.

Ikiwa unacheza na MLflow, usisite kutuandikia na kutuambia jinsi unavyoitumia, na hata zaidi ikiwa unaitumia katika uzalishaji.

Pata maelezo zaidi kuhusu kozi:
Kujifunza kwa mashine. Kozi ya msingi
Kujifunza kwa mashine. Kozi ya juu

Soma zaidi:

Chanzo: mapenzi.com

Kuongeza maoni