Επέκταση Spark με MLflow

Γεια σου, Χαμπροβίτες. Όπως έχουμε ήδη γράψει, αυτόν τον μήνα η OTUS ξεκινά δύο μαθήματα μηχανικής μάθησης ταυτόχρονα, συγκεκριμένα βάση и προχωρημένος. Από αυτή την άποψη, συνεχίζουμε να μοιραζόμαστε χρήσιμο υλικό.

Ο σκοπός αυτού του άρθρου είναι να μιλήσουμε για την πρώτη μας εμπειρία με Ροή ML.

Θα ξεκινήσουμε την αναθεώρηση Ροή ML από τον διακομιστή παρακολούθησης και προλογίστε όλες τις επαναλήψεις της μελέτης. Στη συνέχεια θα μοιραστούμε την εμπειρία σύνδεσης του Spark με το MLflow χρησιμοποιώντας UDF.

Πλαίσιο

Είμαστε μέσα Alpha Υγεία χρησιμοποιούμε μηχανική μάθηση και τεχνητή νοημοσύνη για να δώσουμε τη δυνατότητα στους ανθρώπους να φροντίζουν την υγεία και την ευημερία τους. Αυτός είναι ο λόγος για τον οποίο τα μοντέλα μηχανικής εκμάθησης βρίσκονται στο επίκεντρο των προϊόντων δεδομένων που αναπτύσσουμε και γι' αυτό το MLflow, μια πλατφόρμα ανοιχτού κώδικα που καλύπτει όλες τις πτυχές του κύκλου ζωής μηχανικής μάθησης, ήρθε στην προσοχή μας.

Ροή ML

Ο κύριος στόχος του MLflow είναι να παρέχει ένα πρόσθετο επίπεδο πάνω από τη μηχανική μάθηση που θα επιτρέπει στους επιστήμονες δεδομένων να συνεργάζονται με σχεδόν οποιαδήποτε βιβλιοθήκη μηχανικής μάθησης (h2o, keras, μελάπ, pytorch, sklearn и tensorflow), πηγαίνοντας τη δουλειά της στο επόμενο επίπεδο.

Το MLflow παρέχει τρία στοιχεία:

  • Παρακολούθηση – καταγραφή και αιτήματα για πειράματα: κώδικας, δεδομένα, διαμόρφωση και αποτελέσματα. Είναι πολύ σημαντικό να ακολουθήσετε τη διαδικασία δημιουργίας ενός μοντέλου.
  • Έργα – Μορφή συσκευασίας για εκτέλεση σε οποιαδήποτε πλατφόρμα (για παράδειγμα, SageMaker)
  • Μοντέλα είναι μια κοινή μορφή για την υποβολή μοντέλων σε διάφορα εργαλεία ανάπτυξης.

Το MLflow (άλφα κατά τη στιγμή της γραφής) είναι μια πλατφόρμα ανοιχτού κώδικα που σας επιτρέπει να διαχειρίζεστε τον κύκλο ζωής μηχανικής μάθησης, συμπεριλαμβανομένου του πειραματισμού, της επαναχρησιμοποίησης και της ανάπτυξης.

Ρύθμιση 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 μας επιτρέπει να καταγράφουμε και να υποβάλλουμε ερωτήματα σε πειράματα με Python και ΠΕΡΙΦΕΡΕΙΑ API. Επιπλέον, μπορείτε να ορίσετε πού θα αποθηκεύονται τα τεχνουργήματα μοντέλων (localhost, Amazon S3, Αποθήκευση Azure Blob, Google Cloud Storage ή Διακομιστής SFTP). Δεδομένου ότι χρησιμοποιούμε AWS στο Alpha Health, το 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 βρίσκεται σε μια παρουσία EC2, όταν εκτελείται τοπικά το MLflow, το μηχάνημα πρέπει να έχει άμεση πρόσβαση στο S3 για να γράψει μοντέλα τεχνουργημάτων.

Επέκταση Spark με MLflow
Το Tracking UI αποθηκεύει τεχνουργήματα στον κάδο S3

Μοντέλα τρεξίματος

Μόλις εκτελεστεί ο διακομιστής παρακολούθησης, μπορείτε να ξεκινήσετε την εκπαίδευση των μοντέλων.

Ως παράδειγμα, θα χρησιμοποιήσουμε την τροποποίηση κρασιού από το παράδειγμα MLflow in 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 σάς επιτρέπει να καταγράφετε παραμέτρους, μετρήσεις και μοντελοποιείτε τεχνουργήματα, ώστε να μπορείτε να παρακολουθείτε πώς αναπτύσσονται ως επαναλήψεις. Αυτή η δυνατότητα είναι εξαιρετικά χρήσιμη, επειδή μας επιτρέπει να αναπαράγουμε το καλύτερο μοντέλο επικοινωνώντας με τον διακομιστή παρακολούθησης ή κατανοώντας ποιος κώδικας πραγματοποίησε την απαιτούμενη επανάληψη χρησιμοποιώντας τα αρχεία καταγραφής 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
επαναλήψεις κρασιού

Πίσω άκρο για το μοντέλο

