MLflow рд╕рд╣ рд╕реНрдкрд╛рд░реНрдХ рд╡рд╛рдврд╡рдгреЗ

рд╣реЕрд▓реЛ, рдЦрд╛рдмреНрд░реЛрд╡реНрд╕реНрдХ рд░рд╣рд┐рд╡рд╛рд╕реА. рдЖрдореНрд╣реА рдЖрдзреАрдЪ рд▓рд┐рд╣рд┐рд▓реНрдпрд╛рдкреНрд░рдорд╛рдгреЗ, рдпрд╛ рдорд╣рд┐рдиреНрдпрд╛рдд OTUS рдПрдХрд╛рдЪ рд╡реЗрд│реА рджреЛрди рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ рдЕрднреНрдпрд╛рд╕рдХреНрд░рдо рд╕реБрд░реВ рдХрд░рдд рдЖрд╣реЗ, рдореНрд╣рдгрдЬреЗ рдкрд╛рдпрд╛ ╨╕ рдкреНрд░рдЧрдд. рдпрд╛ рд╕рдВрджрд░реНрднрд╛рдд, рдЖрдореНрд╣реА рдЙрдкрдпреБрдХреНрдд рд╕рд╛рд╣рд┐рддреНрдп рд╕рд╛рдорд╛рдпрд┐рдХ рдХрд░рдгреЗ рд╕реБрд░реВ рдареЗрд╡рддреЛ.

рдпрд╛ рд▓реЗрдЦрд╛рдЪрд╛ рдЙрджреНрджреЗрд╢ рдЖрдордЪреНрдпрд╛ рдкрд╣рд┐рд▓реНрдпрд╛ рдЕрдиреБрднрд╡рд╛рдмрджреНрджрд▓ рдмреЛрд▓рдгреЗ рдЖрд╣реЗ MLflow.

рдЖрдореНрд╣реА рдкреБрдирд░рд╛рд╡рд▓реЛрдХрди рд╕реБрд░реВ рдХрд░реВ MLflow рддреНрдпрд╛рдЪреНрдпрд╛ рдЯреНрд░реЕрдХрд┐рдВрдЧ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░реВрди рдЖрдгрд┐ рдЕрднреНрдпрд╛рд╕рд╛рдЪреНрдпрд╛ рд╕рд░реНрд╡ рдкреБрдирд░рд╛рд╡реГрддреНрддреА рд▓реЙрдЧ рдХрд░рд╛. рдордЧ рдЖрдореНрд╣реА UDF рд╡рд╛рдкрд░реВрди рд╕реНрдкрд╛рд░реНрдХрд▓рд╛ MLflow рд╢реА рдЬреЛрдбрдгреНрдпрд╛рдЪрд╛ рдЖрдордЪрд╛ рдЕрдиреБрднрд╡ рд╢реЗрдЕрд░ рдХрд░реВ.

рд╕рдВрджрд░реНрдн

рдЖрдореНрд╣реА рдордзреНрдпреЗ рдЖрд╣реЛрдд рдЕрд▓реНрдлрд╛ рдЖрд░реЛрдЧреНрдп рдЖрдореНтАНрд╣реА рдорд╢рд┐рди рд▓рд░реНрдирд┐рдВрдЧ рдЖрдгрд┐ рдЖрд░реНрдЯрд┐рдлрд┐рд╢рд┐рдпрд▓ рдЗрдВрдЯреЗрд▓рд┐рдЬреЗрдВрд╕ рд╡рд╛рдкрд░рддреЛ рдЬреЗрдгреЗрдХрд░реВрди рд▓реЛрдХрд╛рдВрдирд╛ рддреНтАНрдпрд╛рдВрдЪреНтАНрдпрд╛ рд╕реНтАНрд╡рд╛рд╕реНтАНрдереНтАНрдпрд╛рдЪреА рдЖрдгрд┐ рддреНтАНрдпрд╛рдВрдЪреНтАНрдпрд╛ рддрдВрджреБрд░реБрд╕реНрддреАрдЪреА рдЬрдмрд╛рдмрджрд╛рд░реА рдШреЗрдгреНтАНрдпрд╛рд╕рд╛рдареА рд╕рдХреНрд╖рдо рдХрд░рдгреНтАНрдпрд╛рд╕рд╛рдареА. рдореНрд╣рдгреВрдирдЪ рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ рдореЙрдбреЗрд▓реНрд╕ рд╣реЗ рдЖрдореНрд╣реА рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдд рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдбреЗрдЯрд╛ рд╕рд╛рдпрдиреНрд╕ рдЙрддреНрдкрд╛рджрдирд╛рдВрдЪреНрдпрд╛ рдХреЗрдВрджреНрд░рд╕реНрдерд╛рдиреА рдЕрд╕рддрд╛рдд рдЖрдгрд┐ рдореНрд╣рдгреВрдирдЪ рдЖрдореНрд╣реА MLflow рдпрд╛ рдУрдкрди рд╕реЛрд░реНрд╕ рдкреНрд▓реЕрдЯрдлреЙрд░реНрдордХрдбреЗ рдЖрдХрд░реНрд╖рд┐рдд рдЭрд╛рд▓реЛ, рдЬреЗ рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ рд▓рд╛рдЗрдлрд╕рд╛рдпрдХрд▓рдЪреНрдпрд╛ рд╕рд░реНрд╡ рдкреИрд▓реВрдВрдЪрд╛ рд╕рдорд╛рд╡реЗрд╢ рдХрд░рддреЗ.

MLflow

MLflow рдЪреЗ рдореБрдЦреНрдп рдЙрджреНрджрд┐рд╖реНрдЯ рдореНрд╣рдгрдЬреЗ рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧрдЪреНрдпрд╛ рд╡рд░ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реНрддрд░ рдкреНрд░рджрд╛рди рдХрд░рдгреЗ рдЬреЗ рдбреЗрдЯрд╛ рд╢рд╛рд╕реНрддреНрд░рдЬреНрдЮрд╛рдВрдирд╛ рдЬрд╡рд│рдЬрд╡рд│ рдХреЛрдгрддреНрдпрд╛рд╣реА рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ рд▓рд╛рдпрдмреНрд░рд░реАрд╕рд╣ рдХрд╛рд░реНрдп рдХрд░рдгреНрдпрд╛рд╕ рдЕрдиреБрдорддреА рджреЗрдИрд▓ (h2o, рдХреЗрд░рд╛рд╕, mleap, рдкрд╛рдпрдЯреЛрд░реНрдЪ, sklearn ╨╕ рдЯреЗрдиреНрд╕рд░рдлреНрд▓реЛ), рддрд┐рдЪреЗ рдХрд╛рдо рдкреБрдвреАрд▓ рд╕реНрддрд░рд╛рд╡рд░ рдиреЗрдд рдЖрд╣реЗ.

MLflow рддреАрди рдШрдЯрдХ рдкреНрд░рджрд╛рди рдХрд░рддреЗ:

  • рдЯреНрд░реЕрдХрд┐рдВрдЧ - рд░реЗрдХреЙрд░реНрдбрд┐рдВрдЧ рдЖрдгрд┐ рдкреНрд░рдпреЛрдЧрд╛рдВрд╕рд╛рдареА рд╡рд┐рдирдВрддреНрдпрд╛: рдХреЛрдб, рдбреЗрдЯрд╛, рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдЖрдгрд┐ рдкрд░рд┐рдгрд╛рдо. рдореЙрдбреЗрд▓ рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪреНрдпрд╛ рдкреНрд░рдХреНрд░рд┐рдпреЗрдЪреЗ рдирд┐рд░реАрдХреНрд╖рдг рдХрд░рдгреЗ рдЦреВрдк рдорд╣рддреНрд╡рд╛рдЪреЗ рдЖрд╣реЗ.
  • рдкреНрд░рдХрд▓реНрдк - рдХреЛрдгрддреНрдпрд╛рд╣реА рдкреНрд▓реЕрдЯрдлреЙрд░реНрдорд╡рд░ рдЪрд╛рд▓рдгреНрдпрд╛рд╕рд╛рдареА рдкреЕрдХреЗрдЬрд┐рдВрдЧ рд╕реНрд╡рд░реВрдк (рдЙрджрд╛. рд╕реЗрдЬрдореЗрдХрд░)
  • рдореЙрдбреЗрд▓ - рд╡рд┐рд╡рд┐рдз рдЙрдкрдпреЛрдЬрди рд╕рд╛рдзрдирд╛рдВрдордзреНрдпреЗ рдореЙрдбреЗрд▓ рд╕рдмрдорд┐рдЯ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╕реНрд╡рд░реВрдк.

рдПрдордПрд▓рдлреНрд▓реЛ (рд▓реЗрдЦрдирд╛рдЪреНрдпрд╛ рд╡реЗрд│реА рдЕрд▓реНрдлрд╛рдордзреНрдпреЗ) рд╣реЗ рдПрдХ рдореБрдХреНрдд рд╕реНрд░реЛрдд рдкреНрд▓реЕрдЯрдлреЙрд░реНрдо рдЖрд╣реЗ рдЬреЗ рддреБрдореНрд╣рд╛рд▓рд╛ рдкреНрд░рдпреЛрдЧ, рдкреБрдирд░реНрд╡рд╛рдкрд░ рдЖрдгрд┐ рдЙрдкрдпреЛрдЬрдирд╛рд╕рд╣ рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ рд▓рд╛рдЗрдлрд╕рд╛рдпрдХрд▓ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреНрдпрд╛рд╕ рдЕрдиреБрдорддреА рджреЗрддреЗ.

MLflow рд╕реЗрдЯ рдХрд░рдд рдЖрд╣реЗ

MLflow рд╡рд╛рдкрд░рдгреНрдпрд╛рд╕рд╛рдареА рддреБрдореНрд╣рд╛рд▓рд╛ рдкреНрд░рдердо рддреБрдордЪреЗ рд╕рдВрдкреВрд░реНрдг рдкрд╛рдпрдерди рд╡рд╛рддрд╛рд╡рд░рдг рд╕реЗрдЯ рдЕрдк рдХрд░рд╛рд╡реЗ рд▓рд╛рдЧреЗрд▓, рдпрд╛рд╕рд╛рдареА рдЖрдореНрд╣реА рд╡рд╛рдкрд░рдгрд╛рд░ рдЖрд╣реЛрдд PyEnv (рдореЕрдХрд╡рд░ рдкрд╛рдпрдерди рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рддрдкрд╛рд╕рд╛ рдпреЗрдереЗ). рдЕрд╢рд╛ рдкреНрд░рдХрд╛рд░реЗ рдЖрдкрдг рдПрдХ рдЖрднрд╛рд╕реА рд╡рд╛рддрд╛рд╡рд░рдг рддрдпрд╛рд░ рдХрд░реВ рд╢рдХрддреЛ рдЬрд┐рдереЗ рдЖрдкрдг рддреЗ рдЪрд╛рд▓рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА рдЖрд╡рд╢реНрдпрдХ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рд╕рд░реНрд╡ рд▓рд╛рдпрдмреНрд░рд░реА рд╕реНрдерд╛рдкрд┐рдд рдХрд░реВ.

