āĻšā§āĻ¯āĻžāĻ˛ā§, āĻāĻžāĻŦā§āĻ°ā§āĻāĻ¸ā§āĻā§āĻ° āĻŦāĻžāĻ¸āĻŋāĻ¨ā§āĻĻāĻžāĻ°āĻžāĨ¤ āĻāĻŽāĻ°āĻž āĻāĻ¤āĻŋāĻŽāĻ§ā§āĻ¯ā§āĻ āĻ˛āĻŋāĻā§āĻāĻŋ, āĻāĻ āĻŽāĻžāĻ¸ā§ OTUS āĻĻā§āĻāĻŋ āĻŽā§āĻļāĻŋāĻ¨ āĻ˛āĻžāĻ°ā§āĻ¨āĻŋāĻ āĻā§āĻ°ā§āĻ¸ āĻāĻžāĻ˛ā§ āĻāĻ°āĻā§, āĻ¯āĻĨāĻž
āĻāĻ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§āĻāĻŋāĻ° āĻāĻĻā§āĻĻā§āĻļā§āĻ¯ āĻšāĻ˛ āĻāĻŽāĻžāĻĻā§āĻ° āĻĒā§āĻ°āĻĨāĻŽ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°ā§āĻ° āĻ
āĻāĻŋāĻā§āĻāĻ¤āĻž āĻ¸āĻŽā§āĻĒāĻ°ā§āĻā§ āĻāĻĨāĻž āĻŦāĻ˛āĻž
āĻāĻŽāĻ°āĻž āĻĒāĻ°ā§āĻ¯āĻžāĻ˛ā§āĻāĻ¨āĻž āĻļā§āĻ°ā§ āĻāĻ°āĻŦ
āĻĒā§āĻ°āĻ¸āĻā§āĻ
āĻāĻŽāĻžāĻ°āĻž āĻāĻāĻŋ
āĻāĻŽāĻāĻ˛āĻĢā§āĻ˛ā§
MLflow āĻāĻ° āĻŽā§āĻ˛ āĻ˛āĻā§āĻˇā§āĻ¯ āĻšāĻ˛ āĻŽā§āĻļāĻŋāĻ¨ āĻ˛āĻžāĻ°ā§āĻ¨āĻŋāĻ āĻāĻ° āĻāĻĒāĻ°ā§ āĻāĻāĻāĻŋ āĻ
āĻ¤āĻŋāĻ°āĻŋāĻā§āĻ¤ āĻ¸ā§āĻ¤āĻ° āĻĒā§āĻ°āĻĻāĻžāĻ¨ āĻāĻ°āĻž āĻ¯āĻž āĻĄā§āĻāĻž āĻŦāĻŋāĻā§āĻāĻžāĻ¨ā§āĻĻā§āĻ° āĻĒā§āĻ°āĻžāĻ¯āĻŧ āĻ¯ā§āĻā§āĻ¨ā§ āĻŽā§āĻļāĻŋāĻ¨ āĻ˛āĻžāĻ°ā§āĻ¨āĻŋāĻ āĻ˛āĻžāĻāĻŦā§āĻ°ā§āĻ°āĻŋāĻ° āĻ¸āĻžāĻĨā§ āĻāĻžāĻ āĻāĻ°āĻ¤ā§ āĻĻā§āĻ¯āĻŧ (
MLflow āĻ¤āĻŋāĻ¨āĻāĻŋ āĻāĻĒāĻžāĻĻāĻžāĻ¨ āĻĒā§āĻ°āĻĻāĻžāĻ¨ āĻāĻ°ā§:
- āĻ āĻ¨ā§āĻ¸āĻ°āĻŖāĻāĻ°āĻŖ - āĻ°ā§āĻāĻ°ā§āĻĄāĻŋāĻ āĻāĻŦāĻ āĻĒāĻ°ā§āĻā§āĻˇāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻ āĻ¨ā§āĻ°ā§āĻ§: āĻā§āĻĄ, āĻĄā§āĻāĻž, āĻāĻ¨āĻĢāĻŋāĻāĻžāĻ°ā§āĻļāĻ¨ āĻāĻŦāĻ āĻĢāĻ˛āĻžāĻĢāĻ˛āĨ¤ āĻāĻāĻāĻŋ āĻŽāĻĄā§āĻ˛ āĻ¤ā§āĻ°āĻŋāĻ° āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻĒāĻ°ā§āĻ¯āĻŦā§āĻā§āĻˇāĻŖ āĻāĻ°āĻž āĻā§āĻŦāĻ āĻā§āĻ°ā§āĻ¤ā§āĻŦāĻĒā§āĻ°ā§āĻŖāĨ¤
- āĻĒā§āĻ°āĻāĻ˛ā§āĻĒ - āĻ¯ā§ āĻā§āĻ¨ā§ āĻĒā§āĻ˛ā§āĻ¯āĻžāĻāĻĢāĻ°ā§āĻŽā§ āĻāĻžāĻ˛āĻžāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻĒā§āĻ¯āĻžāĻā§āĻāĻŋāĻ āĻŦāĻŋāĻ¨ā§āĻ¯āĻžāĻ¸ (āĻ¯ā§āĻŽāĻ¨
SageMaker ) - āĻŽāĻĄā§āĻ˛ - āĻŦāĻŋāĻāĻŋāĻ¨ā§āĻ¨ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨āĻžāĻ° āĻ¸āĻ°āĻā§āĻāĻžāĻŽāĻā§āĻ˛āĻŋāĻ¤ā§ āĻŽāĻĄā§āĻ˛ āĻāĻŽāĻž āĻĻā§āĻāĻ¯āĻŧāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖ āĻŦāĻŋāĻ¨ā§āĻ¯āĻžāĻ¸āĨ¤
āĻāĻŽāĻāĻ˛āĻĢā§āĻ˛ā§ (āĻ˛ā§āĻāĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻāĻ˛āĻĢāĻžāĻ¤ā§) āĻāĻāĻāĻŋ āĻāĻĒā§āĻ¨ āĻ¸ā§āĻ°ā§āĻ¸ āĻĒā§āĻ˛ā§āĻ¯āĻžāĻāĻĢāĻ°ā§āĻŽ āĻ¯āĻž āĻāĻĒāĻ¨āĻžāĻā§ āĻĒāĻ°ā§āĻā§āĻˇāĻž, āĻĒā§āĻ¨āĻāĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻŦāĻ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨āĻž āĻ¸āĻš āĻŽā§āĻļāĻŋāĻ¨ āĻ˛āĻžāĻ°ā§āĻ¨āĻŋāĻ āĻā§āĻŦāĻ¨āĻāĻā§āĻ° āĻĒāĻ°āĻŋāĻāĻžāĻ˛āĻ¨āĻž āĻāĻ°āĻ¤ā§ āĻĻā§āĻ¯āĻŧāĨ¤
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
```
āĻĻā§āĻ°āĻˇā§āĻāĻŦā§āĻ¯: UDF-āĻāĻ° āĻŽāĻ¤ā§ āĻŽāĻĄā§āĻ˛ āĻāĻžāĻ˛āĻžāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻāĻŽāĻ°āĻž PyArrow āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻŋāĨ¤ PyArrow āĻāĻŦāĻ Numpy-āĻāĻ° āĻ¸āĻāĻ¸ā§āĻāĻ°āĻŖāĻā§āĻ˛āĻŋāĻā§ āĻ āĻŋāĻ āĻāĻ°āĻž āĻĻāĻ°āĻāĻžāĻ° āĻāĻžāĻ°āĻŖ āĻĒāĻ°āĻŦāĻ°ā§āĻ¤ā§ āĻ¸āĻāĻ¸ā§āĻāĻ°āĻŖāĻā§āĻ˛āĻŋ āĻāĻā§ āĻ āĻĒāĻ°ā§āĻ° āĻ¸āĻžāĻĨā§ āĻŦāĻŋāĻ°ā§āĻ§āĻĒā§āĻ°ā§āĻŖāĨ¤
āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ UI āĻāĻžāĻ˛ā§ āĻāĻ°ā§āĻ¨
MLflow āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻāĻŽāĻžāĻĻā§āĻ° āĻĒāĻžāĻāĻĨāĻ¨ āĻāĻŦāĻ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻĒāĻ°ā§āĻā§āĻˇāĻžāĻā§āĻ˛āĻŋ āĻ˛āĻ āĻāĻŦāĻ āĻ
āĻ¨ā§āĻ¸āĻ¨ā§āĻ§āĻžāĻ¨ āĻāĻ°āĻ¤ā§ āĻĻā§āĻ¯āĻŧ
# 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 āĻāĻŦāĻ āĻŽāĻĄā§āĻ˛ āĻā§āĻ˛āĻžāĻ¯āĻŧā§āĻ¨ā§āĻā§āĻ° āĻ āĻŦāĻļā§āĻ¯āĻ āĻāĻ°ā§āĻāĻŋāĻĢā§āĻ¯āĻžāĻā§āĻ āĻ āĻŦāĻ¸ā§āĻĨāĻžāĻ¨ā§ āĻ ā§āĻ¯āĻžāĻā§āĻ¸ā§āĻ¸ āĻĨāĻžāĻāĻ¤ā§ āĻšāĻŦā§āĨ¤ āĻ āĻ°ā§āĻĨāĻžā§, āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ UI āĻāĻāĻāĻŋ EC2 āĻĻā§āĻˇā§āĻāĻžāĻ¨ā§āĻ¤ā§ āĻĨāĻžāĻāĻž āĻ¨āĻŋāĻ°ā§āĻŦāĻŋāĻļā§āĻˇā§, āĻ¸ā§āĻĨāĻžāĻ¨ā§āĻ¯āĻŧāĻāĻžāĻŦā§ MLflow āĻāĻžāĻ˛āĻžāĻ¨ā§āĻ° āĻ¸āĻŽāĻ¯āĻŧ, āĻāĻ°ā§āĻāĻŋāĻĢā§āĻ¯āĻžāĻā§āĻ āĻŽāĻĄā§āĻ˛ āĻ˛ā§āĻāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻŽā§āĻļāĻŋāĻ¨ā§āĻ° āĻ āĻŦāĻļā§āĻ¯āĻ S3-āĻ āĻ¸āĻ°āĻžāĻ¸āĻ°āĻŋ āĻ ā§āĻ¯āĻžāĻā§āĻ¸ā§āĻ¸ āĻĨāĻžāĻāĻ¤ā§ āĻšāĻŦā§āĨ¤
āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ UI āĻāĻāĻāĻŋ S3 āĻŦāĻžāĻ˛āĻ¤āĻŋāĻ¤ā§ āĻļāĻŋāĻ˛ā§āĻĒāĻāĻ°ā§āĻŽ āĻ¸āĻā§āĻāĻ¯āĻŧ āĻāĻ°ā§
āĻāĻ˛āĻŽāĻžāĻ¨ āĻŽāĻĄā§āĻ˛
āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ° āĻāĻžāĻ˛ā§ āĻšāĻāĻ¯āĻŧāĻžāĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻžāĻĨā§ āĻāĻĒāĻ¨āĻŋ āĻŽāĻĄā§āĻ˛āĻĻā§āĻ° āĻĒā§āĻ°āĻļāĻŋāĻā§āĻˇāĻŖ āĻļā§āĻ°ā§ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨āĨ¤
āĻāĻāĻāĻŋ āĻāĻĻāĻžāĻšāĻ°āĻŖ āĻšāĻŋāĻ¸āĻžāĻŦā§, āĻāĻŽāĻ°āĻž 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 āĻāĻĒāĻ¨āĻžāĻā§ āĻŽāĻĄā§āĻ˛ āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻāĻžāĻ°, āĻŽā§āĻā§āĻ°āĻŋāĻā§āĻ¸ āĻāĻŦāĻ āĻāĻ°ā§āĻāĻŋāĻĢā§āĻ¯āĻžāĻā§āĻāĻā§āĻ˛āĻŋ āĻ˛āĻ āĻāĻ°āĻžāĻ° āĻ āĻ¨ā§āĻŽāĻ¤āĻŋ āĻĻā§āĻ¯āĻŧ āĻ¯āĻžāĻ¤ā§ āĻāĻĒāĻ¨āĻŋ āĻā§āĻ°ā§āĻ¯āĻžāĻ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨ āĻāĻŋāĻāĻžāĻŦā§ āĻ¤āĻžāĻ°āĻž āĻĒā§āĻ¨āĻ°āĻžāĻŦā§āĻ¤ā§āĻ¤āĻŋāĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻŦāĻŋāĻŦāĻ°ā§āĻ¤āĻŋāĻ¤ āĻšāĻ¯āĻŧāĨ¤ āĻāĻ āĻŦā§āĻļāĻŋāĻˇā§āĻā§āĻ¯āĻāĻŋ āĻ āĻ¤ā§āĻ¯āĻ¨ā§āĻ¤ āĻāĻžāĻ°ā§āĻ¯āĻāĻ° āĻāĻžāĻ°āĻŖ āĻāĻāĻāĻžāĻŦā§ āĻāĻŽāĻ°āĻž āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°ā§āĻ° āĻ¸āĻžāĻĨā§ āĻ¯ā§āĻāĻžāĻ¯ā§āĻ āĻāĻ°ā§ āĻŦāĻž āĻāĻŽāĻŋāĻā§āĻ° āĻāĻŋāĻ āĻšā§āĻ¯āĻžāĻļ āĻ˛āĻ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻā§āĻ¨ āĻā§āĻĄāĻāĻŋ āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ā§āĻ¯āĻŧ āĻĒā§āĻ¨āĻ°āĻžāĻŦā§āĻ¤ā§āĻ¤āĻŋ āĻ¸āĻŽā§āĻĒāĻžāĻĻāĻ¨ āĻāĻ°ā§āĻā§ āĻ¤āĻž āĻŦā§āĻāĻžāĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻāĻŽāĻ°āĻž āĻ¸ā§āĻ°āĻž āĻŽāĻĄā§āĻ˛āĻāĻŋ āĻĒā§āĻ¨āĻ°ā§āĻ¤ā§āĻĒāĻžāĻĻāĻ¨ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°āĻŋāĨ¤
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 āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°, "mlflow āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°" āĻāĻŽāĻžāĻ¨ā§āĻĄ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻāĻžāĻ˛ā§ āĻšāĻ¯āĻŧā§āĻā§, āĻ¸ā§āĻĨāĻžāĻ¨ā§āĻ¯āĻŧ āĻĢāĻžāĻāĻ˛ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽā§ āĻ°āĻžāĻ¨ āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻāĻŦāĻ āĻĄā§āĻāĻž āĻ˛ā§āĻāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ REST API āĻ°āĻ¯āĻŧā§āĻā§āĨ¤ āĻāĻĒāĻ¨āĻŋ āĻāĻ¨āĻāĻžāĻ¯āĻŧāĻ°āĻ¨āĻŽā§āĻ¨ā§āĻ āĻā§āĻ°āĻŋāĻ¯āĻŧā§āĻŦāĻ˛ "MLFLOW_TRACKING_URI" āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°ā§āĻ° āĻ āĻŋāĻāĻžāĻ¨āĻž āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨ āĻāĻŦāĻ MLflow āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ API āĻ¸ā§āĻŦāĻ¯āĻŧāĻāĻā§āĻ°āĻŋāĻ¯āĻŧāĻāĻžāĻŦā§ āĻ˛āĻā§āĻā§āĻ° āĻ¤āĻĨā§āĻ¯, āĻ˛āĻ āĻŽā§āĻā§āĻ°āĻŋāĻā§āĻ¸ āĻāĻ¤ā§āĻ¯āĻžāĻĻāĻŋ āĻ¤ā§āĻ°āĻŋ/āĻĒā§āĻ°āĻžāĻĒā§āĻ¤ āĻāĻ°āĻ¤ā§ āĻāĻ āĻ āĻŋāĻāĻžāĻ¨āĻžāĻ¯āĻŧ āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°ā§āĻ° āĻ¸āĻžāĻĨā§ āĻ¯ā§āĻāĻžāĻ¯ā§āĻ āĻāĻ°āĻŦā§āĨ¤
āĻāĻ¤ā§āĻ¸:
āĻĄāĻā§āĻ¸// āĻāĻāĻāĻŋ āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ° āĻāĻžāĻ˛āĻžāĻ¨ā§
āĻāĻāĻāĻŋ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°ā§āĻ° āĻ¸āĻžāĻĨā§ āĻŽāĻĄā§āĻ˛ āĻĒā§āĻ°āĻĻāĻžāĻ¨ āĻāĻ°āĻ¤ā§, āĻāĻŽāĻžāĻĻā§āĻ° āĻāĻāĻāĻŋ āĻāĻ˛āĻŽāĻžāĻ¨ āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ° (āĻ˛āĻā§āĻ āĻāĻ¨ā§āĻāĻžāĻ°āĻĢā§āĻ¸ āĻĻā§āĻā§āĻ¨) āĻāĻŦāĻ āĻŽāĻĄā§āĻ˛āĻāĻŋāĻ° āĻ°āĻžāĻ¨ āĻāĻāĻĄāĻŋ āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ā§ˇ
āĻāĻāĻĄāĻŋ āĻāĻžāĻ˛āĻžāĻ¨
# 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
āĻāĻŽāĻāĻ˛āĻĢā§āĻ˛ā§ āĻ¸āĻžāĻ°ā§āĻ āĻāĻžāĻ°ā§āĻ¯āĻāĻžāĻ°āĻŋāĻ¤āĻž āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻŽāĻĄā§āĻ˛āĻā§āĻ˛āĻŋ āĻĒāĻ°āĻŋāĻŦā§āĻļāĻ¨ āĻāĻ°āĻ¤ā§, āĻŽāĻĄā§āĻ˛ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻā§ āĻ¤āĻĨā§āĻ¯ āĻĒāĻžāĻāĻ¯āĻŧāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻŽāĻžāĻĻā§āĻ° āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ 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]}
āĻ¸ā§āĻĒāĻžāĻ°ā§āĻ āĻĨā§āĻā§ āĻŽāĻĄā§āĻ˛ āĻāĻ˛āĻŽāĻžāĻ¨
āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°āĻāĻŋ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦ āĻ¸āĻŽāĻ¯āĻŧā§ āĻŽāĻĄā§āĻ˛ āĻĒāĻ°āĻŋāĻŦā§āĻļāĻ¨ āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻ¯āĻĨā§āĻˇā§āĻ āĻļāĻā§āĻ¤āĻŋāĻļāĻžāĻ˛ā§, āĻ¤āĻžāĻĻā§āĻ° āĻĒā§āĻ°āĻļāĻŋāĻā§āĻˇāĻŖ āĻāĻŦāĻ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ° āĻāĻžāĻ°ā§āĻ¯āĻāĻžāĻ°āĻŋāĻ¤āĻž āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻ¯āĻĨā§āĻˇā§āĻ āĻļāĻā§āĻ¤āĻŋāĻļāĻžāĻ˛ā§ āĻšāĻāĻ¯āĻŧāĻž āĻ¸āĻ¤ā§āĻ¤ā§āĻŦā§āĻ (āĻ¸ā§āĻ¤ā§āĻ°:
āĻāĻ˛ā§āĻĒāĻ¨āĻž āĻāĻ°ā§āĻ¨ āĻ¯ā§ āĻāĻĒāĻ¨āĻŋ āĻā§āĻŦāĻ˛ āĻ āĻĢāĻ˛āĻžāĻāĻ¨ā§ āĻĒā§āĻ°āĻļāĻŋāĻā§āĻˇāĻŖāĻāĻŋ āĻāĻ°ā§āĻā§āĻ¨ āĻāĻŦāĻ āĻ¤āĻžāĻ°āĻĒāĻ° āĻāĻĒāĻ¨āĻžāĻ° āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻĄā§āĻāĻžāĻ¤ā§ āĻāĻāĻāĻĒā§āĻ āĻŽāĻĄā§āĻ˛ āĻĒā§āĻ°āĻ¯āĻŧā§āĻ āĻāĻ°ā§āĻā§āĻ¨āĨ¤ āĻāĻāĻžāĻ¨ā§āĻ āĻ¸ā§āĻĒāĻžāĻ°ā§āĻ āĻāĻŦāĻ āĻāĻŽāĻāĻ˛āĻĢā§āĻ˛ā§ āĻā§āĻŦāĻ˛āĻā§āĻŦāĻ˛ āĻāĻ°ā§āĨ¤
PySpark + Jupyter + Spark āĻāĻ¨āĻ¸ā§āĻāĻ˛ āĻāĻ°ā§āĻ¨
āĻāĻ¤ā§āĻ¸:
āĻļā§āĻ°ā§ āĻāĻ°ā§āĻ¨ PySpark - āĻā§āĻĒāĻŋāĻāĻžāĻ°
āĻāĻŽāĻ°āĻž āĻā§āĻāĻžāĻŦā§ āĻ¸ā§āĻĒāĻžāĻ°ā§āĻ āĻĄā§āĻāĻžāĻĢā§āĻ°ā§āĻŽā§ MLflow āĻŽāĻĄā§āĻ˛ āĻĒā§āĻ°āĻ¯āĻŧā§āĻ āĻāĻ°āĻŋ āĻ¤āĻž āĻĻā§āĻāĻžāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯, 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
, āĻāĻŽāĻ°āĻž āĻāĻŽāĻžāĻĻā§āĻ° āĻ¨ā§āĻāĻŦā§āĻ āĻĒāĻāĻ¨ā§āĻĻāĻ¸āĻ āĻĢā§āĻ˛ā§āĻĄāĻžāĻ°ā§ āĻ¸āĻāĻ°āĻā§āĻˇāĻŖ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨.
PySpark āĻĨā§āĻā§ Jupyter āĻ˛āĻā§āĻ āĻšāĻā§āĻā§
āĻ¯ā§āĻšā§āĻ¤ā§ āĻāĻŽāĻ°āĻž āĻā§āĻĒāĻŋāĻāĻžāĻ°āĻā§ āĻĒāĻžāĻāĻ¸ā§āĻĒāĻžāĻ°ā§āĻ āĻĄā§āĻ°āĻžāĻāĻāĻžāĻ° āĻšāĻŋāĻ¸āĻžāĻŦā§ āĻāĻ¨āĻĢāĻŋāĻāĻžāĻ° āĻāĻ°āĻ¤ā§ āĻ¸āĻā§āĻˇāĻŽ āĻšāĻ¯āĻŧā§āĻāĻŋ, āĻ¤āĻžāĻ āĻāĻŽāĻ°āĻž āĻāĻāĻ¨ āĻĒāĻžāĻāĻ¸ā§āĻĒāĻžāĻ°ā§āĻā§āĻ° āĻĒā§āĻ°āĻ¸āĻā§āĻā§ āĻā§āĻĒāĻŋāĻāĻžāĻ° āĻ¨ā§āĻāĻŦā§āĻ āĻāĻžāĻ˛āĻžāĻ¤ā§ āĻĒāĻžāĻ°āĻŋāĨ¤
(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 - āĻāĻāĻāĻĒā§āĻāĻŋāĻ āĻāĻ¯āĻŧāĻžāĻāĻ¨ āĻŽāĻžāĻ¨ā§āĻ° āĻĒā§āĻ°ā§āĻŦāĻžāĻāĻžāĻ¸
āĻāĻ āĻŽā§āĻšā§āĻ°ā§āĻ¤ā§, āĻāĻŽāĻ°āĻž MLflow āĻāĻ° āĻ¸āĻžāĻĨā§ PySpark āĻāĻŋāĻāĻžāĻŦā§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻ¤ā§ āĻšāĻ¯āĻŧ āĻ¸ā§ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻā§ āĻāĻĨāĻž āĻŦāĻ˛ā§āĻāĻŋ, āĻĒā§āĻ°ā§ āĻāĻ¯āĻŧāĻžāĻāĻ¨ āĻĄā§āĻāĻžāĻ¸ā§āĻā§ āĻāĻ¯āĻŧāĻžāĻāĻ¨ āĻŽāĻžāĻ¨ā§āĻ° āĻĒā§āĻ°ā§āĻŦāĻžāĻāĻžāĻ¸ āĻāĻ˛āĻā§āĨ¤ āĻāĻŋāĻ¨ā§āĻ¤ā§ āĻ¯āĻĻāĻŋ āĻāĻĒāĻ¨āĻžāĻā§ āĻ¸ā§āĻāĻžāĻ˛āĻž āĻ¸ā§āĻĒāĻžāĻ°ā§āĻ āĻĨā§āĻā§ āĻĒāĻžāĻāĻĨāĻ¨ āĻāĻŽāĻāĻ˛āĻĢā§āĻ˛ā§ āĻŽāĻĄāĻŋāĻāĻ˛ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻ¤ā§ āĻšāĻ¯āĻŧ?
āĻ¸ā§āĻāĻžāĻ˛āĻž āĻāĻŦāĻ āĻĒāĻžāĻāĻĨāĻ¨ā§āĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻ¸ā§āĻĒāĻžāĻ°ā§āĻ āĻĒā§āĻ°āĻ¸āĻā§āĻ āĻŦāĻŋāĻāĻā§āĻ¤ āĻāĻ°ā§ āĻāĻŽāĻ°āĻž āĻāĻāĻŋāĻ āĻĒāĻ°ā§āĻā§āĻˇāĻž āĻāĻ°ā§āĻāĻŋāĨ¤ āĻ āĻ°ā§āĻĨāĻžā§, āĻāĻŽāĻ°āĻž āĻĒāĻžāĻāĻĨāĻ¨ā§ āĻāĻŽāĻāĻ˛āĻĢā§āĻ˛ā§ āĻāĻāĻĄāĻŋāĻāĻĢ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§āĻŋāĻ¤ āĻāĻ°ā§āĻāĻŋ āĻāĻŦāĻ āĻāĻāĻŋ āĻ¸ā§āĻāĻžāĻ˛āĻž āĻĨā§āĻā§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§āĻāĻŋ (āĻšā§āĻ¯āĻžāĻ, āĻ¸āĻŽā§āĻāĻŦāĻ¤ āĻ¸ā§āĻ°āĻž āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ āĻ¨āĻ¯āĻŧ, āĻ¤āĻŦā§ āĻāĻŽāĻžāĻĻā§āĻ° āĻāĻžāĻā§ āĻ¯āĻž āĻāĻā§)āĨ¤
āĻ¸ā§āĻāĻžāĻ˛āĻž āĻ¸ā§āĻĒāĻžāĻ°ā§āĻ + āĻāĻŽāĻāĻ˛āĻĢā§āĻ˛ā§
āĻāĻ āĻāĻĻāĻžāĻšāĻ°āĻŖā§āĻ° āĻāĻ¨ā§āĻ¯ āĻāĻŽāĻ°āĻž āĻ¯ā§āĻ āĻāĻ°āĻŦ
āĻ¸ā§āĻĒāĻžāĻ°ā§āĻ + āĻāĻ°āĻŋ + āĻā§āĻĒāĻŋāĻāĻžāĻ° āĻāĻ¨āĻ¸ā§āĻāĻ˛ āĻāĻ°ā§āĻ¨
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
```
āĻāĻĒāĻ¨āĻŋ āĻ¸āĻāĻ¯ā§āĻā§āĻ¤ āĻ¨ā§āĻāĻŦā§āĻ āĻĨā§āĻā§ āĻĻā§āĻāĻ¤ā§ āĻĒāĻžāĻā§āĻā§āĻ¨, āĻāĻāĻĄāĻŋāĻāĻĢ āĻ¸ā§āĻĒāĻžāĻ°ā§āĻ āĻāĻŦāĻ āĻĒāĻžāĻāĻ¸ā§āĻĒāĻžāĻ°ā§āĻā§āĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻāĻžāĻ āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻā§āĨ¤ āĻāĻŽāĻ°āĻž āĻāĻļāĻž āĻāĻ°āĻŋ āĻāĻ āĻ āĻāĻļāĻāĻŋ āĻ¤āĻžāĻĻā§āĻ° āĻāĻ¨ā§āĻ¯ āĻāĻĒāĻ¯ā§āĻā§ āĻšāĻŦā§ āĻ¯āĻžāĻ°āĻž āĻ¸ā§āĻāĻžāĻ˛āĻž āĻĒāĻāĻ¨ā§āĻĻ āĻāĻ°ā§āĻ¨ āĻāĻŦāĻ āĻā§āĻĒāĻžāĻĻāĻ¨ā§ āĻŽā§āĻļāĻŋāĻ¨ āĻ˛āĻžāĻ°ā§āĻ¨āĻŋāĻ āĻŽāĻĄā§āĻ˛ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻāĻ°āĻ¤ā§ āĻāĻžāĻ¨āĨ¤
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 āĻ¸āĻŽā§āĻĒā§āĻ°āĻĻāĻžāĻ¯āĻŧāĻā§ āĻ§āĻ¨ā§āĻ¯āĻŦāĻžāĻĻ āĻāĻžāĻ¨āĻžāĻ¤ā§ āĻāĻžāĻāĨ¤
āĻāĻĒāĻ¨āĻŋ āĻ¯āĻĻāĻŋ MLflow āĻ¨āĻŋāĻ¯āĻŧā§ āĻā§āĻ˛āĻ¤ā§ āĻĨāĻžāĻā§āĻ¨, āĻ¤āĻžāĻšāĻ˛ā§ āĻāĻŽāĻžāĻĻā§āĻ° āĻāĻžāĻā§ āĻ˛āĻŋāĻāĻ¤ā§ āĻĻā§āĻŦāĻŋāĻ§āĻž āĻāĻ°āĻŦā§āĻ¨ āĻ¨āĻž āĻāĻŦāĻ āĻāĻĒāĻ¨āĻŋ āĻā§āĻāĻžāĻŦā§ āĻāĻāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§āĻ¨ āĻ¤āĻž āĻāĻŽāĻžāĻĻā§āĻ° āĻāĻžāĻ¨āĻžāĻ¨, āĻāĻŦāĻ āĻāĻ°āĻ āĻŦā§āĻļāĻŋ āĻāĻ°ā§ āĻ¯āĻĻāĻŋ āĻāĻĒāĻ¨āĻŋ āĻāĻāĻŋ āĻā§āĻĒāĻžāĻĻāĻ¨ā§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§āĻ¨āĨ¤
āĻā§āĻ°ā§āĻ¸ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻā§ āĻāĻ°āĻ āĻāĻžāĻ¨ā§āĻ¨:
āĻāĻ°āĻ āĻĒāĻĄāĻŧā§āĻ¨:
āĻ¤āĻ¤ā§āĻ¤ā§āĻŦāĻžāĻŦāĻ§āĻžāĻ¨ā§ āĻļā§āĻāĻžāĻ° āĻ¸āĻŽāĻ¸ā§āĻ¯āĻžāĻā§āĻ˛āĻŋāĻ¤ā§ āĻĒā§āĻ°āĻ§āĻžāĻ¨ āĻāĻĒāĻžāĻĻāĻžāĻ¨ āĻŦāĻŋāĻļā§āĻ˛ā§āĻˇāĻŖ āĻĒā§āĻ°āĻ¯āĻŧā§āĻā§āĻ° āĻā§āĻāĻāĻŋ āĻāĻŦāĻ āĻ¸āĻ¤āĻ°ā§āĻāĻ¤āĻž āĻĄāĻāĻžāĻ°ā§āĻ° āĻ¸āĻžāĻĨā§ āĻāĻāĻāĻŋ āĻŽā§āĻļāĻŋāĻ¨ āĻ˛āĻžāĻ°ā§āĻ¨āĻŋāĻ āĻŽāĻĄā§āĻ˛ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻāĻ°āĻž - āĻĒāĻžāĻ°ā§āĻ 1 āĻĄāĻāĻžāĻ°ā§āĻ° āĻ¸āĻžāĻĨā§ āĻāĻāĻāĻŋ āĻŽā§āĻļāĻŋāĻ¨ āĻ˛āĻžāĻ°ā§āĻ¨āĻŋāĻ āĻŽāĻĄā§āĻ˛ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻāĻ°āĻž - āĻĒāĻžāĻ°ā§āĻ 2
āĻāĻ¤ā§āĻ¸: www.habr.com