Snowpark ML Ops: Modell-Registry

Bemerkung

Die unter diesem Thema beschriebene Modell-Registry-API ist im Snowpark ML-Paket ab Version 1.2.0 verfügbar.

Als Teil von Snowpark ML Operations (MLOps) ermöglicht die Snowpark Model Registry Kunden die sichere Verwaltung von Modellen und deren Metadaten in Snowflake, unabhängig von ihrem Ursprung. Die Snowpark Model Registry speichert Modelle für maschinelles Lernen als First-Class-Objekte auf Schema-Ebene in Snowflake, sodass sie von anderen in Ihrer Organisation leicht gefunden und verwendet werden können. Mit Snowpark ML können Sie Registrys erstellen und Modelle darin speichern. Modelle können mehrere Versionen haben, und Sie können eine Version als Standardversion festlegen.

Sobald Sie ein Modell gespeichert haben, können Sie dessen Methoden (gleichbedeutend mit Funktionen oder gespeicherten Prozeduren) aufrufen, um Modelloperationen, wie z. B. Inferenzen, in einem virtuellen Warehouse von Snowflake auszuführen.

Tipp

Ein Beispiel für einen durchgängigen Workflow in Snowpark ML einschließlich der Modell-Registry finden Sie unter Einführung in maschinelles Lernen mit Snowpark ML.

Die drei wichtigsten Objekte der Snowpark Model Registry-API sind:

  • snowflake.ml.registry.Registry: Verwaltet Modelle innerhalb eines Schemas.

  • snowflake.ml.model.Model: Repräsentiert ein Modell.

  • snowflake.ml.model.ModelVersion: Repräsentiert eine Version eines Modells.

Ausführliche Informationen zu diesen Klassen finden Sie in der Referenz zur Snowpark ML-API.

Die Snowpark Model Registry unterstützt die folgenden Typen von Modellen.

Unter diesem Thema wird beschrieben, wie Sie mit Snowpark ML Registry-Operationen in Python ausführen können. Sie können viele Registry-Operationen auch in SQL ausführen. Weitere Informationen dazu finden Sie unter Befehle für Modelle.

Unterschiede zur privaten Vorschau

Snowflake hatte zuvor bereits ausgewählten Kunden eine Model Registry in privater Vorschau zur Verfügung gestellt. Das unter diesem Thema beschriebene Registry-Feature weist gegenüber der Version aus der privaten Vorschau erhebliche Änderungen in Bezug auf Funktionalität und APIs auf. Vor allem die Model Registry-Funktionalität wird jetzt nativ innerhalb von Snowflake gehostet, indem ein neues Objekt auf Schemaebene verwendet wird.

Bemerkung

Diese öffentliche Vorschauversion unterstützt noch nicht die Bereitstellung von Modellen in Snowpark Container Services (SPCS). Wenn Sie auf diese Funktionalität angewiesen sind, verwenden Sie vorerst weiterhin die Registry der privaten Vorschau.

Weitere Informationen zu den Unterschieden zwischen diesen beiden APIs finden Sie unter Snowpark ML Ops: Migration von der Vorschau-API der Modell-Registry.

Erforderliche Berechtigungen

Um ein Modell zu erstellen, müssen Sie entweder Eigentümer des Schemas sein, in dem das Modell erstellt wird, oder über die Berechtigung CREATE MODEL für dieses Schema verfügen. Um ein Modell zu verwenden, müssen Sie entweder Eigentümer des Modells sein oder über die Berechtigung USAGE für das Modell verfügen.

Öffnen der Snowpark Model Registry

Modelle sind Snowflake-Objekte erster Klasse und können zusammen mit anderen Snowflake-Objekten in einer Datenbank und einem Schema organisiert werden. Die Snowpark Model Registry ist eine Python-Klasse zur Verwaltung von Modellen innerhalb eines Schemas. Somit kann jedes Snowflake-Schema als Registry verwendet werden. Es ist nicht notwendig, ein Schema für diesen Zweck zu initialisieren oder anderweitig vorzubereiten. Snowflake empfiehlt das Erstellen eines oder mehrerer dedizierter Schemas für diesen Zweck, z. B. ML.REGISTRY. Sie können das Schema mit CREATE SCHEMA erstellen.

Bevor Sie Modelle in der Registry erstellen oder ändern können, müssen Sie die Registry öffnen. Wenn Sie die Registry öffnen, erhalten Sie eine Referenz auf die Registry, mit der Sie neue Modelle hinzufügen und Referenzen auf vorhandene Modelle erhalten können.

from snowflake.ml.registry import Registry

reg = Registry(session=sp_session, database_name="ML", schema_name="REGISTRY")
Copy

Bemerkung

Während dieser öffentlichen Vorschau unterstützen Model-Objekte weder Replikation noch Klonen.

Registrieren von Modellen und Versionen

Das Hinzufügen eines Modells zur Registry wird als Protokollierung (Logging) des Modells bezeichnet. Ein Modell wird protokolliert, indem die log_model-Methode der Registry aufgerufen wird. Diese Methode ermöglicht Folgendes:

  • Serialisieren des Modells, ein Python-Objekt, und Erstellen eines Snowflake-Modellobjekts daraus

  • Hinzufügen von Metadaten, wie z. B. eine Beschreibung, zu dem Modell wie im log_model-Aufruf angegeben

Bemerkung

Sie können einem Modell keine Tags hinzufügen, wenn es der Registry hinzugefügt wird, da Tags Attribute des Modells sind und log_model eine bestimmte Modellversion hinzufügt. Sie können aber nach der Protokollierung der ersten Version des Modells die Tags des Modells aktualisieren.

Jedes Modell kann eine beliebige Anzahl von Versionen haben. Um weitere Versionen des Modells zu protokollieren, rufen Sie log_model erneut mit demselben model_name-Wert, aber einem anderen version_name-Wert auf.