Ο διακομιστής παρακολούθησης MLflow που εκκινείται με την εντολή "mlflow server" έχει ένα REST API για την παρακολούθηση των εκτελέσεων και την εγγραφή δεδομένων στο τοπικό σύστημα αρχείων. Μπορείτε να καθορίσετε τη διεύθυνση του διακομιστή παρακολούθησης χρησιμοποιώντας τη μεταβλητή περιβάλλοντος "MLFLOW_TRACKING_URI" και το API παρακολούθησης MLflow θα επικοινωνήσει αυτόματα με τον διακομιστή παρακολούθησης σε αυτήν τη διεύθυνση για να δημιουργήσει/λάβει πληροφορίες εκκίνησης, μετρήσεις καταγραφής κ.λπ.

Πηγή: Έγγραφα// Εκτέλεση διακομιστή παρακολούθησης

Για να παρέχουμε στο μοντέλο διακομιστή, χρειαζόμαστε έναν διακομιστή παρακολούθησης που λειτουργεί (δείτε τη διεπαφή εκκίνησης) και το αναγνωριστικό εκτέλεσης του μοντέλου.

Επέκταση Spark με 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, χρειαζόμαστε πρόσβαση στη διεπαφή χρήστη παρακολούθησης για να λάβουμε πληροφορίες σχετικά με το μοντέλο καθορίζοντας απλώς --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

Παρά το γεγονός ότι ο διακομιστής παρακολούθησης είναι αρκετά ισχυρός για να εξυπηρετεί μοντέλα σε πραγματικό χρόνο, να τα εκπαιδεύει και να χρησιμοποιεί τη λειτουργικότητα του διακομιστή (πηγή: mlflow // docs // models #local), η χρήση του Spark (batch ή streaming) είναι μια ακόμα πιο ισχυρή λύση λόγω της διανομής του.

Φανταστείτε ότι μόλις κάνατε εκπαίδευση εκτός σύνδεσης και μετά εφαρμόσατε το μοντέλο εξόδου σε όλα τα δεδομένα σας. Εδώ είναι που το Spark και το MLflow έρχονται από μόνα τους.

Εγκαταστήστε το PySpark + Jupyter + Spark

Πηγή: Ξεκινήστε PySpark - Jupyter

Για να δείξουμε πώς εφαρμόζουμε μοντέλα MLflow σε πλαίσια δεδομένων Spark, πρέπει να ρυθμίσουμε τα σημειωματάρια Jupyter για να λειτουργούν με το 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, θα μπορούμε να αποθηκεύσουμε τα σημειωματάρια μας στον επιθυμητό φάκελο.

Τρέχοντας τον 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

Επέκταση 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 εκτελώντας πρόβλεψη ποιότητας κρασιού σε ολόκληρο το σύνολο δεδομένων κρασιού. Τι γίνεται όμως αν χρειαστεί να χρησιμοποιήσετε τις λειτουργικές μονάδες Python MLflow από το Scala Spark;

Το δοκιμάσαμε επίσης διαχωρίζοντας το πλαίσιο Spark μεταξύ Scala και Python. Δηλαδή, καταχωρήσαμε το MLflow UDF στην Python, και το χρησιμοποιήσαμε από τη Scala (ναι, ίσως όχι η καλύτερη λύση, αλλά αυτή που έχουμε).

Scala Spark + MLflow

Για αυτό το παράδειγμα, θα προσθέσουμε Πυρήνας Toree σε έναν υπάρχοντα Δία.

Εγκαταστήστε το 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 είναι στο Alpha τη στιγμή της γραφής, φαίνεται αρκετά υποσχόμενο. Η δυνατότητα εκτέλεσης πολλαπλών πλαισίων μηχανικής εκμάθησης και η χρήση τους από ένα μόνο τελικό σημείο οδηγεί τα συστήματα συστάσεων στο επόμενο επίπεδο.

Επιπλέον, το MLflow φέρνει πιο κοντά τους μηχανικούς δεδομένων και τους επιστήμονες δεδομένων, θέτοντας ένα κοινό επίπεδο μεταξύ τους.

Μετά από αυτήν την εξερεύνηση του MLflow, είναι βέβαιο ότι θα προχωρήσουμε και θα το χρησιμοποιήσουμε για τους αγωγούς Spark και τα συστήματα συστάσεων.

Θα ήταν ωραίο να συγχρονίσετε την αποθήκευση αρχείων με τη βάση δεδομένων αντί για το σύστημα αρχείων. Αυτό θα πρέπει να μας δώσει πολλά τελικά σημεία που μπορούν να χρησιμοποιήσουν το ίδιο κοινόχρηστο αρχείο. Για παράδειγμα, χρησιμοποιήστε πολλαπλές παρουσίες Presto и Αθήνα με το ίδιο Glue metastore.

Συνοψίζοντας, θα ήθελα να ευχαριστήσω την κοινότητα του MLFlow που έκανε την εργασία μας με τα δεδομένα πιο ενδιαφέρουσα.

Εάν παίζετε με το MLflow, μη διστάσετε να μας γράψετε και να μας πείτε πώς το χρησιμοποιείτε και ακόμη περισσότερο εάν το χρησιμοποιείτε στην παραγωγή.

Μάθετε περισσότερα για τα μαθήματα:
μηχανική μάθηση. Βασικό μάθημα
μηχανική μάθηση. προχωρημένο μάθημα

Διαβάστε περισσότερα:

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο