Салом, Хабровиён. Тавре ки мо аллакай навишта будем, дар ин моҳ OTUS якбора ду курси омӯзиши мошинро оғоз мекунад, яъне
Мақсади ин мақола ин аст, ки дар бораи таҷрибаи аввалини мо бо
Мо баррасиро оғоз мекунем
Мавзӯъ
Мо дар он ҳастем
MLflow
Ҳадафи асосии MLflow таъмин намудани қабати иловагӣ дар болои омӯзиши мошинсозӣ мебошад, ки ба олимони маълумот имкон медиҳад, ки қариб бо ҳама китобхонаҳои омӯзиши мошинсозӣ кор кунанд (
MLflow се ҷузъро таъмин мекунад:
- Поиш - сабт ва дархостҳо барои таҷрибаҳо: рамз, маълумот, конфигуратсия ва натиҷаҳо. Раванди эҷоди моделро риоя кардан хеле муҳим аст.
- Лоиҳаҳо - Формати бастабандӣ барои кор дар ҳама гуна платформа (масалан,
SageMaker ) - моделҳои формати маъмул барои пешниҳоди моделҳо ба абзорҳои гуногуни густариш аст.
MLflow (алфа дар вақти навиштан) як платформаи кушодаасос аст, ки ба шумо имкон медиҳад, ки давраи омӯзиши мошинсозӣ, аз ҷумла озмоиш, дубора истифода ва густаришро идора кунед.
Танзими MLflow
Барои истифодаи MLflow, шумо бояд аввал тамоми муҳити Python-ро насб кунед, барои ин мо истифода хоҳем кард
```
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
```
Китобхонаҳои лозимиро насб кунед.
```
pip install mlflow==0.7.0
Cython==0.29
numpy==1.14.5
pandas==0.23.4
pyarrow==0.11.0
```
Эзоҳ: Мо PyArrow-ро барои идора кардани моделҳо ба монанди UDFs истифода мебарем. Версияҳои PyArrow ва Numpy бояд ислоҳ карда шаванд, зеро версияҳои охирин бо ҳамдигар ихтилоф доштанд.
Оғози UI Tracking UI
Tracking MLflow ба мо имкон медиҳад, ки таҷрибаҳоро бо Python ва
# Running a Tracking Server
mlflow server
--file-store /tmp/mlflow/fileStore
--default-artifact-root s3://<bucket>/mlflow/artifacts/
--host localhost
--port 5000
MLflow истифодаи нигаҳдории доимии файлро тавсия медиҳад. Нигоҳдории файл дар он ҷоест, ки сервер метамаълумотро иҷро мекунад ва озмоиш мекунад. Ҳангоми оғоз кардани сервер, боварӣ ҳосил кунед, ки он ба нигоҳдории файлҳои доимӣ ишора мекунад. Дар ин ҷо, ба хотири таҷриба, мо танҳо истифода мебарем /tmp
.
Дар хотир доред, ки агар мо хоҳем, ки сервери mlflow-ро барои иҷро кардани таҷрибаҳои кӯҳна истифода барем, онҳо бояд дар мағозаи файл мавҷуд бошанд. Аммо, ҳатто бидуни ин, мо метавонем онҳоро дар UDF истифода барем, зеро ба мо танҳо роҳ ба модел лозим аст.
Эзоҳ: Дар хотир доред, ки UI Tracking UI ва муштарии модел бояд ба макони артефакт дастрасӣ дошта бошанд. Яъне, новобаста аз он, ки UI Tracking UI дар мисоли EC2 ҷойгир аст, ҳангоми ба таври маҳаллӣ иҷро кардани MLflow, мошин бояд барои навиштани моделҳои артефакт ба S3 дастрасии мустақим дошта бошад.
Пайгирии UI артефактҳоро дар сатили S3 нигоҳ медорад
Моделҳои иҷрошаванда
Ҳамин ки сервери Tracking кор мекунад, шумо метавонед ба омӯзиши моделҳо шурӯъ кунед.
Ҳамчун мисол, мо тағир додани шаробро аз мисоли MLflow дар
MLFLOW_TRACKING_URI=http://localhost:5000 python wine_quality.py
--alpha 0.9
--l1_ration 0.5
--wine_file ./data/winequality-red.csv
Тавре ки мо гуфта будем, MLflow ба шумо имкон медиҳад, ки параметрҳо, ченакҳо ва артефактҳои моделиро сабт кунед, то шумо метавонед пайгирӣ кунед, ки чӣ гуна онҳо ҳамчун итератсия инкишоф меёбанд. Ин хусусият бениҳоят муфид аст, зеро он ба мо имкон медиҳад, ки модели беҳтаринро тавассути тамос бо сервери Tracking дубора тавлид кунем ё фаҳмем, ки кадом код бо истифода аз сабтҳои git hash-и ӯҳдадориҳо такрори лозимиро иҷро кардааст.
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")
такрори шароб
Қисми қафо барои модел
Сервери пайгирии MLflow, ки бо фармони "server mlflow" оғоз шудааст, дорои REST API барои пайгирии иҷроҳо ва навиштани маълумот ба системаи файлии маҳаллӣ мебошад. Шумо метавонед суроғаи сервери пайгириро бо истифода аз тағирёбандаи муҳити зисти "MLFLOW_TRACKING_URI" муайян кунед ва API пайгирии MLflow ба таври худкор бо сервери пайгирӣ дар ин суроға тамос мегирад, то иттилооти оғозёбӣ, ченакҳои сабти ном ва ғ.
Манбаъ:
Ҳуҷҷатҳо// Иҷрои сервери пайгирӣ
Барои таъмин кардани модел бо сервер, ба мо сервери пайгирии иҷрошаванда (ба интерфейси оғозёбӣ нигаред) ва ID Run модел лозим аст.
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, ба мо лозим аст, ки ба UI Tracking UI дастрасӣ дошта бошем, то дар бораи модел бо роҳи муайян кардани маълумот маълумот гирем. --run_id
.
Вақте ки модел бо сервери пайгирӣ тамос мегирад, мо метавонем нуқтаи ниҳоии модели навро ба даст орем.
# 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
Сарфи назар аз он, ки сервери Tracking ба қадри кофӣ тавоност, ки ба моделҳо дар вақти воқеӣ хидмат кунад, онҳоро таълим диҳед ва аз функсияҳои сервер истифода баред (манбаъ:
Тасаввур кунед, ки шумо танҳо омӯзиши офлайнӣ анҷом додаед ва сипас модели баромадро ба ҳамаи маълумоти худ татбиқ кардед. Дар ин ҷо Spark ва MLflow ба худ меоянд.
PySpark + Jupyter + Spark насб кунед
Манбаъ:
Оғози PySpark - Jupyter
Барои нишон додани он ки чӣ тавр мо моделҳои MLflow-ро ба dataframes Spark истифода мебарем, мо бояд ноутбукҳои Jupyter-ро барои кор бо PySpark насб кунем.
Бо насб кардани версияи охирини устувор оғоз кунед
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̀
PySpark ва Jupyter -ро дар муҳити виртуалӣ насб кунед:
pip install pyspark jupyter
Тағйирёбандаҳои муҳити атрофро танзим кунед:
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"
Муайян карда notebook-dir
, мо метавонем дафтархои худро дар папкаи дилхох нигох дорем.
Иҷрои Jupyter аз PySpark
Азбаски мо тавонистем Jupiter-ро ҳамчун ронандаи PySpark насб кунем, ҳоло мо метавонем дафтарчаи Jupyter-ро дар контексти 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
Тавре ки дар боло зикр гардид, MLflow вазифаи сабти артефактҳои моделиро дар S3 таъмин мекунад. Ҳамин ки мо модели интихобшударо дар дасти худ дорем, мо имкон дорем, ки онро ҳамчун UDF бо истифода аз модул ворид кунем 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)
PySpark - Пешгӯии сифати шароб
То ин вақт, мо дар бораи чӣ гуна истифода бурдани PySpark бо MLflow тавассути пешгӯии сифати шароб дар тамоми маҷмӯаи маълумоти шароб сӯҳбат кардем. Аммо чӣ мешавад, агар ба шумо лозим аст, ки модулҳои Python MLflow -ро аз Scala Spark истифода баред?
Мо инро инчунин тавассути тақсим кардани контексти Spark байни Scala ва Python озмоиш кардем. Яъне, мо MLflow UDF-ро дар Python ба қайд гирифтем ва онро аз Scala истифода бурдем (бале, шояд ҳалли беҳтарин нест, аммо он чизе ки мо дорем).
Scala Spark + MLflow
Барои ин мисол, мо илова мекунем
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
```
Тавре ки шумо аз дафтари замимашуда мебинед, UDF байни Spark ва PySpark тақсим карда мешавад. Мо умедворем, ки ин қисм барои онҳое, ки Scala-ро дӯст медоранд ва мехоҳанд моделҳои омӯзиши мошинро дар истеҳсолот ҷойгир кунанд, муфид хоҳад буд.
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 |
+-----------+--------+-----------+---------+-----------+
Қадамҳои оянда
Гарчанде ки MLflow дар вақти навиштан дар Алфа аст, он хеле умедбахш ба назар мерасад. Танҳо қобилияти кор кардани чаҳорчӯбаҳои омӯзиши мошинҳои сершумор ва истифодаи онҳо аз як нуқтаи ниҳоӣ системаҳои тавсиядиҳандаро ба сатҳи оянда мебарад.
Илова бар ин, MLflow муҳандисони маълумот ва олимони маълумотро ба ҳам наздик мекунад ва дар байни онҳо як қабати умумӣ мегузорад.
Пас аз ин таҳқиқи MLflow, мо боварӣ дорем, ки пеш рафта, онро барои лӯлаҳои Spark ва системаҳои тавсиядиҳандаи худ истифода мебарем.
Хуб мебуд, ки нигоҳдории файлро бо пойгоҳи додаҳо ба ҷои системаи файлӣ ҳамоҳанг созед. Ин бояд ба мо якчанд нуқтаи ниҳоӣ диҳад, ки метавонанд як мубодилаи файлро истифода баранд. Масалан, якчанд мисолҳоро истифода баред
Дар ҷамъбаст, ман мехоҳам ба ҷомеаи MLFlow ташаккур гӯям, ки кори моро бо маълумот ҷолибтар кардааст.
Агар шумо бо MLflow бозӣ кунед, озодона ба мо нависед ва ба мо бигӯед, ки чӣ гуна онро истифода мебаред ва ҳатто бештар аз он, агар шумо онро дар истеҳсолот истифода баред.
Маълумоти бештар дар бораи курсҳо:
Бештар:
Хавфҳо ва огоҳиҳо ҳангоми татбиқи таҳлили ҷузъҳои асосӣ ба мушкилоти омӯзиши назоратшаванда Ҷойгир кардани модели омӯзиши мошинсозӣ бо Docker - Қисми 1 Ҷойгир кардани модели омӯзиши мошинсозӣ бо Docker - Қисми 2
Манбаъ: will.com