Im folgenden Beispiel ist clf, kurz für „classifier“ (Klassifikator), das Python-Modellobjekt, das bereits an anderer Stelle in Ihrem Code erstellt wurde. Sie können beim Registrieren einen Kommentar und Tags hinzufügen, wie hier gezeigt. Die Kombination aus Name und Version muss im Schema eindeutig sein. Sie können conda_dependencies-Listen angeben; die angegebenen Pakete werden mit dem Modell bereitgestellt.

mv = reg.log_model(clf,
                   model_name="my_model",
                   version_name="1",
                   conda_dependencies=["scikit-learn"],
                   comment="My awesome ML model",
                   metrics={"score": 96},
                   sample_input_data=train_features)
Copy

Im Folgenden werden die Argumente von log_model beschrieben.

Erforderliche Argumente

Argument

Beschreibung

model

Das Python-Modellobjekt eines unterstützten Modelltyps. Muss serialisierbar („pickleable“) sein.

model_name

Name des Modells, der zusammen mit version_name verwendet wird, um das Modell in der Registry zu identifizieren. Sobald das Modell protokolliert wurde, kann der Name nicht mehr geändert werden.

version_name

Zeichenfolge, die die Version des Modells angibt und zusammen mit dem model_name-Wert zur Identifizierung des Modells in der Registry verwendet wird.

Bemerkung

Die Kombination aus Modellname und Version muss im Schema eindeutig sein.

Optionale Argumente

Argument

Beschreibung

code_paths

Liste der Pfade zu den Verzeichnissen des zu importierenden Codes beim Laden oder Bereitstellen des Modells.

comment

Kommentar, zum Beispiel eine Beschreibung des Modells.

conda_dependencies

Liste der Conda-Pakete, die für das Modell erforderlich sind. Dieses Argument gibt Paketnamen und optionale Versionen im Conda-Format an, d. h. "[channel::]package [operator version]". Wenn Sie keinen Kanal angeben, wird der Snowflake-Kanal verwendet.

ext_modules

Liste der externen Module, die mit dem Modell serialisiert („pickled“) werden sollen. Unterstützt bei Scikit-learn, Snowpark ML, PyTorch, TorchScript und benutzerdefinierten Modellen.

metrics

Dictionary mit Kennzahlen, die mit der Modellversion verknüpft sind.

options

Dictionary mit Optionen für die Modellerstellung. Die folgenden Optionen sind für alle Modelltypen verfügbar.

  • embed_local_ml_library: Ob eine Kopie der lokalen Snowpark ML-Bibliothek in das Modell eingebettet werden soll. Standard: False.

  • relax_version: Ob die Versionsbeschränkungen von Abhängigkeiten gelockert werden sollen. Dadurch werden Versionsangaben wie ==x.y.z durch Angaben wie <=x.y, <(x+1) ersetzt. Standard: False. Verfügbar ab Snowpark ML-Paketversion 1.2.1.

  • method_options: Ein Dictionary mit Optionen pro Methode, wobei der Schlüssel der Name einer Methode und der Wert ein Dictionary ist, das eine oder mehrere der hier beschriebenen Optionen enthält. Folgende Optionen sind verfügbar:

    • case_sensitive: Gibt an, ob bei der Methode und ihrer Signatur die Groß-/Kleinschreibung beachtet wird. Methoden, bei denen die Groß-/Kleinschreibung beachtet wird, müssen bei Verwendung von SQL in Anführungszeichen gesetzt werden. Diese Option erlaubt auch nicht-alphabetische Zeichen in Methodennamen. Standard: False.

    • max_batch_size: Maximale Batchgröße, die die Methode beim Aufruf im Warehouse akzeptiert. Standard: None (Batchgröße wird automatisch ermittelt)

Einzelne Modelltypen können zusätzliche Optionen unterstützen. Siehe Hinweise zu spezifischen Modelltypen.

pip_requirements

Liste der Paketspezifikationen für PyPI-Pakete, die für das Modell erforderlich sind.

python_version

Python-Version, in der das Modell ausgeführt werden soll. Der Standardwert ist None, wodurch die letzte im Warehouse verfügbare Version verwendet wird.

sample_input_data

DataFrame mit Stichprobe als Eingabedaten. Die für das Modell erforderlichen Feature-Namen (Merkmale) und deren Typen werden aus diesem DataFrame extrahiert. Bei allen Modellen außer Snowpark ML- und MLFlow-Modellen muss entweder dieses Argument oder signatures angegeben werden.

signatures

Methodensignaturen des Modells als Zuordnung des Namens der Zielmethode zu Signaturen von Eingabe und Ausgabe. Bei allen Modellen außer Snowpark ML- und MLFlow-Modellen muss entweder dieses Argument oder sample_input_data angegeben werden.

log_model gibt ein snowflake.ml.model.ModelVersion-Objekt zurück, das die Version des Modells repräsentiert, die der Registry hinzugefügt wurde.

Nach dem Registrieren kann das Modell selbst nicht mehr geändert werden (aber seine Metadaten). Um ein Modell und alle seine Versionen zu löschen, verwenden Sie die Methode delete_model der Registry.

Löschen von Modellen

Verwenden Sie die delete_model-Methode der Registry, um ein Modell und alle seine Versionen zu löschen.

reg.delete_model("mymodel")
Copy

Abrufen von Modellen aus der Registry

Um Informationen zu jedem Modell zu erhalten, verwenden Sie die Methode show_models.

model_df = reg.show_models()
Copy

Das Ergebnis von show_models ist ein pandas-DataFrame. Die verfügbaren Spalten sind unten aufgeführt.

Spalte

Beschreibung

created_on

Datum und Uhrzeit der Erstellung des Modells.

name

Name des Modells.

database_name

Datenbank, in der das Modell gespeichert ist.

schema_name

Schema, in dem das Modell gespeichert ist.

owner

Rolle, die Eigentümer des Modells ist.

comment

Kommentar zum Modell.

versions

JSON-Array mit den Versionen des Modells.

default_version_name

Version des Modells, wenn auf das Modell ohne Versionsangabe verwiesen wird.

Um stattdessen eine Liste der Modelle in der Registry zu erhalten, jedes als Model-Instanz, verwenden Sie die Methode models.

model_list = reg.models()
Copy

Um eine Referenz auf ein bestimmtes Modell aus der Registry über den Namen zu erhalten, verwenden Sie die Methode get_model der Registry. Diese Methode gibt eine Model-Instanz zurück.

m = reg.get_model("MyModel")
Copy

Bemerkung

Model-Instanzen sind keine Kopien des ursprünglichen protokollierten Python-Modellobjekts, sondern Referenzen auf das zugrunde liegende Modellobjekt in der Registry.

Sobald Sie einen Verweis auf ein Modell haben, entweder eines aus der von der Methode models zurückgegebenen Liste oder eines, das mit get_model abgerufen wurde, können Sie deren Metadaten und Versionen weiterverwenden.

Anzeigen und Aktualisieren der Metadaten eines Modells

Sie können die Metadatenattribute eines Modells in der Registry anzeigen und aktualisieren, einschließlich des Kommentars, der Tags und der Kennzahlen.

Abrufen und Aktualisieren von Kommentaren

Verwenden Sie das Attribut comment des Modells, um den Kommentar des Modells abzurufen und zu aktualisieren.

print(m.comment)
m.comment = "A better description than the one I provided originally"
Copy

Bemerkung

Das description-Attribut ist ein Alias für comment. Der obige Code kann auch wie folgt geschrieben werden:

print(m.description)
m.description = "A better description than the one I provided originally"
Copy

Abrufen und Aktualisieren von Tags

Tags sind Metadaten, mit denen der Zweck eines Modells, der Algorithmus, das Trainings-Dataset, die Lebenszyklusphase oder andere von Ihnen gewählte Informationen erfasst werden können. Sie können die Tags beim Registrieren des Modells oder zu einem beliebigen späteren Zeitpunkt setzen. Sie können auch die Werte vorhandener Tags aktualisieren oder Tags ganz entfernen.

Bemerkung

Die Namen aller Tags (und möglicherweise ihre möglichen Werte) müssen im Voraus mit CREATE TAG definiert werden. Siehe Objekt-Tagging.

Um alle Tags eines Modells in Form eines Python-Dictionarys zu erhalten, verwenden Sie show_tags.

print(m.show_tags())
Copy

Um ein neues Tag hinzuzufügen oder den Wert eines vorhandenen Tags zu ändern, verwenden Sie set_tag.

m.set_tag("live_version", "1")
Copy

Um den Wert eines Tags abzurufen, verwenden Sie get_tag:

m.get_tag("live_version")
Copy

Um ein Tag zu entfernen, verwenden Sie unset_tag.

model.unset_tag("live_version")
Copy

Verwenden von Modellversionen

Ein Modell kann eine beliebige Anzahl von Versionen haben, die jeweils durch eine Zeichenfolge gekennzeichnet sind. Sie können für den Versionsnamen jede beliebige Namenskonvention verwenden. Beim Protokollieren eines Modells wird eine spezifische Version des Modells protokolliert. Um weitere Versionen eines Modells zu protokollieren, rufen Sie log_model erneut mit demselben model_name-Wert, aber einem anderen version_name-Wert auf.

Eine Version eines Modells wird durch eine Instanz der Klasse snowflake.ml.model.ModelVersion repräsentiert.

Um eine Liste aller Versionen eines Modells zu erhalten, rufen Sie die Methode versions des Modellobjekts auf. Das Ergebnis ist eine Liste von ModelVersion-Instanzen.

version_list = m.versions()
Copy

Um stattdessen Informationen zu jedem Modell als DataFrame zu erhalten, rufen Sie die Methode show_versions des Modells auf.

version_df = m.show_versions()
Copy

Der Ergebnis-DataFrame enthält die folgenden Spalten.

Spalte

Beschreibung

created_on

Datum und Uhrzeit der Erstellung der Modellversion.

name

Name der Version.

database_name

Datenbank, in der die Version gespeichert ist.

schema_name

Schema, in dem die Version gespeichert ist.

model_name

Name des Modells, zu dem diese Version gehört.

is_default_version

Boolescher Wert, der angibt, ob diese Version die Standardversion des Modells ist.

functions

JSON-Array mit den Namen der in dieser Version verfügbaren Funktionen.

metadata

JSON-Objekt, das Metadaten als Schlüssel-Wert-Paare enthält ({}, wenn keine Metadaten angegeben sind).

user_data

JSON-Objekt aus dem Abschnitt user_data der Manifest-Datei mit der Modelldefinition ({}, wenn keine Benutzerdaten angegeben sind).

Löschen von Modellversionen

Sie können eine Modellversion mit der delete_version-Methode des Modells löschen.

m.delete_version("rc1")
Copy

Standardversion

Eine Version eines Modells kann als Standardmodell festgelegt werden. Sie können das default-Attribut des Modells abrufen oder festlegen, um die aktuelle Standardversion (als ModelVersion-Objekt) zu erhalten bzw. zu ändern (unter Verwendung einer Zeichenfolge (String)).

default_version = m.default
m.default = "2"
Copy

Abrufen einer Referenz auf eine Modellversion

Um eine Referenz auf eine bestimmte Version eines Modells als ModelVersion-Instanz zu erhalten, verwenden Sie die version-Methode des Modells. Verwenden Sie das default-Attribut des Modells, um die Standardversion des Modells zu abzurufen.

mv = m.version("1")
mv = m.default
Copy

Sobald Sie einen Verweis auf eine bestimmte Version eines Modells haben (wie die Variable mv in unserem obigen Beispiel), können Sie dessen Kommentare oder Kennzahlen abrufen oder aktualisieren und die Methoden (Funktionen) des Modells aufrufen, wie in den folgenden Abschnitten beschrieben.

Abrufen und Aktualisieren von Kommentaren

Wie bei Modellen können auch Modellversionen Kommentare haben, die über das Attribut comment oder description der Modellversion abgerufen und gesetzt werden können.

print(mv.comment)
print(mv.description)

mv.comment = "A model version comment"
mv.description = "Same as setting the comment"
Copy

Abrufen und Aktualisieren von Kennzahlen

Kennzahlen (Metriken) sind Schlüssel-Wert-Paare, die dazu dienen, die Vorhersagegenauigkeit und andere Eigenschaften der Modellversion zu überwachen. Sie können die Kennzahlen beim Erstellen einer Modellversion oder mit der Methode set_metric festlegen. Der Wert einer Kennzahl kann jedes Python-Objekt sein, das in JSON serialisiert werden kann, einschließlich Zahlen, Zeichenfolgen (Strings), Listen und Dictionarys. Im Gegensatz zu Tags müssen die Namen und möglichen Werte von Kennzahlen nicht im Voraus festgelegt werden.

Eine Kennzahl für die Testgenauigkeit kann mit accuracy_score von sklearn erstellt werden:

from sklearn import metrics

test_accuracy = metrics.accuracy_score(test_labels, prediction)
Copy

Die Wahrheitsmatrix (Konfusionsmatrix) kann auf ähnliche Weise mit sklearn generiert werden:

test_confusion_matrix = metrics.confusion_matrix(test_labels, prediction)
Copy

Dann können diese Werte wie folgt als Kennzahlen festgelegt werden.

# scalar metric
mv.set_metric("test_accuracy", test_accuracy)

# hierarchical (dictionary) metric
mv.set_metric("evaluation_info", {"dataset_used": "my_dataset", "accuracy": test_accuracy, "f1_score": f1_score})

# multivalent (matrix) metric
mv.set_metric("confusion_matrix", test_confusion_matrix)
Copy

Um die Kennzahlen einer Modellversion als Python-Dictionary abzurufen, verwenden Sie show_metrics.

metrics = mv.show_metrics()
Copy

Um eine Kennzahl zu löschen, rufen Sie delete_metric auf.

mv.delete_metric("test_accuracy")
Copy

Aufrufen von Modellmethoden

Modellversionen können Methoden haben, d. h. angehängte Funktionen, die ausgeführt werden können, um Inferenzen oder andere Modelloperationen auszuführen. Die Versionen eines Modells können unterschiedliche Methoden haben, und auch die Signaturen dieser Methoden können sich unterscheiden.

Um eine Methode einer Modellversion aufzurufen, verwenden Sie mv.run, geben den Namen der aufzurufenden Funktion an und übergeben einen DataFrame, der die Inferenzdaten und alle anderen erforderlichen Parameter enthält. Die Methode wird in einem Snowflake-Warehouse ausgeführt.

Bemerkung

Beim Aufrufen einer Methode wird diese in dem Warehouse ausgeführt, das in der Sitzung angegeben ist, die Sie für die Verbindung mit der Registry verwenden. Siehe Angeben eines Warehouses.

Im folgenden Beispiel wird die Ausführung der Methode predict eines Modells gezeigt. Die predict-Methode dieses Modells benötigt außer den Inferenzdaten (hier test_features) keine weiteren Parameter. Wenn dies der Fall wäre, würden sie als zusätzliche Argumente nach den Inferenzdaten übergeben werden.

remote_prediction = mv.run(test_features, function_name="predict")
Copy

Um zu erfahren, welche Methoden für ein bestimmtes Modell aufgerufen werden können, rufen Sie mv.show_functions auf. Der Rückgabewert dieser Methode ist eine Liste von ModelFunctionInfo-Objekten. Jedes dieser Objekte enthält die folgenden Attribute:

  • name: Name der Funktion, die von Python oder SQL aufgerufen werden kann.

  • target_method: Name der ursprünglichen Methode in dem ursprünglichen protokollierten Python-Modell.

Verwenden der Modell-Registry in SQL

Da Modelle First-Class-Objekte auf Schemaebene sind, bietet Snowflake SQL Befehle für deren Verwendung. Diese sind:

Bemerkung

Snowflake SQL enthält zwar Befehle zum Erstellen von Modellen und Versionen, diese sind jedoch für die Verwendung mit der Python-API der Snowpark Model Registry gedacht. Protokollieren Sie Modelle in Python wie unter Registrieren von Modellen und Versionen gezeigt.

Aufrufen von Modellmethoden in SQL

Sie können Methoden eines Modells in SQL mit der model_name!method_name(...)-Syntax aufrufen. Die für ein Modell verfügbaren Methoden werden durch die zugrunde liegende Python-Modellklasse bestimmt. Viele Modelle verwenden zum Beispiel eine Methode namens predict für die Inferenz.

Um eine Methode der aktuellen Version eines Modells aufzurufen, verwenden Sie die hier gezeigte Syntax, wobei Sie zwischen den Klammern ggf. verfügbare Argumente an die Methode übergeben sowie in der FROM-Klausel den Namen der Tabelle, die die Inferenzdaten enthält.

SELECT <model_name>!<method_name>(...) FROM <table_name>;
Copy

Um eine Methode einer bestimmten Version eines Modells aufzurufen, erstellen Sie zunächst einen Alias für die spezifische Version des Modells und rufen dann die gewünschte Methode über den Alias auf.

WITH <model_version_alias> AS MODEL <model_name> VERSION <version>
    SELECT <model_version_alias>!<method_name>(...) FROM <table_name>;
Copy

Hinweise zu Kosten

