Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ возмоТностСй Spark с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ MLflow

ΠŸΡ€ΠΈΠ²Π΅Ρ‚, Ρ…Π°Π±Ρ€ΠΎΠ²Ρ‡Π°Π½Π΅. Как ΠΌΡ‹ ΡƒΠΆΠ΅ писали, Π² этом мСсяцС OTUS запускаСт сразу Π΄Π²Π° курса ΠΏΠΎ ΠΌΠ°ΡˆΠΈΠ½Π½ΠΎΠΌΡƒ ΠΎΠ±ΡƒΡ‡Π΅Π½ΠΈΡŽ, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ ΠΈ ΠΏΡ€ΠΎΠ΄Π²ΠΈΠ½ΡƒΡ‚Ρ‹ΠΉ. Π’ связи с этим ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅ΠΌ Π΄Π΅Π»ΠΈΡ‚ΡŒΡΡ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ΠΌ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠΌ.

ЦСль этой ΡΡ‚Π°Ρ‚ΡŒΠΈ – Ρ€Π°ΡΡΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΎ нашСм ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠΏΡ‹Ρ‚Π΅ использования MLflow.

ΠœΡ‹ Π½Π°Ρ‡Π½Π΅ΠΌ ΠΎΠ±Π·ΠΎΡ€ MLflow с Π΅Π³ΠΎ tracking-сСрвСра ΠΈ ΠΏΡ€ΠΎΠ»ΠΎΠ³ΠΈΡ€ΡƒΠ΅ΠΌ всС ΠΈΡ‚Π΅Ρ€Π°Ρ†ΠΈΠΈ исслСдования. Π—Π°Ρ‚Π΅ΠΌ подСлимся ΠΎΠΏΡ‹Ρ‚ΠΎΠΌ соСдинСния Spark с MLflow с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ UDF.

ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚

ΠœΡ‹ Π² Alpha Health ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ машинноС ΠΎΠ±ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΈ искусствСнный ΠΈΠ½Ρ‚Π΅Π»Π»Π΅ΠΊΡ‚, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄Π°Ρ‚ΡŒ людям Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π·Π°Π±ΠΎΡ‚ΠΈΡ‚ΡŒΡΡ ΠΎ своСм Π·Π΄ΠΎΡ€ΠΎΠ²ΡŒΠ΅ ΠΈ Π±Π»Π°Π³ΠΎΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΈ. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ ΠΌΠΎΠ΄Π΅Π»ΠΈ машинного обучСния Π»Π΅ΠΆΠ°Ρ‚ Π² основС Ρ€Π°Π·Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌΡ‹Ρ… Π½Π°ΠΌΠΈ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ΠΎΠ² ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…, ΠΈ ΠΈΠΌΠ΅Π½Π½ΠΎ поэтому нашС Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ ΠΏΡ€ΠΈΠ²Π»Π΅ΠΊΠ»Π° MLflow β€” ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ° с ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ исходным ΠΊΠΎΠ΄ΠΎΠΌ, которая ΠΎΡ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ всС аспСкты ΠΆΠΈΠ·Π½Π΅Π½Π½ΠΎΠ³ΠΎ Ρ†ΠΈΠΊΠ»Π° машинного обучСния.

MLflow

Основная Ρ†Π΅Π»ΡŒ MLflow – ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ слой ΠΏΠΎΠ²Π΅Ρ€Ρ… машинного обучСния, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΠ» Π±Ρ‹ спСциалистам ΠΏΠΎ data science Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ практичСски с любой Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΎΠΉ машинного обучСния (h2o, keras, mleap, pytorch, sklearn ΠΈ tensorflow), выводя Π΅Π΅ Ρ€Π°Π±ΠΎΡ‚Ρƒ Π½Π° Π½ΠΎΠ²Ρ‹ΠΉ ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ.

MLflow обСспСчиваСт Ρ‚Ρ€ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°:

  • Tracking – запись ΠΈ запросы ΠΊ экспСримСнтам: ΠΊΠΎΠ΄, Π΄Π°Π½Π½Ρ‹Π΅, конфигурация ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹. Π‘Π»Π΅Π΄ΠΈΡ‚ΡŒ Π·Π° процСссом создания ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΎΡ‡Π΅Π½ΡŒ Π²Π°ΠΆΠ½ΠΎ.
  • Projects – Π€ΠΎΡ€ΠΌΠ°Ρ‚ ΡƒΠΏΠ°ΠΊΠΎΠ²ΠΊΠΈ для запуска Π½Π° любой ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, SageMaker)
  • Models – ΠΎΠ±Ρ‰ΠΈΠΉ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ Π² Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ инструмСнты развСртывания.