```
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 рдЯреНрд░реЕрдХрд┐рдВрдЧ рдЖрдореНрд╣рд╛рд▓рд╛ Python рдЖрдгрд┐ рд╡рд╛рдкрд░реВрди рдкреНрд░рдпреЛрдЧ рд▓реЙрдЧ рдЖрдгрд┐ рдХреНрд╡реЗрд░реА рдХрд░рдгреНрдпрд╛рд╕ рдЕрдиреБрдорддреА рджреЗрддреЗ рдЙрд░реНрд╡рд░рд┐рдд API. рдпрд╛рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рдореЙрдбреЗрд▓ рдЖрд░реНрдЯрд┐рдлреЕрдХреНрдЯреНрд╕ рдХреБрдареЗ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд░рд╛рдпрдЪреЗ рд╣реЗ рддреБрдореНрд╣реА рдард░рд╡реВ рд╢рдХрддрд╛ (рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ, рдНрдореЗрдЭреЙрди S3, рдЕрдЭрд░ рдмреНрд▓реЙрдм рд╕реНрдЯреЛрд░реЗрдЬ, Google рдореЗрдШ рд╕рдВрдЪрдпрди рдХрд┐рдВрд╡рд╛ SFTP рд╕рд░реНрд╡реНрд╣рд░). рдЖрдореНрд╣реА рдЕрд▓реНрдлрд╛ рд╣реЗрд▓реНрде рдпреЗрдереЗ 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 рдордзреНрдпреЗ рд╡рд╛рдкрд░реВ рд╢рдХрддреЛ, рдХрд╛рд░рдг рдЖрдореНрд╣рд╛рд▓рд╛ рдлрдХреНрдд рдореЙрдбреЗрд▓рдЪрд╛ рдорд╛рд░реНрдЧ рд╣рд╡рд╛ рдЖрд╣реЗ.

рдЯреАрдк: рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рд╛ рдХреА рдЯреНрд░реЕрдХрд┐рдВрдЧ UI рдЖрдгрд┐ рдореЙрдбреЗрд▓ рдХреНрд▓рд╛рдпрдВрдЯрд▓рд╛ рдЖрд░реНрдЯрд┐рдлреЕрдХреНрдЯ рд╕реНрдерд╛рдирд╛рдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдЕрд╕рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рдореНрд╣рдгрдЬреЗрдЪ, рдЯреНрд░реЕрдХрд┐рдВрдЧ UI EC2 рдЙрджрд╛рд╣рд░рдгрд╛рдордзреНрдпреЗ рд░рд╛рд╣рддреЛ рдпрд╛рдХрдбреЗ рджреБрд░реНрд▓рдХреНрд╖ рдХрд░реВрди, MLflow рд╕реНрдерд╛рдирд┐рдХ рдкрд╛рддрд│реАрд╡рд░ рдЪрд╛рд▓рд╡рддрд╛рдирд╛, рдЖрд░реНрдЯрд┐рдлреЕрдХреНрдЯ рдореЙрдбреЗрд▓реНрд╕ рд▓рд┐рд╣рд┐рдгреНрдпрд╛рд╕рд╛рдареА рдорд╢реАрдирд▓рд╛ S3 рд╡рд░ рдереЗрдЯ рдкреНрд░рд╡реЗрд╢ рдЕрд╕рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ.

MLflow рд╕рд╣ рд╕реНрдкрд╛рд░реНрдХ рд╡рд╛рдврд╡рдгреЗ
рдЯреНрд░реЕрдХрд┐рдВрдЧ 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 рд╕рд╣ рд╕реНрдкрд╛рд░реНрдХ рд╡рд╛рдврд╡рдгреЗ
рд╡рд╛рдЗрди рдкреБрдирд░рд╛рд╡реГрддреНрддреА

рдореЙрдбреЗрд▓рд╕рд╛рдареА рд╕рд░реНрд╡реНрд╣рд░ рднрд╛рдЧ

рдПрдордПрд▓рдлреНрд▓реЛ рдЯреНрд░реЕрдХрд┐рдВрдЧ рд╕рд░реНрд╡реНрд╣рд░, тАЬрдПрдордПрд▓рдлреНрд▓реЛ рд╕рд░реНрд╡реНрд╣рд░тАЭ рдХрдорд╛рдВрдб рд╡рд╛рдкрд░реВрди рд▓реЙрдиреНрдЪ рдХреЗрд▓рд╛ рдЧреЗрд▓рд╛ рдЖрд╣реЗ, рдЬреНрдпрд╛рдордзреНрдпреЗ рд╕реНрдерд╛рдирд┐рдХ рдлрд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдордордзреНрдпреЗ рдзрд╛рд╡рд╛рдВрдЪрд╛ рдорд╛рдЧреЛрд╡рд╛ рдШреЗрдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ рдбреЗрдЯрд╛ рд▓рд┐рд╣рд┐рдгреНрдпрд╛рд╕рд╛рдареА REST API рдЖрд╣реЗ. рддреБрдореНрд╣реА рдкрд░реНрдпрд╛рд╡рд░рдг рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓ тАЬMLFLOW_TRACKING_URIтАЭ рд╡рд╛рдкрд░реВрди рдЯреНрд░реЕрдХрд┐рдВрдЧ рд╕рд░реНрд╡реНрд╣рд░ рдкрддреНрддрд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реВ рд╢рдХрддрд╛ рдЖрдгрд┐ MLflow рдЯреНрд░реЕрдХрд┐рдВрдЧ API рд▓рд╛рдБрдЪ рдорд╛рд╣рд┐рддреА, рд▓реЙрдЧ рдореЗрдЯреНрд░рд┐рдХреНрд╕ рдЗрддреНрдпрд╛рджреА рддрдпрд╛рд░/рдкреНрд░рд╛рдкреНрдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдпрд╛ рдкрддреНрддреНрдпрд╛рд╡рд░ рдЯреНрд░реЕрдХрд┐рдВрдЧ рд╕рд░реНрд╡реНрд╣рд░рд╢реА рдЖрдкреЛрдЖрдк рд╕рдВрдкрд░реНрдХ рдХрд░реЗрд▓.

рд╕реНрддреНрд░реЛрдд: рдбреЙрдХреНрд╕// рдЯреНрд░реЕрдХрд┐рдВрдЧ рд╕рд░реНрд╡реНрд╣рд░ рдЪрд╛рд▓рд╡рдд рдЖрд╣реЗ

рд╕рд░реНрд╡реНрд╣рд░рд╕рд╣ рдореЙрдбреЗрд▓ рдкреНрд░рджрд╛рди рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдЖрдореНрд╣рд╛рд▓рд╛ рдПрдХ рдЪрд╛рд▓реВ рдЯреНрд░реЕрдХрд┐рдВрдЧ рд╕рд░реНрд╡реНрд╣рд░ (рд▓рд╛рдБрдЪ рдЗрдВрдЯрд░рдлреЗрд╕ рдкрд╣рд╛) рдЖрдгрд┐ рдореЙрдбреЗрд▓рдЪрд╛ рд░рди рдЖрдпрдбреА рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ.

MLflow рд╕рд╣ рд╕реНрдкрд╛рд░реНрдХ рд╡рд╛рдврд╡рдгреЗ
рдЖрдпрдбреА рдЪрд╛рд▓рд╡рд╛

# 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 рдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ --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 - Jupyter

рдЖрдореНрд╣реА Spark рдбреЗрдЯрд╛рдлреНрд░реЗрдорд╡рд░ MLflow рдореЙрдбреЗрд▓ рдХрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рддреЛ рд╣реЗ рджрд╛рдЦрд╡рдгреНрдпрд╛рд╕рд╛рдареА, рдЖрдореНрд╣рд╛рд▓рд╛ PySpark рд╕реЛрдмрдд рдПрдХрддреНрд░ рдХрд╛рдо рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА Jupyter рдиреЛрдЯрдмреБрдХ рд╕реЗрдЯ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ.

рдирд╡реАрдирддрдо рд╕реНрдерд┐рд░ рдЖрд╡реГрддреНрддреА рд╕реНрдерд╛рдкрд┐рдд рдХрд░реВрди рдкреНрд░рд╛рд░рдВрдн рдХрд░рд╛ рдЕрдкрд╛рдЪреЗ рд╕реНрдкрд╛рд░реНрдХ:

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 рд▓рд╛рдБрдЪ рдХрд░рдд рдЖрд╣реЗ

рдЖрдореНрд╣реА рдЬреНрдпреБрдкрд┐рдЯрд░рд▓рд╛ PySpark рдбреНрд░рд╛рдЗрд╡реНрд╣рд░ рдореНрд╣рдгреВрди рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░реВ рд╢рдХрд▓реЛ рдЕрд╕рд▓реНрдпрд╛рдиреЗ, рдЖрдореНрд╣реА рдЖрддрд╛ 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 рд╕рд╣ рд╕реНрдкрд╛рд░реНрдХ рд╡рд╛рдврд╡рдгреЗ

рд╡рд░ рдирдореВрдж рдХреЗрд▓реНрдпрд╛рдкреНрд░рдорд╛рдгреЗ, 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)

MLflow рд╕рд╣ рд╕реНрдкрд╛рд░реНрдХ рд╡рд╛рдврд╡рдгреЗ
PySpark - рдЖрдЙрдЯрдкреБрдЯрд┐рдВрдЧ рд╡рд╛рдЗрди рдЧреБрдгрд╡рддреНрддрд╛ рдЕрдВрджрд╛рдЬ

рдпрд╛ рдЯрдкреНрдкреНрдпрд╛рдкрд░реНрдпрдВрдд, рдЖрдореНрд╣реА MLflow рд╕рд╣ PySpark рдХрд╕реЗ рд╡рд╛рдкрд░рд╛рд╡реЗ, рд╕рдВрдкреВрд░реНрдг рд╡рд╛рдЗрди рдбреЗрдЯрд╛рд╕реЗрдЯрд╡рд░ рд╡рд╛рдЗрди рдЧреБрдгрд╡рддреНрддреЗрдЪреЗ рдЕрдВрджрд╛рдЬ рдХрд╕реЗ рд╡рд╛рдкрд░рд╛рд╡реЗ рдпрд╛рдмрджреНрджрд▓ рдмреЛрд▓рд▓реЛ рдЖрд╣реЛрдд. рдкрдг рдЬрд░ рддреБрдореНрд╣рд╛рд▓рд╛ рд╕реНрдХрд╛рд▓рд╛ рд╕реНрдкрд╛рд░реНрдХрдордзреАрд▓ рдкрд╛рдпрдерди рдПрдордПрд▓рдлреНрд▓реЛ рдореЙрдбреНрдпреВрд▓реНрд╕ рд╡рд╛рдкрд░рдгреНрдпрд╛рдЪреА рдЧрд░рдЬ рдЕрд╕реЗрд▓ рддрд░?

рдЖрдореНрд╣реА рд╕реНрдХрд╛рд▓рд╛ рдЖрдгрд┐ рдкрд╛рдпрдерди рджрд░рдореНрдпрд╛рди рд╕реНрдкрд╛рд░реНрдХ рд╕рдВрджрд░реНрдн рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реВрди рдпрд╛рдЪреА рджреЗрдЦреАрд▓ рдЪрд╛рдЪрдгреА рдХреЗрд▓реА. рдореНрд╣рдгрдЬреЗрдЪ, рдЖрдореНрд╣реА Python рдордзреНрдпреЗ MLflow UDF рдиреЛрдВрджрдгреАрдХреГрдд рдХреЗрд▓реЗ рдЖрдгрд┐ рддреЗ Scala рд╡рд░реВрди рд╡рд╛рдкрд░рд▓реЗ (рд╣реЛрдп, рдХрджрд╛рдЪрд┐рдд рд╕рд░реНрд╡реЛрддреНрддрдо рдЙрдкрд╛рдп рдирд╛рд╣реА, рдкрд░рдВрддреБ рдЖрдордЪреНрдпрд╛рдХрдбреЗ рдХрд╛рдп рдЖрд╣реЗ).

рд╕реНрдХрд╛рд▓рд╛ рд╕реНрдкрд╛рд░реНрдХ + рдПрдордПрд▓рдлреНрд▓реЛ

рдпрд╛ рдЙрджрд╛рд╣рд░рдгрд╛рд╕рд╛рдареА рдЖрдкрдг рдЬреЛрдбреВ рддреЛрд░реА рдХрд░реНрдирд▓ рд╡рд┐рджреНрдпрдорд╛рди рдмреГрд╣рд╕реНрдкрддрд┐ рдордзреНрдпреЗ.

рд╕реНрдкрд╛рд░реНрдХ + рдЯреЛрд░реА + рдЬреНрдпреБрдкрд┐рдЯрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рд╛

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 рджрд░рдореНрдпрд╛рди рд╕рд╛рдорд╛рдпрд┐рдХ рдХреЗрд▓реЗ рдЖрд╣реЗ. рдЖрдореНрд╣рд╛рд▓рд╛ рдЖрд╢рд╛ рдЖрд╣реЗ рдХреА рдЬреНрдпрд╛рдВрдирд╛ рд╕реНрдХрд╛рд▓рд╛ рдЖрд╡рдбрддреЗ рдЖрдгрд┐ рдЙрддреНрдкрд╛рджрдирд╛рдд рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ рдореЙрдбреЗрд▓ рд▓рд╛рдЧреВ рдХрд░реВ рдЗрдЪреНрдЫрд┐рддрд╛рдд рддреНрдпрд╛рдВрдЪреНрдпрд╛рд╕рд╛рдареА рд╣рд╛ рднрд╛рдЧ рдЙрдкрдпреБрдХреНрдд рдард░реЗрд▓.

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 рд╕рд╣ рдЦреЗрд│рдд рдЕрд╕рд╛рд▓, рддрд░ рдЖрдореНрд╣рд╛рд▓рд╛ рд▓рд┐рд╣рд╛рдпрд▓рд╛ рдЕрдЬрд┐рдмрд╛рдд рд╕рдВрдХреЛрдЪ рдХрд░реВ рдирдХрд╛ рдЖрдгрд┐ рддреБрдореНрд╣реА рддреЗ рдХрд╕реЗ рд╡рд╛рдкрд░рддрд╛ рддреЗ рдЖрдореНрд╣рд╛рд▓рд╛ рд╕рд╛рдВрдЧрд╛ рдЖрдгрд┐ рддреНрдпрд╛рд╣реАрдкреЗрдХреНрд╖рд╛ рддреБрдореНрд╣реА рдЙрддреНрдкрд╛рджрдирд╛рдд рд╡рд╛рдкрд░рдд рдЕрд╕рд╛рд▓ рддрд░.

рдЕрднреНрдпрд╛рд╕рдХреНрд░рдорд╛рдВрдмрджреНрджрд▓ рдЕрдзрд┐рдХ рдЬрд╛рдгреВрди рдШреНрдпрд╛:
рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ. рдмреЗрд╕рд┐рдХ рдХреЛрд░реНрд╕
рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ. рдкреНрд░рдЧрдд рдЕрднреНрдпрд╛рд╕рдХреНрд░рдо

рдкреБрдвреЗ рд╡рд╛рдЪрд╛:

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