Für die Verwendung der Snowpark ML Model Registry fallen die üblichen verbrauchsabhängigen Kosten von Snowflake an. Dazu zählen:

  • Kosten für die Speicherung von Modellartefakten, Metadaten und Funktionen. Allgemeine Informationen zu Speicherkosten finden Sie unter Untersuchen der Speicherkosten.

  • Kosten für das Kopieren von Dateien zwischen Stagingbereichen und Snowflake. Siehe COPY FILES.

  • Kosten für serverlose Modellobjektoperationen über die Snowsight-UI oder die SQL- oder Python-Schnittstelle, z. B. das Anzeigen von Modellen und Modellversionen und das Ändern der Kommentare, Tags und Kennzahlen von Modellen.

  • Warehouse-Computekosten, die je nach Typ des Modells und der Menge der für Interferenz verwendeten Daten variieren. Allgemeine Informationen zu Snowflake-Computekosten finden Sie unter Erläuterungen zu den Computekosten. Warehouse-Computekosten fallen bei:

    • Operationen zum Erstellen von Modellen und Versionen

    • Aufrufen der Methoden eines Modells

Hinweise zu spezifischen Modelltypen

In diesem Abschnitt finden Sie zusätzliche Informationen zum Protokollieren bestimmter Modelltypen in der Snowpark Model Registry.

Snowpark-ML

Die Registry unterstützt Modelle, die mit Snowpark ML-Modellierungs-APIs (von snowpark.ml.modeling.framework.base.BaseEstimator abgeleitete Modelle) erstellt wurden. Die folgenden zusätzlichen Optionen können im options-Dictionary beim Aufruf von log_model verwendet werden.

Option

Beschreibung

target_methods

Liste mit den Namen der für das Modellobjekt verfügbaren Methoden. Snowpark ML-Modelle haben standardmäßig die folgenden Zielmethoden, vorausgesetzt, die Methode existiert: predict, transform, predict_proba, predict_log_proba, decision_function

Beim Protokollieren eines Snowpark ML-Modells müssen Sie sample_input_data oder signatures nicht angeben. Diese Werte werden während der Anpassung automatisch abgeleitet.

Beispiel

import pandas as pd
import numpy as np
from sklearn import datasets
from snowflake.ml.modeling.xgboost import XGBClassifier

iris = datasets.load_iris()
df = pd.DataFrame(data=np.c_[iris["data"], iris["target"]], columns=iris["feature_names"] + ["target"])
df.columns = [s.replace(" (CM)", "").replace(" ", "") for s in df.columns.str.upper()]

input_cols = ["SEPALLENGTH", "SEPALWIDTH", "PETALLENGTH", "PETALWIDTH"]
label_cols = "TARGET"
output_cols = "PREDICTED_TARGET"

clf_xgb = XGBClassifier(
        input_cols=input_cols, output_cols=output_cols, label_cols=label_cols, drop_input_cols=True
)
clf_xgb.fit(df)
model_ref = registry.log_model(
    clf_xgb,
    model_name="XGBClassifier",
    version_name="v1",
)
model_ref.run(df.drop(columns=label_cols).head(10), function_name='predict_proba')
Copy

scikit-learn

Die Registry unterstützt Modelle, die mit Scikit-learn erstellt wurden (von sklearn.base.BaseEstimator oder sklearn.pipeline.Pipeline abgeleitete Modelle). Die folgenden zusätzlichen Optionen können im options-Dictionary beim Aufruf von log_model verwendet werden.

Option

Beschreibung

target_methods

Liste der Namen der Methoden, die für das Modellobjekt verfügbar sind. Scikit-learn-Modelle haben standardmäßig die folgenden Zielmethoden, vorausgesetzt, die Methode existiert: predict, transform, predict_proba, predict_log_proba, decision_function

Sie müssen entweder den Parameter sample_input_data oder signatures angeben, wenn Sie ein Scikit-learn-Modell protokollieren, damit die Registry die Signaturen der Zielmethoden kennt.

Beispiel

from sklearn import datasets, ensemble

iris_X, iris_y = datasets.load_iris(return_X_y=True, as_frame=True)
model = ensemble.RandomForestClassifier(random_state=42)
model.fit(iris_X, iris_y)
model_ref = registry.log_model(
    model,
    model_name="RandomForestClassifier",
    version_name="v1",
    sample_input_data=iris_X,
    options={
        "method_options": {
            "predict": {"case_sensitive": True},
            "predict_proba": {"case_sensitive": True},
            "predict_log_proba": {"case_sensitive": True},
        }
    },
)
model_ref.run(iris_X[-10:], function_name='"predict_proba"')
Copy

XGBoost

Die Registry unterstützt Modelle, die mit XGBoost erstellt wurden (von xgboost.XGBModel oder xgboost.Booster abgeleitete Modelle). Die folgenden zusätzlichen Optionen können im options-Dictionary beim Aufruf von log_model verwendet werden.

Option

Beschreibung

target_methods

Liste mit den Namen der für das Modellobjekt verfügbaren Methoden. Von XGBModel abgeleitete Modelle haben standardmäßig die folgenden Zielmethoden, vorausgesetzt, die Methode existiert: predict, predict_proba, apply. Von Booster abgeleitete Modelle haben standardmäßig die Methode predict.

cuda_version

Die Version der CUDA-Laufzeitumgebung, die beim Bereitstellen auf einer Plattform mit GPU verwendet werden soll. Der Standardwert ist 11.7. Wird das Modell manuell auf None gesetzt, kann es nicht auf einer Plattform mit GPU eingesetzt werden.

Beim Protokollieren eines XGBoost-Modells müssen Sie entweder den Parameter sample_input_data oder signatures angeben, damit die Registry die Signaturen der Zielmethoden kennt.

Beispiel

import xgboost
from sklearn import datasets, model_selection