MLflow (Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ написания ΡΡ‚Π°Ρ‚ΡŒΠΈ Π² alpha-вСрсии) β€” ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ° с ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ исходным ΠΊΠΎΠ΄ΠΎΠΌ, которая позволяСт ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ ΠΆΠΈΠ·Π½Π΅Π½Π½Ρ‹ΠΌ Ρ†ΠΈΠΊΠ»ΠΎΠΌ машинного обучСния, Π² Ρ‚ΠΎΠΌ числС экспСримСнтами, ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΈ Ρ€Π°Π·Π²Π΅Ρ€Ρ‚Ρ‹Π²Π°Π½ΠΈΠ΅ΠΌ.

Настройка MLflow

Для использования MLflow Π½ΡƒΠΆΠ½ΠΎ сначала Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ всю срСду Python, для этого ΠΌΡ‹ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ PyEnv (Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Python Π½Π° Mac, заглянитС сюда). Π’Π°ΠΊ ΠΌΡ‹ смоТСм ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΡƒΡŽ срСду, ΠΊΡƒΠ΄Π° установим всС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ для запуска Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ.

```
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 для запуска Ρ‚Π°ΠΊΠΈΡ… ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ ΠΊΠ°ΠΊ UDF. ВСрсии PyArrow ΠΈ Numpy Π½ΡƒΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ ΠΏΠΎΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ послСдниС вСрсии ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ΠΎΠ²Π°Π»ΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ собой.

ЗапускаСм Tracking UI

MLflow Tracking позволяСт Π½Π°ΠΌ Π»ΠΎΠ³ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ Π΄Π΅Π»Π°Ρ‚ΡŒ запросы ΠΊ экспСримСнтам с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Python ΠΈ REST API. Помимо этого, ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ, Π³Π΄Π΅ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚Ρ‹ ΠΌΠΎΠ΄Π΅Π»ΠΈ (localhost, Amazon S3, Azure Blob Storage, Google Cloud Storage ΠΈΠ»ΠΈ SFTP-сСрвСр). ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² Alpha Health ΠΌΡ‹ ΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ AWS, Π² качСствС Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π° Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚ΠΎΠ² Π±ΡƒΠ΄Π΅Ρ‚ S3.

# 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, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π½Π°ΠΌ Π½ΡƒΠΆΠ΅Π½ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡƒΡ‚ΡŒ Π΄ΠΎ ΠΌΠΎΠ΄Π΅Π»ΠΈ.

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅: Π˜ΠΌΠ΅ΠΉΡ‚Π΅ Π² Π²ΠΈΠ΄Ρƒ, Ρ‡Ρ‚ΠΎ Tracking UI ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΌΠΎΠ΄Π΅Π»ΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΈΠΌΠ΅Ρ‚ΡŒ доступ ΠΊ ΠΌΠ΅ΡΡ‚ΠΎΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΡŽ Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚Π°. Π’ΠΎ Π΅ΡΡ‚ΡŒ Π²Π½Π΅ зависимости ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Tracking UI располагаСтся Π² экзСмплярС EC2, ΠΏΡ€ΠΈ локальном запускС MLflow Ρƒ ΠΌΠ°ΡˆΠΈΠ½Ρ‹ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ прямой доступ ΠΊ S3 для записи ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚ΠΎΠ².

Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ возмоТностСй Spark с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ MLflow
Tracking UI Ρ…Ρ€Π°Π½ΠΈΡ‚ Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚Ρ‹ Π² Π±Π°ΠΊΠ΅Ρ‚Π΅ S3

Запуск ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ

Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Tracking-сСрвСр, ΠΌΠΎΠΆΠ½ΠΎ Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒ ΠΎΠ±ΡƒΡ‡Π°Ρ‚ΡŒ ΠΌΠΎΠ΄Π΅Π»ΠΈ.

Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΌΡ‹ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠ΅ΠΉ wine ΠΈΠ· ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° MLflow Π² Sklearn.

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

Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ возмоТностСй Spark с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ MLflow
Π˜Ρ‚Π΅Ρ€Π°Ρ†ΠΈΠΈ wine

БСрвСрная Ρ‡Π°ΡΡ‚ΡŒ для ΠΌΠΎΠ΄Π΅Π»ΠΈ

Tracking-сСрвСр MLflow, Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½Ρ‹ΠΉ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ β€œmlflow server”, ΠΈΠΌΠ΅Π΅Ρ‚ REST API для отслСТивания запусков ΠΈ записи Π΄Π°Π½Π½Ρ‹Ρ… Π² Π»ΠΎΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ Ρ„Π°ΠΉΠ»ΠΎΠ²ΡƒΡŽ систСму. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ адрСс tracking-сСрвСра с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ срСды Β«MLFLOW_TRACKING_URIΒ» ΠΈ tracking API MLflow автоматичСски свяТСтся с tracking-сСрвСром ΠΏΠΎ этому адрСсу, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ/ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ запускС, ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ Π»ΠΎΠ³ΠΎΠ² ΠΈ Ρ‚.Π΄.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: Docs// Running a tracking server

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ модСль сСрвСром Π½Π°ΠΌ понадобится Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½Ρ‹ΠΉ tracking-сСрвСр (см. интСрфСйс запуска) ΠΈ Run ID ΠΌΠΎΠ΄Π΅Π»ΠΈ.

Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ возмоТностСй Spark с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ MLflow
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 serve, Π½Π°ΠΌ понадобится доступ ΠΊ Tracking UI, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ ΠΌΠΎΠ΄Π΅Π»ΠΈ просто ΡƒΠΊΠ°Π·Π°Π² --run_id.

Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ модСль связываСтся с Tracking-сСрвСром, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π½ΠΎΠ²ΡƒΡŽ ΠΊΠΎΠ½Π΅Ρ‡Π½ΡƒΡŽ Ρ‚ΠΎΡ‡ΠΊΡƒ ΠΌΠΎΠ΄Π΅Π»ΠΈ.

# 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-сСрвСр достаточно ΠΌΠΎΡ‰Π½Ρ‹ΠΉ для обслуТивания ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, ΠΈΡ… обучСния ΠΈ использования Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»Π°serve (источник: mlflow // docs // models # local), ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Spark (batch ΠΈΠ»ΠΈ streaming) – Π΅Ρ‰Π΅ Π±ΠΎΠ»Π΅Π΅ ΠΌΠΎΡ‰Π½ΠΎΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π·Π° счСт распрСдСлСнности.

ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²ΡŒΡ‚Π΅, Ρ‡Ρ‚ΠΎ Π²Ρ‹ просто ΠΏΡ€ΠΎΠ²Π΅Π»ΠΈ ΠΎΠ±ΡƒΡ‡Π΅Π½ΠΈΠ΅ Π² ΠΎΡ„Ρ„Π»Π°ΠΉΠ½Π΅, Π° ΠΏΠΎΡ‚ΠΎΠΌ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠ»ΠΈ Π²Ρ‹Ρ…ΠΎΠ΄Π½ΡƒΡŽ модСль ΠΊΠΎ всСм вашим Π΄Π°Π½Π½Ρ‹ΠΌ. ИмСнно Ρ‚ΡƒΡ‚ Spark ΠΈ MLflow ΠΏΠΎΠΊΠ°ΠΆΡƒΡ‚ сСбя с Π»ΡƒΡ‡ΡˆΠ΅ΠΉ стороны.

УстанавливаСм PySpark + Jupyter + Spark

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: Get started PySpark β€” Jupyter

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ, ΠΊΠ°ΠΊ ΠΌΡ‹ примСняСм ΠΌΠΎΠ΄Π΅Π»ΠΈ MLflow ΠΊ Π΄Π°Ρ‚Π°Ρ„Ρ€Π΅ΠΉΠΌΠ°ΠΌ Spark, Π½ΡƒΠΆΠ½ΠΎ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ΡΠΎΠ²ΠΌΠ΅ΡΡ‚Π½ΡƒΡŽ Ρ€Π°Π±ΠΎΡ‚Ρƒ Jupyter notebooks с PySpark.

НачнитС с установки послСднСй ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½ΠΎΠΉ вСрсии 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Μ€

УстановитС 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, ΠΌΡ‹ смоТСм Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ наши notebook-ΠΈ Π² ΠΆΠ΅Π»Π°Π΅ΠΌΠΎΠΉ ΠΏΠ°ΠΏΠΊΠ΅.

ЗапускаСм Jupyter ΠΈΠ· PySpark

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ смогли Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ Jupiter Π² качСствС Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€Π° PySpark, Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ Jupyter notebook Π² контСкстС 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

Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ возмоТностСй Spark с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ MLflow

Как Π±Ρ‹Π»ΠΎ сказано Π²Ρ‹ΡˆΠ΅, 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)

Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ возмоТностСй Spark с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ MLflow
PySpark – Π’Ρ‹Π²ΠΎΠ΄ ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·Π° качСства Π²ΠΈΠ½Π°

Π”ΠΎ этого ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° ΠΌΡ‹ Π³ΠΎΠ²ΠΎΡ€ΠΈΠ»ΠΈ ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ PySpark с MLflow, запуская ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ качСства Π²ΠΈΠ½Π° Π½Π° всСм Π½Π°Π±ΠΎΡ€Π΅ Π΄Π°Π½Π½Ρ‹Ρ… wine. Но Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ, Ссли Π½ΡƒΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ Python MLflow ΠΈΠ· Scala Spark?

ΠœΡ‹ протСстировали ΠΈ это, Ρ€Π°Π·Π΄Π΅Π»ΠΈΠ² контСкст Spark ΠΌΠ΅ΠΆΠ΄Ρƒ Scala ΠΈ Python. Π’ΠΎ Π΅ΡΡ‚ΡŒ ΠΌΡ‹ зарСгистрировали MLflow UDF Π² Python, ΠΈ использовали Π΅Π³ΠΎ ΠΈΠ· Scala (Π΄Π°, Π²ΠΎΠ·ΠΎΠΆΠ½ΠΎ, Π½Π΅ Π»ΡƒΡ‡ΡˆΠ΅Π΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, Π½ΠΎ Ρ‡Ρ‚ΠΎ ΠΈΠΌΠ΅Π΅ΠΌ).

Scala Spark + MLflow

Для этого ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΌΡ‹ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Toree Kernel Π² ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Jupiter.

УстанавливаСм 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
```

Как Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· ΠΏΡ€ΠΈΠΊΡ€Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ³ΠΎ notebook-Π°, 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 находится Π² Alpha-вСрсии, ΠΎΠ½Π° выглядит довольно ΠΌΠ½ΠΎΠ³ΠΎΠΎΠ±Π΅Ρ‰Π°ΡŽΡ‰Π΅. Одна лишь Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ нСсколько Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠΎΠ² машинного обучСния ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… ΠΈΠ· ΠΎΠ΄Π½ΠΎΠΉ ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠΉ Ρ‚ΠΎΡ‡ΠΊΠΈ Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ систСмы Π½Π° Π½ΠΎΠ²Ρ‹ΠΉ ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ.

К Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅, MLflow сблиТаСт Data-ΠΈΠ½ΠΆΠ΅Π½Π΅Ρ€ΠΎΠ² ΠΈ спСциалистов ΠΏΠΎ Data Science, прокладывая ΠΌΠ΅ΠΆΠ΄Ρƒ Π½ΠΈΠΌΠΈ ΠΎΠ±Ρ‰ΠΈΠΉ слой.

ПослС этого исслСдования MLflow, ΠΌΡ‹ ΡƒΠ²Π΅Ρ€Π΅Π½Ρ‹, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠΉΠ΄Π΅ΠΌ дальшС ΠΈ Π±ΡƒΠ΄Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π΅ для Π½Π°ΡˆΠΈΡ… ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½ΠΎΠ² Spark ΠΈ Π² Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… систСмах.