cal_X, cal_y = datasets.load_breast_cancer(as_frame=True, return_X_y=True)
cal_X_train, cal_X_test, cal_y_train, cal_y_test = model_selection.train_test_split(cal_X, cal_y)
params = dict(n_estimators=100, reg_lambda=1, gamma=0, max_depth=3, objective="binary:logistic")
regressor = xgboost.train(params, xgboost.DMatrix(data=cal_X_train, label=cal_y_train))
model_ref = registry.log_model(
    regressor,
    model_name="xgBooster",
    version_name="v1",
    sample_input_data=cal_X_test,
    options={
        "target_methods": ["predict"],
        "method_options": {
            "predict": {"case_sensitive": True},
        },
    },
)
model_ref.run(cal_X_test[-10:])
Copy

PyTorch

Die Registry unterstützt PyTorch-Modelle (von torch.nn.Module oder torch.jit.ModuleScript abgeleitete Klassen), wenn die forward-Methode des Modells eine oder mehrere torch.Tensor-Instanzen als Eingabe akzeptiert und einen torch.Tensor-Wert oder ein Tupel davon zurückgibt. Die Registry konvertiert zwischen pandas-DataFrames und Tensoren, wenn sie das Modell aufruft und die Ergebnisse zurückgibt. Tensoren entsprechen den Spalten im Datenframe.

Angenommen, Ihr Modell akzeptiert zwei Tensoren wie die folgenden:

import torch

class TorchModel(torch.nn.Module):
    def __init__(self, n_input: int, n_hidden: int, n_out: int, dtype: torch.dtype = torch.float32) -> None:
        super().__init__()
        self.model = torch.nn.Sequential(
            torch.nn.Linear(n_input, n_hidden, dtype=dtype),
            torch.nn.ReLU(),
            torch.nn.Linear(n_hidden, n_out, dtype=dtype),
            torch.nn.Sigmoid(),
        )

    def forward(self, tensor_1: torch.Tensor, tensor_2: torch.Tensor) -> torch.Tensor:
        return self.model(tensor_1) + self.model(tensor_2)
Copy

Wenn Sie torch.Tensor([[1,2],[3,4]]) als tensor_1 und torch.Tensor([[5,6], [7,8]]) als tensor_2 übergeben möchten, erstellen Sie wie folgt einen DataFrame, den Sie an das Modell übergeben.

import pandas as pd
tensors = pd.DataFrame([[[1,2],[5,6]],[[3,4],[7,8]]])
Copy

Das tensors-DataFrame sieht dann wie folgt aus.

        0       1
0  [1, 2]  [5, 6]
1  [3, 4]  [7, 8]
Copy

Ähnlich verhält es sich, wenn Ihr Modell zwei Tensoren zurückgibt, z. B. (torch.Tensor([[1,2],[3,4]]), torch.Tensor([[5,6], [7,8]])): Das Ergebnis ist ein DataFrame wie der obige.

Wenn Sie eine Stichprobe als Eingabedaten für ein PyTorch-Modell bereitstellen, müssen Sie entweder eine Liste von Tensoren (die in einen pandas-DataFrame umgewandelt werden) oder einen DataFrame bereitstellen. Eine Liste kann einen einzelnen Tensor enthalten, aber ein Tensor allein wird nicht akzeptiert.

Protokollieren des Modells

Die folgenden zusätzlichen Optionen können im options-Dictionary beim Aufruf von log_model verwendet werden.

Option

Beschreibung

target_methods

Liste mit den Namen der für das Modellobjekt verfügbaren Methoden. Der Standardwert bei PyTorch-Modellen ist forward.

cuda_version

Die Version der CUDA-Laufzeitumgebung, die beim Bereitstellen auf einer Plattform mit GPU verwendet werden soll. Der Standardwert ist 11.7. Wird das Modell manuell auf None gesetzt, kann es nicht auf einer Plattform mit GPU eingesetzt werden.

Sie müssen entweder den Parameter sample_input_data oder signatures angeben, wenn Sie ein PyTorch-Modell protokollieren, damit die Registry die Signaturen der Zielmethoden kennt.

Beispiel

import torch
import numpy as np

class TorchModel(torch.nn.Module):
        def __init__(self, n_input: int, n_hidden: int, n_out: int, dtype: torch.dtype = torch.float32) -> None:
                super().__init__()
                self.model = torch.nn.Sequential(
                        torch.nn.Linear(n_input, n_hidden, dtype=dtype),
                        torch.nn.ReLU(),
                        torch.nn.Linear(n_hidden, n_out, dtype=dtype),
                        torch.nn.Sigmoid(),
                )

        def forward(self, tensor: torch.Tensor) -> torch.Tensor:
                return self.model(tensor)

n_input, n_hidden, n_out, batch_size, learning_rate = 10, 15, 1, 100, 0.01
dtype = torch.float32
x = np.random.rand(batch_size, n_input)
data_x = torch.from_numpy(x).to(dtype=dtype)
data_y = (torch.rand(size=(batch_size, 1)) < 0.5).to(dtype=dtype)

model = TorchModel(n_input, n_hidden, n_out, dtype=dtype)
loss_function = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
for _epoch in range(100):
        pred_y = model.forward(data_x)
        loss = loss_function(pred_y, data_y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()


model_ref = registry.log_model(
    model,
    model_name="torchModel",
    version_name="v1",
    sample_input_data=[data_x],
)
model_ref.run([data_x])
Copy

TensorFlow

Modelle, die tensorflow.Module oder tensorflow.keras.Model erweitern, werden unterstützt, wenn sie Tensoren akzeptieren und zurückgeben und kompilierbar oder bereits kompiliert sind.

  • Die __call__-Methode für einen tensorflow.Module-Wert oder die call-Methode für einen tensorflow.keras.Model-Wert akzeptiert einen oder mehrere tensorflow.Tensor-Werte oder tensorflow.Variable-Werte als Eingabe und gibt einen tensorflow.Tensor- oder tensorflow.Variable-Wert oder ein Tupel eines dieser Typen zurück.

  • Wenn Ihr Modell Module erweitert, muss es kompilierbar sein, d. h. die __call__-Methode ist mit @tensorflow.function dekoriert. Siehe tf.function-Dokumentation. Wenn es Model erweitert, muss es kompiliert werden. Siehe Dokumentation zum Kompilieren.

Die Registry konvertiert zwischen pandas-DataFrames und Tensoren, wenn sie das Modell aufruft und die Ergebnisse zurückgibt. Tensoren entsprechen den Spalten im Datenframe.

Angenommen, Ihr Modell akzeptiert zwei Tensoren wie die folgenden:

import tensorflow as tf

class KerasModel(tf.keras.Model):
    def  __init__(self, n_hidden: int, n_out: int) -> None:
        super().__init__()
        self.fc_1 = tf.keras.layers.Dense(n_hidden, activation="relu")
        self.fc_2 = tf.keras.layers.Dense(n_out, activation="sigmoid")

    def call(self, tensor_1: tf.Tensor, tensor_2: tf.Tensor) -> tf.Tensor:
        input = tensor_1 + tensor_2
        x = self.fc_1(input)
        x = self.fc_2(x)
        return x
Copy

Wenn Sie tf.Tensor([[1,2],[3,4]]) als tensor_1 und tf.Tensor([[5,6], [7,8]]) als tensor_2 übergeben möchten, erstellen Sie wie folgt einen DataFrame, den Sie an das Modell übergeben.

import pandas as pd
tensors = pd.DataFrame([[[1,2],[5,6]],[[3,4],[7,8]]])
Copy

Das tensors-DataFrame sieht dann wie folgt aus.

        0       1
0  [1, 2]  [5, 6]
1  [3, 4]  [7, 8]
Copy

Ähnlich verhält es sich, wenn Ihr Modell zwei Tensoren zurückgibt, z. B. (tf.Tensor([[1,2],[3,4]]), tf.Tensor([[5,6], [7,8]])): Das Ergebnis ist ein DataFrame wie der obige.

Wenn Sie eine Stichprobe als Eingabedaten für ein TensorFlow-Modell bereitstellen, müssen Sie entweder eine Liste von Tensoren (die in einen pandas-DataFrame umgewandelt werden) oder einen DataFrame bereitstellen. Eine Liste kann einen einzelnen Tensor enthalten, aber ein Tensor allein wird nicht akzeptiert.

Protokollieren des Modells

Die folgenden zusätzlichen Optionen können im options-Dictionary beim Aufruf von log_model verwendet werden.

Option

Beschreibung

target_methods

Liste mit den Namen der für das Modellobjekt verfügbaren Methoden. Der Standardwert bei TensorFlow-Modellen ist forward.

cuda_version

Die Version der CUDA-Laufzeitumgebung, die beim Bereitstellen auf einer Plattform mit GPU verwendet werden soll. Der Standardwert ist 11.7. Wird das Modell manuell auf None gesetzt, kann es nicht auf einer Plattform mit GPU eingesetzt werden.

Sie müssen entweder den Parameter sample_input_data oder signatures angeben, wenn Sie ein TensorFlow-Modell protokollieren, damit die Registry die Signaturen der Zielmethoden kennt.

Beispiel

import tensorflow as tf
import numpy as np

class KerasModel(tf.keras.Model):
        def __init__(self, n_hidden: int, n_out: int) -> None:
                super().__init__()
                self.fc_1 = tf.keras.layers.Dense(n_hidden, activation="relu")
                self.fc_2 = tf.keras.layers.Dense(n_out, activation="sigmoid")

        def call(self, tensor: tf.Tensor) -> tf.Tensor:
                input = tensor
                x = self.fc_1(input)
                x = self.fc_2(x)
                return x

n_input, n_hidden, n_out, batch_size, learning_rate = 10, 15, 1, 100, 0.01
dtype = tf.float32
x = np.random.rand(batch_size, n_input)
data_x = tf.convert_to_tensor(x, dtype=dtype)
raw_data_y = tf.random.uniform((batch_size, 1))
raw_data_y = tf.where(raw_data_y > 0.5, tf.ones_like(raw_data_y), tf.zeros_like(raw_data_y))
data_y = tf.cast(raw_data_y, dtype=dtype)

model = KerasModel(n_hidden, n_out)
model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=learning_rate), loss=tf.keras.losses.MeanSquaredError())
model.fit(data_x, data_y, batch_size=batch_size, epochs=100)

model_ref = registry.log_model(
    model,
    model_name="tfModel",
    version_name="v1",
    sample_input_data=[data_x],
)
model_ref.run([data_x])
Copy

MLFlow

MLFlow-Modelle, die eine PyFunc-Konfiguration bereitstellen, werden unterstützt. Wenn Ihr MLFlow-Modell eine Signatur hat, wird das signature-Argument aus dem Modell abgeleitet. Andernfalls müssen Sie entweder signature oder sample_input_data angeben.

Die folgenden zusätzlichen Optionen können im options-Dictionary beim Aufruf von log_model verwendet werden.

Option

Beschreibung

model_uri

Die URI der Artefakte des MLFlow-Modells. Muss angegeben werden, wenn es in den Metadaten des Modells nicht als model.metadata.get_model_info().model_uri verfügbar ist.

ignore_mlflow_metadata

Wenn True, werden die Metadaten des Modells nicht in das Modellobjekt in der Registry importiert. Standard: False

ignore_mlflow_dependencies

Wenn True, werden die Abhängigkeiten in den Metadaten des Modells ignoriert, was aufgrund der Einschränkungen hinsichtlich der verfügbaren Pakete in Snowflake-Warehouses nützlich ist. Standard: False

Beispiel

import mlflow
from sklearn import datasets, model_selection, ensemble