Π‘Ρ‹Π»ΠΎ Π±Ρ‹ Π½Π΅ΠΏΠ»ΠΎΡ…ΠΎ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ с Π±Π°Π·ΠΎΠΉ Π΄Π°Π½Π½Ρ‹Ρ…, вмСсто Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠΉ систСмы. Π’Π°ΠΊ ΠΌΡ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ нСсколько ΠΊΠΎΠ½Π΅Ρ‡Π½Ρ‹Ρ… Ρ‚ΠΎΡ‡Π΅ΠΊ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ΄Π½ΠΎ ΠΈ Ρ‚ΠΎ ΠΆΠ΅ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅. НапримСр, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ нСсколько экзСмпляров Presto ΠΈ Athena с ΠΎΠ΄Π½ΠΈΠΌ ΠΈ Ρ‚Π΅ΠΌ ΠΆΠ΅ Glue metastore.

Подводя ΠΈΡ‚ΠΎΠ³ΠΈ, хочСтся ΡΠΊΠ°Π·Π°Ρ‚ΡŒ спасибо сообщСству MLFlow Π·Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚Π΅ Π½Π°ΡˆΡƒ Ρ€Π°Π±ΠΎΡ‚Ρƒ с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ интСрСснСС.

Если Π²Ρ‹ ΠΈΠ³Ρ€Π°Π΅Ρ‚Π΅ΡΡŒ с MLflow, Π½Π΅ ΡΡ‚Π΅ΡΠ½ΡΠΉΡ‚Π΅ΡΡŒ ΠΏΠΈΡΠ°Ρ‚ΡŒ Π½Π°ΠΌ ΠΈ Ρ€Π°ΡΡΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ, ΠΊΠ°ΠΊ Π²Ρ‹ Π΅Π³ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅, ΠΈ Ρ‚Π΅ΠΌ Π±ΠΎΠ»Π΅Π΅, Ссли ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ Π΅Π³ΠΎ Π½Π° ΠΏΡ€ΠΎΠ΄Π°ΠΊΡˆΠ΅Π½Π΅.

Π£Π·Π½Π°Ρ‚ΡŒ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΎ курсах:
Machine Learning. Π‘Π°Π·ΠΎΠ²Ρ‹ΠΉ курс
Machine Learning. ΠŸΡ€ΠΎΠ΄Π²ΠΈΠ½ΡƒΡ‚Ρ‹ΠΉ курс

Π§ΠΈΡ‚Π°Ρ‚ΡŒ Π΅Ρ‰Ρ‘:

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