db = datasets.load_diabetes(as_frame=True)
X_train, X_test, y_train, y_test = model_selection.train_test_split(db.data, db.target)
with mlflow.start_run() as run:
    rf = ensemble.RandomForestRegressor(n_estimators=100, max_depth=6, max_features=3)
    rf.fit(X_train, y_train)

    # Use the model to make predictions on the test dataset.
    predictions = rf.predict(X_test)
    signature = mlflow.models.signature.infer_signature(X_test, predictions)
    mlflow.sklearn.log_model(
        rf,
        "model",
        signature=signature,
    )
    run_id = run.info.run_id


model_ref = registry.log_model(
    mlflow.pyfunc.load_model(f"runs:/{run_id}/model"),
    model_name="mlflowModel",
    version_name="v1",
    conda_dependencies=["mlflow<=2.4.0", "scikit-learn", "scipy"],
    options={"ignore_mlflow_dependencies": True}
)
model_ref.run(X_test)
Copy

Hugging Face-Pipeline

Die Registry unterstützt Hugging Face-Modellklassen, die als Transformer definiert sind, die von transformers.Pipeline abgeleitet sind. Der folgende Code ist ein Beispiel für das Protokollieren eines kompatiblen Modells.

lm_hf_model = transformers.pipeline(
    task="text-generation",
    model="bigscience/bloom-560m",
    token="...",  # Put your HuggingFace token here.
    return_full_text=False,
    max_new_tokens=100,
)

lmv = reg.log_model(lm_hf_model, model_name='bloom', version_name='v560m')
Copy

Wichtig

Ein auf huggingface_pipeline.HuggingFacePipelineModel basierendes Modell enthält nur Konfigurationsdaten. Die Modellgewichtungen werden bei jeder Verwendung des Modells vom Hugging Face Hub heruntergeladen.

Die Modell-Registry unterstützt derzeit nur die Bereitstellung von Modellen für Warehouses. Warehouses unterstützen einen Zugriff auf externe Netzwerke nur mit spezieller Konfiguration. Selbst wenn die erforderlichen Integrationen für den externen Zugriff erstellt wurden, gibt es derzeit keine Möglichkeit, anzugeben, welche Integrationen ein bestimmtes Modell benötigt.

Die derzeit Best Practice ist, stattdessen transformers.Pipeline zu verwenden, wie im obigen Beispiel gezeigt. Dadurch werden die Modellgewichtungen auf Ihr lokales System heruntergeladen und das gesamte Modell in das Warehouse hochgeladen. Das Ergebnis ist ein in sich geschlossenes Modell, das keinen Internetzugang benötigt.

Die Registry leitet das signatures-Argument ab, solange die Pipeline nur Aufgaben enthält, die in der folgenden Liste aufgeführt sind.

  • conversational

  • fill-mask

  • question-answering

  • summarization

  • table-question-answering

  • text2text-generation

  • text-classification (Alias sentiment-analysis)

  • text-generation

  • token-classification (Alias ner)

  • translation

  • translation_xx_to_yy

  • zero-shot-classification

Zum Anzeigen der abgeleiteten Signatur können Sie die show_functions-Methode verwenden. Das folgende Beispiel zeigt das Ergebnis von lmv.show_functions(), wobei lmv das oben protokollierte Modell ist.

{'name': '__CALL__',
  'target_method': '__call__',
  'signature': ModelSignature(
                      inputs=[
                          FeatureSpec(dtype=DataType.STRING, name='inputs')
                      ],
                      outputs=[
                          FeatureSpec(dtype=DataType.STRING, name='outputs')
                      ]
                  )}]
Copy

Mit diesen Informationen können Sie das Modell wie folgt aufrufen.

import pandas as pd
remote_prediction = lmv.run(pd.DataFrame(["Hello, how are you?"], columns=["inputs"]))
Copy

Nutzungshinweise

  • Viele Hugging Face-Modelle sind groß und passen nicht in ein Standard-Warehouse. Verwenden Sie ein Snowpark-optimiertes Warehouse, oder wählen Sie eine kleinere Version des Modells aus. Versuchen Sie zum Beispiel, statt des Modells Llama-2-70b-chat-hf das Modell Llama-2-7b-chat-hf zu verwenden.

  • Snowflake-Warehouses haben keine GPUs. Verwenden Sie nur CPU-optimierte Hugging Face-Modelle.

  • Einige Hugging Face-Transformatoren geben pro Eingabezeile ein Array von Dictionarys zurück. Die Registry konvertiert solche Ausgaben in eine Zeichenfolge, die eine JSON-Repräsentation des Arrays enthält. Die Mehrfach-Ausgabe der Fragebeantwortungsausgabe sieht zum Beispiel so aus:

    [{"score": 0.61094731092453, "start": 139, "end": 178, "answer": "learn more about the world of athletics"},
    {"score": 0.17750297486782074, "start": 139, "end": 180, "answer": "learn more about the world of athletics.\""}]
    
    Copy

Sie müssen entweder den Parameter sample_input_data oder signatures angeben, wenn Sie ein Hugging Face-Modell protokollieren, damit die Registry die Signaturen der Zielmethoden kennt.

Beispiel

# Prepare model
import transformers
import pandas as pd

finbert_model = transformers.pipeline(
    task="text-classification",
    model="ProsusAI/finbert",
    top_k=2,
)

# Log the model
mv = registry.log_model(
    finbert_model,
    model_name="finbert",
    version_name="v1",
)

# Use the model
mv.run(pd.DataFrame(
        [
            ["I have a problem with my Snowflake that needs to be resolved asap!!", ""],
            ["I would like to have udon for today's dinner.", ""],
        ]
    )
)
Copy

Ergebnis:

0  [{"label": "negative", "score": 0.8106237053871155}, {"label": "neutral", "score": 0.16587384045124054}]
1  [{"label": "neutral", "score": 0.9263970851898193}, {"label": "positive", "score": 0.05286872014403343}]
Copy