Snowpark ML Modeling: Entwicklung von ML-Modellen

Bemerkung

Die Snowpark ML Modeling-API ist ab Paketversion 1.1.1 allgemein verfügbar.

Die Snowpark ML Modeling-API verwendet bekannte Python-Frameworks wie Scikit-learn und XGBoost für die Vorverarbeitung von Daten, das Feature-Engineering und das Training von Modellen innerhalb von Snowflake.

Die Entwicklung von Modellen mit Snowpark ML Modeling bietet folgende Vorteile:

  • Feature-Engineering und Vorverarbeitung: Verbessern Sie die Performance und Skalierbarkeit mit verteilter Ausführung für häufig verwendete Scikit-learn-Vorverarbeitungsfunktionen.

  • Modelltraining: Beschleunigen Sie das Training für Scikit-learn-, XGBoost- und LightGBM-Modelle, ohne manuell gespeicherte Prozeduren oder benutzerdefinierte Funktionen (UDFs) erstellen zu müssen, durch Verwendung der verteilten Hyperparameter-Optimierung.

Die Snowpark ML Modeling-API bietet Schätzer- und Transformerfunktionen mit APIs, die denen der Bibliotheken scikit-learn, xgboost und lightgbm ähnlich sind. Sie können diese APIs verwenden, um Machine Learning-Modelle zu erstellen und zu trainieren, die mit Snowpark ML Operations verwendet werden können, wie z. B. die Snowpark Model Registry.

Tipp

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

Bemerkung

Bei diesem Thema wird vorausgesetzt, dass Sie Snowpark ML und dessen Abhängigkeiten bereits installiert haben. Siehe Installieren von Snowpark ML.

Beispiele

Schauen Sie sich die folgenden Beispiele an, um einen Eindruck von den Ähnlichkeiten der Snowpark ML Modeling-API mit den Bibliotheken für maschinelles Lernen zu erhalten, die Sie vielleicht kennen.

Vorverarbeitung

Dieses Beispiel veranschaulicht die Verwendung der Datenvorverarbeitungs- und Datentransformationsfunktionen von Snowpark ML Modeling. Die beiden im Beispiel verwendeten Vorverarbeitungsfunktionen (MixMaxScaler und OrdinalEncoder) nutzen die Snowflake-Engine für die verteilte Verarbeitung, um erhebliche Leistungsverbesserungen gegenüber clientseitigen oder gespeicherten Prozedurimplementierungen zu erzielen. Weitere Details dazu finden Sie unter Verteilte Vorverarbeitung.

import numpy as np
import pandas as pd
import random
import string

from sklearn.datasets import make_regression
from snowflake.ml.modeling.preprocessing import MinMaxScaler, OrdinalEncoder
from snowflake.ml.modeling.pipeline import Pipeline
from snowflake.snowpark import Session

# Create a session with your preferred method
# session =

NUMERICAL_COLS = ["X1", "X2", "X3"]
CATEGORICAL_COLS = ["C1", "C2", "C3"]
FEATURE_COLS = NUMERICAL_COLS + CATEGORICAL_COLS
CATEGORICAL_OUTPUT_COLS = ["C1_OUT", "C2_OUT", "C3_OUT"]
FEATURE_OUTPUT_COLS = ["X1_FEAT_OUT", "X2_FEAT_OUT", "X3_FEAT_OUT", "C1_FEAT_OUT", "C2_FEAT_OUT", "C3_FEAT_OUT"]

# Create a dataset with numerical and categorical features
X, _ = make_regression(
    n_samples=1000,
    n_features=3,
    noise=0.1,
    random_state=0,
)
X = pd.DataFrame(X, columns=NUMERICAL_COLS)

def generate_random_string(length):
    return "".join(random.choices(string.ascii_uppercase, k=length))

categorical_feature_length = 2
categorical_features = {}
for c in CATEGORICAL_COLS:
    categorical_column = [generate_random_string(categorical_feature_length) for _ in range(X.shape[0])]
    categorical_features[c] = categorical_column

X = X.assign(**categorical_features)

features_df = session.create_dataframe(X)

# Fit a pipeline with OrdinalEncoder and MinMaxScaler on Snowflake
pipeline = Pipeline(
    steps=[
        (
            "OE",
            OrdinalEncoder(
                input_cols=CATEGORICAL_COLS,
                output_cols=CATEGORICAL_OUTPUT_COLS,
            )
        ),
        (
            "MMS",
            MinMaxScaler(
                input_cols=NUMERICAL_COLS + CATEGORICAL_OUTPUT_COLS,
                output_cols=FEATURE_OUTPUT_COLS,
            )
        ),
    ]
)

pipeline.fit(features_df)

# Use the pipeline to transform a dataset.
result = pipeline.transform(features_df)
Copy

Training

Dieses Beispiel zeigt, wie ein einfaches xgboost-Klassifikatormodell mit Snowpark ML Modeling trainiert wird und dann Vorhersagen erstellt werden. Die Snowpark ML-API ist hier ähnlich wie xgboost, mit nur wenigen Unterschieden bezüglich der Angabe der Spalten. Weitere Informationen zu diesen Unterschieden finden Sie unter Allgemeine Unterschiede der API.

import pandas as pd
from sklearn.datasets import make_classification

from snowflake.ml.modeling.xgboost import XGBClassifier
from snowflake.ml.utils.connection_params import SnowflakeLoginOptions
from snowflake.snowpark import Session

# Create a session with your preferred method
# session =

FEATURE_COLS = ["X1", "X2", "X3", "X4", "X5", "X6"]
LABEL_COLS = ["Y"]
OUTPUT_COLS = ["PREDICTIONS"]

# Set up data.
X, y = make_classification(
    n_samples=40000,
    n_features=6,
    n_informative=4,
    n_redundant=1,
    random_state=0,
    shuffle=True,
)

X = pd.DataFrame(X, columns=FEATURE_COLS)
y = pd.DataFrame(y, columns=LABEL_COLS)

features_pandas = pd.concat([X, y], axis=1)
features_df = session.create_dataframe(features_pandas)

# Train an XGBoost model on snowflake.
xgboost_model = XGBClassifier(
    input_cols=FEATURE_COLS,
    label_cols=LABEL_COLS,
    output_cols=OUTPUT_COLS
)

xgboost_model.fit(features_df)

# Use the model to make predictions.
predictions = xgboost_model.predict(features_df)
predictions[OUTPUT_COLS].show()
Copy

Feature-Vorverarbeitung von Merkmalen und Training auf nicht synthetischen Daten

In diesem Beispiel werden die Daten hochenergetischer Gammateilchen von einem bodengestützten Luft-Tscherenkow-Teleskop verwendet. Das Teleskop beobachtet hochenergetische Gammateilchen, indem es sich die Strahlung geladener Teilchen zunutze macht, die in den von den Gammastrahlen ausgelösten elektromagnetischen Schauern erzeugt werden. Der Detektor erfasst die Cherenkov-Strahlung (sichtbare bis ultraviolette Wellenlängen), die durch die Atmosphäre dringt, und ermöglicht so die Rekonstruktion der Parameter des Gammaschauers. Das Teleskop spürt auch Hadronenstrahlen auf, die in kosmischen Schauern häufig vorkommen und Signale erzeugen, die Gammastrahlen nachahmen.

Ziel ist es, ein Klassifizierungsmodell zur Unterscheidung von Gammastrahlen und Hadronenstrahlen zu entwickeln. Das Modell ermöglicht es den Wissenschaftlern, das Hintergrundrauschen herauszufiltern und sich auf die echten Gammastrahlensignale zu konzentrieren. Gammastrahlen ermöglichen es den Wissenschaftlern, kosmische Ereignisse wie die Geburt und das Sterben von Sternen, kosmische Explosionen und das Verhalten von Materie unter extremen Bedingungen zu beobachten.

Die Teilchendaten stehen zum Download bereit unter MAGIC-Gammateleskop. Laden Sie die Daten herunter, und entpacken Sie sie. Setzen Sie die Variable DATA_FILE_PATH so, dass sie auf die Datendatei verweist, und führen Sie den folgenden Code aus, um die Daten in Snowflake zu laden.

DATA_FILE_PATH = "~/Downloads/magic+gamma+telescope/magic04.data"

# Setup
from snowflake.ml.utils.connection_params import SnowflakeLoginOptions
from snowflake.snowpark import Session
import posixpath
import os

##
# Note: Create session https://docs.snowflake.com/en/developer-guide/snowpark/reference/python/latest/api/snowflake.snowpark.Session
##
session = Session.builder.configs(SnowflakeLoginOptions()).create()

session.sql("""
CREATE OR REPLACE TABLE Gamma_Telescope_Data(
    F_LENGTH FLOAT,
    F_WIDTH FLOAT,
    F_SIZE FLOAT,
    F_CONC FLOAT,
    F_CONC1 FLOAT,
    F_ASYM FLOAT,
    F_M3_LONG FLOAT,
    F_M3_TRANS FLOAT,
    F_ALPHA FLOAT,
    F_DIST FLOAT,
    CLASS VARCHAR(10))
""").collect()
session.sql("CREATE OR REPLACE STAGE SNOWPARK_ML_TEST_DATA_STAGE").collect()
session.file.put(
    DATA_FILE_PATH,
    "SNOWPARK_ML_TEST_DATA_STAGE/magic04.data",
    auto_compress=False,
    overwrite=True,
)

session.sql("""
COPY INTO Gamma_Telescope_Data FROM @SNOWPARK_ML_TEST_DATA_STAGE/magic04.data
FILE_FORMAT = (TYPE = 'CSV' field_optionally_enclosed_by='"',SKIP_HEADER = 0);
""").collect()

session.sql("select * from Gamma_Telescope_Data limit 5").collect()
Copy

Sobald Sie die Daten geladen haben, verwenden Sie den folgenden Code zum Trainieren und Vorhersagen unter Verwendung der folgenden Schritte.

  • Nehmen Sie eine Vorverarbeitung der Daten vor:

    • Ersetzen Sie fehlende Werte durch den Mittelwert.

    • Zentrieren Sie die Daten mit einem Standard-Skalierer.

  • Trainieren eines xgboost-Klassifikators, um den Typ der Ereignisse zu bestimmen.

  • Testen der Genauigkeit des Modells anhand von Trainings- und Test-Datensets.

from snowflake.ml.utils.connection_params import SnowflakeLoginOptions
from snowflake.snowpark import Session, DataFrame

from snowflake.ml.modeling.preprocessing import StandardScaler
from snowflake.ml.modeling.impute import SimpleImputer
from snowflake.ml.modeling.pipeline import Pipeline
from snowflake.ml.modeling.xgboost import XGBClassifier

from snowflake.ml.modeling.metrics import accuracy_score

##
# Note: Create session https://docs.snowflake.com/en/developer-guide/snowpark/reference/python/latest/api/snowflake.snowpark.Session
##
session = Session.builder.configs(SnowflakeLoginOptions()).create()

# Step 1: Create train and test dataframes
all_data = session.sql("select *, IFF(CLASS = 'g', 1.0, 0.0) as LABEL from Gamma_Telescope_Data").drop("CLASS")
train_data, test_data = all_data.random_split(weights=[0.9, 0.1], seed=0)

# Step 2: Construct training pipeline with preprocessing and modeling steps
FEATURE_COLS = [c for c in train_data.columns if c != "LABEL"]
LABEL_COLS = ["LABEL"]

pipeline = Pipeline(steps = [
    ("impute", SimpleImputer(input_cols=FEATURE_COLS, output_cols=FEATURE_COLS)),
    ("scaler", StandardScaler(input_cols=FEATURE_COLS, output_cols=FEATURE_COLS)),
    ("model", XGBClassifier(input_cols=FEATURE_COLS, label_cols=LABEL_COLS))
])

# Step 3: Train
pipeline.fit(train_data)

# Step 4: Eval
predict_on_training_data = pipeline.predict(train_data)
training_accuracy = accuracy_score(df=predict_on_training_data, y_true_col_names=["LABEL"], y_pred_col_names=["OUTPUT_LABEL"])

predict_on_test_data = pipeline.predict(test_data)
eval_accuracy = accuracy_score(df=predict_on_test_data, y_true_col_names=["LABEL"], y_pred_col_names=["OUTPUT_LABEL"])

print(f"Training accuracy: {training_accuracy} \nEval accuracy: {eval_accuracy}")
Copy

Verteilte Hyperparameter-Optimierung

Dieses Beispiel zeigt, wie die verteilte Hyperparameter-Optimierung mit der Snowpark ML-Implementierung von GridSearchCV von scikit-learn durchgeführt wird. Die einzelnen Ausführungen werden parallel unter Verwendung verteilter Warehouse-Computeressourcen ausgeführt. Weitere Informationen zur Optimierung verteilter Hyperparameter finden Sie unter Verteilte Hyperparameter-Optimierung.

from snowflake.snowpark import Session, DataFrame
from snowflake.ml.utils.connection_params import SnowflakeLoginOptions

from sklearn.datasets import make_classification
from snowflake.snowpark import Session, DataFrame
from snowflake.ml.modeling.xgboost import XGBClassifier
from snowflake.ml.modeling.model_selection.grid_search_cv import GridSearchCV

FEATURE_COLS = ["X1", "X2", "X3", "X4", "X5", "X6"]
LABEL_COLS = ["Y"]
OUTPUT_COLS = ["PREDICTIONS"]

# Create a session using your favorite login option.
# In this example we use a session builder with `SnowflakeLoginOptions`.
session = Session.builder.configs(SnowflakeLoginOptions()).create()

# Set up data.
def set_up_data(session: Session, n_samples: int) -> DataFrame:
    X, y = make_classification(
        n_samples=n_samples,
        n_features=6,
        n_informative=2,
        n_redundant=0,
        random_state=0,
        shuffle=True,
    )

    X = pd.DataFrame(X, columns=FEATURE_COLS)
    y = pd.DataFrame(y, columns=LABEL_COLS)

    features_pandas = pd.concat([X, y], axis=1)
    features_pandas.head()

    features_df = session.create_dataframe(features_pandas)
    return features_df

features_df = set_up_data(session, 10**4)

# Create a warehouse to use for the tuning job.
session.sql(
    """
CREATE or replace warehouse HYPERPARAM_WH
    WITH WAREHOUSE_SIZE = 'X-SMALL'
    WAREHOUSE_TYPE = 'Standard'
    AUTO_SUSPEND = 60
    AUTO_RESUME = TRUE
    INITIALLY_SUSPENDED = FALSE;"""
).collect()
session.use_warehouse("HYPERPARAM_WH")

# Tune an XGB Classifier model using sklearn GridSearchCV.
DISTRIBUTIONS = dict(
    n_estimators=[10, 50],
    learning_rate=[0.01, 0.1, 0.2],
)
estimator = XGBClassifier()
grid_search_cv = GridSearchCV(estimator=estimator, param_grid=DISTRIBUTIONS, input_cols=FEATURE_COLS, label_cols=LABEL_COLS, output_cols=OUTPUT_COLS)

grid_search_cv.fit(features_df)

# Use the best model to make predictions.
predictions = grid_search_cv.predict(features_df)
predictions[OUTPUT_COLS].show()

# Retrieve sklearn model, and print the best score
sklearn_grid_search_cv = grid_search_cv.to_sklearn()
print(sklearn_grid_search_cv.best_score_)
Copy

Um die Leistungsfähigkeit der verteilten Optimierung wirklich zu erkennen, trainieren Sie mit einer Million Datenzeilen.

large_features_df = set_up_data(session, 10**6)

# Scale up the warehouse for a faster fit. This takes 2m15s to run on an L warehouse versus 4m5s on a XS warehouse.
session.sql(f"ALTER WAREHOUSE {session.get_current_warehouse()} SET WAREHOUSE_SIZE='LARGE'").collect()

grid_search_cv.fit(large_features_df)
print(grid_search_cv.to_sklearn().best_score_)
Copy

Snowpark ML Modeling-Klassen

Alle Modellierungs- und Vorverarbeitungsklassen von Snowpark ML Modeling befinden sich im Namespace snowflake.ml.modeling. Die Module von Snowpark ML haben dieselben Namen wie die entsprechenden Module im sklearn-Namespace. Beispielsweise ist das Snowpark ML-Modul, das sklearn.calibration entspricht, snowflake.ml.modeling.calibration. Die Module xgboost und lightgbm entsprechen den Modulen snowflake.ml.modeling.xgboost bzw. snowflake.ml.modeling.lightgbm.

Die Snowpark ML Modeling-API bietet Wrapper für die zugrunde liegenden scikit-learn-, xgboost- und lightgbm-Klassen, von denen die meisten im virtuellen Warehouse als gespeicherte Prozeduren (die auf einem einzigen Warehouse-Knoten ausgeführt werden) ausgeführt werden. Nicht alle Klassen von scikit-learn werden in Snowpark ML unterstützt. Eine Liste der derzeit verfügbaren Klassen finden Sie in der Snowpark ML-API-Referenz.

Einige Klassen (u. a. Vorverarbeitungs- und Metrikklassen) unterstützen die verteilte Ausführung und können im Vergleich zur lokalen Ausführung derselben Operationen erhebliche Leistungsvorteile bieten. Weitere Informationen dazu finden Sie unter Verteilte Vorverarbeitung und Verteilte Hyperparameter-Optimierung. In der folgenden Tabelle sind die spezifischen Klassen aufgeführt, die eine verteilte Ausführung unterstützen.

Snowpark ML-Modulname

Verteilte Klassen

snowflake.ml.modeling.impute

  • SimpleImputer

snowflake.ml.modeling.metrics

correlation:

  • correlation

covariance:

  • covariance

classification:

  • accuracy_score

  • confusion_matrix

  • f1_score

  • fbeta_score

  • log_loss

  • precision_recall_fscore_support

  • precision_score

  • recall_score

regression:

  • mean_absolute_error

  • mean_absolute_percentage_error

  • mean_squared_error

snowflake.ml.modeling.model_selection

  • GridSearchCV

  • RandomizedSearchCV

snowflake.ml.modeling.preprocessing

  • Binarizer

  • KBinsDiscretizer

  • LabelEncoder

  • MaxAbsScaler

  • MinMaxScaler

  • Normalizer

  • OneHotEncoder

  • OrdinalEncoder

  • RobustScaler

  • StandardScaler

Allgemeine Unterschiede der API

Tipp

Alle Informationen zur Modellierungs-API finden Sie in der API-Referenz für Snowpark ML.

Snowpark ML Modeling umfasst Algorithmen zur Datenvorverarbeitung, Transformation und Vorhersage, die auf scikit-learn, xgboost und lightgbm basieren. Die Snowpark Python-Klassen sind Ersatz für die entsprechenden Klassen aus den Originalpaketen mit ähnlichen Signaturen. Diese APIs sind jedoch für Snowpark-DataFrames und nicht für NumPy-Arrays konzipiert.

Obwohl die Snowpark ML Modeling-API ähnlich wie scikit-learn ist, gibt es einige wichtige Unterschiede. In diesem Abschnitt wird erklärt, wie Sie die Methoden __init__ (Konstruktor), fit und predict für die in Snowpark ML bereitgestellten Schätzer- und Transformer-Klassen aufrufen.

  • Der Konstruktor aller Snowpark ML Python-Klassen akzeptiert zusätzliche zu den Parametern, die von den entsprechenden Klassen in scikit-learn, xgboost oder lightgbm akzeptiert werden, fünf weitere Parameter: input_cols, output_cols, sample_weight_col, label_cols und drop_input_cols. Dabei handelt es sich um Zeichenfolgen oder Sequenzen von Zeichenfolgen, die die Namen der Eingabespalten, der Ausgabespalten, der Spalte für die Gewichtung des Samples und der Beschriftungsspalten in einem Snowpark- oder Pandas-DataFrame angeben.

  • Die Methoden fit und predict in Snowpark ML akzeptieren einen einzigen DataFrame anstelle von separaten Arrays, die die Eingabedaten, Beschriftungen und Gewichtungen repräsentieren. Mit Snowpark ML geben Sie bei der Instanziierung der Klasse die Namen der Spalten an, die für diese Zwecke verwendet werden sollen. Diese Namen werden dann verwendet, um die benötigten Spalten im DataFrame zu finden, die Sie an fit oder predict übergeben. Weitere Informationen dazu finden Sie unter fit und predict.

  • Die Methoden transform und predict in Snowpark ML geben eine DataFrame zurück, das alle Spalten aus dem an die Methode übergebenen DataFrame enthält, wobei die Ausgabe der Vorhersage in zusätzlichen Spalten gespeichert wird. (Sie können die Transformation an Ort und Stelle vornehmen, indem für Eingabe- und Ausgabespalten Sie dieselben Namen angeben, oder Sie lassen die Eingabespalten weg, indem Sie drop_input_cols = True übergeben.) Die Äquivalenten zu scikit-learn, xgboost und lightgbm geben Arrays zurück, die nur die Ergebnisse enthalten.

  • Snowpark Python-Transformer verfügen nicht über eine fit_transform-Methode. Wie bei scikit-learn wird die Parametervalidierung jedoch nur in der Methode fit ausgeführt, sodass Sie fit irgendwann vor transform aufrufen müssen, auch wenn der Transformer keine Anpassung vornimmt. fit gibt den Transformer zurück, sodass die Methodenaufrufe verkettet werden können, z. B. Binarizer(threshold=0.5).fit(df).transform(df).

  • Snowpark ML-Transformer verfügen nicht über eine inverse_transform-Methode. Diese Methode ist bei Snowpark ML nicht notwendig, da die ursprüngliche Darstellung in den Eingabespalten des Eingabe-DataFrame erhalten bleibt, es sei denn, Sie führen explizit eine In-Place-Transformation aus, indem Sie die gleichen Namen für die Eingabe- und die Ausgabespalten angeben.

Sie können jedes Snowpark ML-Modellierungsobjekt in das entsprechende scikit-learn-, xgboost- oder lightgbm-Objekt konvertieren, sodass Sie alle Methoden und Attribute des zugrunde liegenden Typs nutzen können. Siehe Abrufen des zugrunde liegenden Modells.

Erstellen eines Modells

Zusätzlich zu den Parametern, die von den einzelnen scikit-learn-Modellklassen akzeptiert werden, akzeptieren alle Snowpark ML Modeling-Klassen bei der Instanziierung die folgenden weiteren Parameter.

Diese Parameter sind technisch gesehen alle optional, aber Sie werden oft entweder input_cols oder output_cols oder beides angeben wollen. label_cols und sample_weight_col sind in bestimmten, in der Tabelle aufgeführten Situationen erforderlich, können aber in anderen Fällen weggelassen werden.

Tipp

Alle Spaltennamen müssen die von Snowflake vorgegebenen Anforderungen an Bezeichner entsprechen. Um beim Erstellen einer Tabelle die Groß-/Kleinschreibung beibehalten oder Sonderzeichen (außer Dollarzeichen und Unterstrich) verwenden zu können, müssen die Spaltennamen in Anführungszeichen eingeschlossen werden. Verwenden Sie Spaltennamen in Großbuchstaben, wann immer dies möglich ist, um die Kompatibilität mit Pandas-DataFrames zu wahren, das Groß-/Kleinschreibung unterscheidet.

from snowflake.ml.modeling.preprocessing import MinMaxScaler
from snowflake.snowpark import Session

# Snowflake identifiers are not case sensitive by default.
# These column names will be automatically updated to ["COLUMN_1", "COLUMN_2", "COLUMN_3"] by the Snowpark DataFrame.
schema = ["column_1", "column_2", "column_3"]
df = session.create_dataframe([[1, 2, 3]], schema = schema)
df.show()
Copy
--------------------------------------
|"COLUMN_1"  |"COLUMN_2"  |"COLUMN_3"|
--------------------------------------
|1           |2          |3          |
--------------------------------------
Copy
# Identify the column names using the Snowflake identifier.
input_cols = ["COLUMN_1", "COLUMN_2", "COLUMN_3"]
mms = MinMaxScaler(input_cols=input_cols)
mms.fit(df)

# To maintain lower case column names, include a double quote within the string.
schema = ['"column_1"', '"column_2"', '"column_3"']
df = session.create_dataframe([[1, 2, 3]], schema = schema)
df.show()
Copy
----------------------------------------
|'"column_1"'|'"column_2"'|'"column_3"'|
----------------------------------------
|1           |2           |3           |
----------------------------------------
Copy
# Since no conversion took place, the schema labels can be used as the column identifiers.
mms = MinMaxScaler(input_cols=schema)
mms.fit(df)
Copy

Parameter

Beschreibung

input_cols

Eine Zeichenfolge oder eine Liste von Zeichenfolgen, die Spaltennamen darstellen, die Features enthalten.

Wenn Sie diesen Parameter weglassen, werden alle Spalten im Eingabe-DataFrame, mit Ausnahme der durch die Parameter label_cols, sample_weight_col und passthrough_cols angegebenen Spalten, als Eingabespalten betrachtet.

label_cols

Eine Zeichenfolge oder eine Liste von Zeichenfolgen, die die Namen von Spalten repräsentieren, die Beschriftungen enthalten.

Für überwachte Schätzer müssen Sie Beschriftungsspalten angeben, da ein Ableiten dieser Spalten nicht möglich ist. Diese Beschriftungsspalten werden als Ziele für Modellvorhersagen verwendet und sollten deutlich von input_cols unterschieden werden.

output_cols

Eine Zeichenfolge oder eine Liste von Zeichenfolgen, die die Namen von Spalten repräsentieren, in denen die Ausgabe von predict- und transform-Operationen gespeichert wird. Die Länge von output_cols muss der erwarteten Anzahl von Ausgabespalten der verwendeten Prädiktor- oder Transformerklasse entsprechen.

Wenn Sie diesen Parameter weglassen, werden die Namen der Ausgabespalten durch Hinzufügen des Präfixes OUTPUT_ zu den Namen der Beschriftungsspalten bei überwachten Schätzern oder des Präfixes OUTPUT_IDX bei nicht überwachten Schätzern abgeleitet. Diese abgeleiteten Ausgabespaltennamen funktionieren für Prädiktoren, aber output_cols muss für Transformer explizit festgelegt werden. Im Allgemeinen ist die explizite Angabe von Ausgabespaltennamen übersichtlicher, insbesondere wenn Sie die Eingabespaltennamen nicht angeben.

Um die Umwandlung an Ort und Stelle vorzunehmen, übergeben Sie für input_cols und output_cols dieselben Namen.

passthrough_cols

Eine Zeichenfolge oder eine Liste von Zeichenfolgen, die die Namen von Spalten repräsentieren, die von Training, Transformation und Inferenz ausgeschlossen werden sollen. Passthrough-Spalten bleiben zwischen dem Eingangs- und dem Ausgangs-DataFrames unberührt.

Diese Option ist hilfreich, wenn Sie die Verwendung bestimmter Spalten, wie z. B. von Indexspalten, während des Trainings oder der Inferenz vermeiden möchten, ohne input_cols übergeben zu müssen. Wenn Sie input_cols nicht übergeben, würden diese Spalten andernfalls als Eingaben gelten.

sample_weight_col

Eine Zeichenfolge mit dem Namen der Spalte, die die Gewichtung der Beispiele enthält.

Dieses Argument ist für gewichtete Datensets erforderlich.

drop_input_cols

Ein boolescher Wert, der angibt, ob die Eingabespalten aus dem Ergebnis-DataFrameentfernt werden. Der Standardwert ist False.

Beispiel

Der DecisionTreeClassifier-Konstruktor hat in scikit-learn keine erforderlichen Argumente; alle Argumente haben Standardwerte. In scikit-learn könnten Sie also Folgendes schreiben:

from sklearn.tree import DecisionTreeClassifier

model = DecisionTreeClassifier()
Copy

In Snowpark ML müssen Sie die Spaltennamen angeben (oder die Standardwerte akzeptieren, indem Sie sie nicht angeben). Im diesem Beispiel werden sie explizit angegeben.

Sie können einen Snowpark ML-Klassifizierer DecisionTreeClassifier initialisieren, indem Sie die Argumente direkt an den Konstruktor übergeben oder indem Sie sie nach der Instanziierung als Attribute des Modells festlegen. (Die Attribute können jederzeit geändert werden.)

  • Als Konstruktor-Argumente:

    from snowflake.ml.modeling.tree import DecisionTreeClassifier
    
    model = DecisionTreeClassifier(
        input_cols=feature_column_names, label_cols=label_column_names, sample_weight_col=weight_column_name,
        output_cols=expected_output_column_names
    )
    
    Copy
  • Durch Einstellen von Modellattributen:

    from snowflake.ml.modeling.tree import DecisionTreeClassifier
    
    model = DecisionTreeClassifier()
    model.set_input_cols(feature_column_names)
    model.set_label_cols(label_column_names)
    model.set_sample_weight_col(weight_column_name)
    model.set_output_cols(output_column_names)
    
    Copy

fit

Der Methode fit eines Snowpark ML-Klassifikators wird ein einzelner Snowpark- oder Pandas-DataFrame mit allen Spalten, einschließlich Features, Labels und Gewichtungen übergeben. Dies unterscheidet sich von der Methode fit von scikit-learn, die separate Eingaben für Features, Labels und Gewichtungen benötigt.

In scikit-learn sieht der Aufruf der Methode DecisionTreeClassifier.fit wie folgt aus:

model.fit(
    X=df[feature_column_names], y=df[label_column_names], sample_weight=df[weight_column_name]
)
Copy

In Snowpark ML müssen Sie nur den DataFrame übergeben. Sie haben die Namen der Eingabe-, Beschriftungs- und Gewichtungsspalten bereits bei der Initialisierung oder mithilfe von Konstruktionsmethoden festgelegt, wie unter Erstellen eines Modells gezeigt.

model.fit(df)
Copy

predict

Der Methode predict einer Snowpark ML-Klasse wird ebenfalls ein einzelner Snowpark- oder Pandas-DataFrame mit allen Feature-Spalten übergeben. Das Ergebnis ist ein DataFrame, der alle Spalten des Eingabe-DataFrame unverändert enthält und an den die Ausgabespalten angehängt sind. Sie müssen die Ausgabespalten aus diesem DataFrame extrahieren. Dies unterscheidet sich von der Methode predict in scikit-learn, die nur die Ergebnisse zurückgibt.

Beispiel

In scikit-learn liefert predict nur die Vorhersageergebnisse:

prediction_results = model.predict(X=df[feature_column_names])
Copy

Um in Snowpark ML nur die Vorhersageergebnisse zu erhalten, extrahieren Sie die Ausgabespalten aus dem zurückgegebenen DataFrame. Hier ist output_column_names eine Liste mit den Namen der Ausgabespalten:

prediction_results = model.predict(df)[output_column_names]
Copy

Verteilte Vorverarbeitung

Viele der Datenvorverarbeitungs- und Datentransformationsfunktionen in Snowpark ML werden mit d er Snowflake-Engine für die verteilte Verarbeitung implementiert, die im Vergleich zur Ausführung auf einem einzelnen Knoten (d. h. gespeicherte Prozeduren) erhebliche Leistungsvorteile bietet. Eine Liste der Funktionen, die die verteilte Ausführung unterstützen, finden Sie unter Snowpark ML Modeling-Klassen.

Das folgende Diagramm zeigt illustrative Leistungszahlen für große öffentliche Datensets, die in einem Snowpark-optimierten Medium-Warehouse ausgeführt werden, und vergleicht scikit-learn, das in gespeicherten Prozeduren ausgeführt wird, mit den verteilten Implementierungen von Snowpark ML. In vielen Szenarien kann Ihr Code 25 bis 50 Mal schneller ausgeführt werden, wenn Snowpark ML Modeling verwendet wird.

Veranschaulichung der Leistungsverbesserungen, die durch verteilte Vorverarbeitung möglich sind

Verteilen von Anpassungen (fit)

Die fit-Methode eines Snowpark ML-Vorverarbeitungstransformers akzeptiert einen Snowpark- oder pandas-DataFrame, passt das Datenset an und gibt den angepassten Transformer zurück.

  • Bei Snowpark-DataFrames wird die verteilte Anpassung der SQL-Engine verwendet. Der Transformer generiert SQL-Abfragen, um die erforderlichen Zustände (wie Mittelwert, Maximum oder Anzahl) zu berechnen. Diese Abfragen werden dann von Snowflake ausgeführt, und die Ergebnisse werden lokal materialisiert. Bei komplexen Zuständen, die nicht in SQL berechnet werden können, holt der Transformer Zwischenergebnisse aus Snowflake und führt lokale Berechnungen über Metadaten durch.

    Bei komplexen Transformern, die während der Transformation temporäre Zustandstabellen benötigen (z. B. OneHotEncoder oder OrdinalEncoder), werden diese Tabellen lokal mit pandas-DataFrames dargestellt.

  • pandas-DataFrames werden lokal angepasst, ähnlich wie bei der Anpassung mit scikit-learn. Der Transformer erstellt einen entsprechenden scikit-learn-Transformer mit den bereitgestellten Parametern. Dann wird der scikit-learn-Transformator angepasst, und der Snowpark ML-Transformer leitet die erforderlichen Zustände aus dem scikit-learn-Objekt ab.

Verteilen von Transformationen (transform)

Die transform-Methode eines Snowpark ML-Vorverarbeitungstransformers nimmt einen Snowpark- oder Pandas-DataFrame entgegen, transformiert diesen und gibt einen transformiertes Datenset zurück.

  • Bei Snowpark-DataFrames wird die verteilte Transformation mit der SQL-Engine ausgeführt. Der angepasste Transformer generiert einen Snowpark-DataFrame mit zugrunde liegenden SQL-Abfragen, die das transformierte Datenset darstellen. Die Methode transform führt bei einfachen Transformationen (z. B. StandardScaler oder MinMaxScaler) eine Auswertung im Lazy-Modus durch, sodass bei der Methode transform im Grunde keine Transformation ausgeführt wird.

    Bestimmte komplexe Transformationen erfordern jedoch eine Ausführung. Dazu gehören Transformer, die während der Transformation temporäre Zustandstabellen (wie OneHotEncoder und OrdinalEncoder) benötigen. Bei einer solchen Transformation erstellt der Transformer eine temporäre Tabelle aus dem Pandas-DataFrame (das den Zustand des Objekts speichert) für Joins und andere Operationen. Ein anderer Fall liegt vor, wenn bestimmte Parameter festgelegt sind. Wenn der Transformer z. B. so eingerichtet ist, dass unbekannte Werte, die während der Transformation gefunden werden, mit einer Fehlermeldung behandelt werden, werden die Daten, einschließlich der Spalten, unbekannten Werte und so weiter, materialisiert.

  • Pandas-DataFrames werden lokal transformiert, ähnlich wie bei der Transformation mit scikit-learn. Der Transformer erstellt einen entsprechenden scikit-learn-Transformer unter Verwendung der to_sklearn-API und führt die Transformation im Arbeitsspeicher aus.

Verteilte Hyperparameter-Optimierung

Das Optimieren der Hyperparameter ist ein integraler Bestandteil des Data Science-Workflows. Die Snowpark ML-API stellt verteilte Implementierungen der scikit-learn-APIs GridSearchCV und RandomizedSearchCV zur Verfügung, um effizientes Hyperparameter-Tuning sowohl auf Ein-Knoten- als auch auf Multi-Knoten-Warehouses zu ermöglichen.

Tipp

Snowpark ML aktiviert standardmäßig die verteilte Hyperparameter-Optimierung. Um diese zu deaktivieren, verwenden Sie den folgenden Python-Import.

import snowflake.ml.modeling.parameters.disable_distributed_hpo
Copy

Bemerkung

Das kleinste virtuelle Snowflake-Warehouse (XS) oder das Snowpark-optimierte Warehouse (M) hat einen einzigen Knoten. Mit jeder weiteren Vergrößerung verdoppelt sich die Anzahl der Knoten.

Bei Ein-Knoten-Warehouses (XS) wird standardmäßig die volle Kapazität des Knotens mithilfe des Joblib-Multiprocessing-Frameworks von scikit-learn genutzt.

Tipp

Wenn Sie bei einem Ein-Knoten-Warehouse (Standard-XS-Warehouse oder Snowpark-optimiertes M-Warehouse) auf Out-of-Memory-Fehler stoßen, versuchen Sie, die Parallelität mithilfe des Parameters n_jobs zu reduzieren. Der Standardwert von n_jobs ist -1, was bedeutet, dass alle Kerne verwendet werden.

Bei Warehouses mit mehreren Knoten werden die fit-Operationen innerhalb Ihres Tuning-Jobs für die Kreuzvalidierung auf die Knoten verteilt. Für das Hochskalieren sind keine Codeänderungen erforderlich. Die Anpassungen des Schätzers werden parallel auf allen verfügbaren Kernen aller Knoten des Warehouses ausgeführt.

Die Anpassungen des Schätzers werden parallel auf allen verfügbaren CPUs auf allen Rechnern im Warehouse ausgeführt

Zur Veranschaulichung betrachten wir das Datenset zum Wohnen in Kalifornien, das mit der scikit-learn-Bibliothek bereitgestellt wird. Die Daten umfassen 20.640 Datenzeilen mit den folgenden Informationen:

  • MedInc: Mittleres Einkommen im Block

  • HouseAge: Mittleres Alter der Häuser im Block

  • AveRooms: Durchschnittliche Anzahl der Zimmer pro Haushalt

  • AveBedrms: Durchschnittliche Anzahl der Schlafzimmer pro Haushalt

  • Population: Bevölkerung im Block

  • AveOccup: Durchschnittliche Anzahl der Haushaltsmitglieder

  • Latitude, Longitude: Längen- und Breitengrad

Das Ziel des Datensets ist das mittlere Einkommen, ausgedrückt in Hunderttausenden von Dollar.

In diesem Beispiel führen wir eine Grid-Search-Kreuzvalidierung mit einem Random-Forest-Regressor durch, um die beste Hyperparameterkombination zur Vorhersage des mittleren Einkommens zu erhalten.

from snowflake.ml.modeling.ensemble.random_forest_regressor import RandomForestRegressor
from snowflake.ml.modeling.model_selection.grid_search_cv import GridSearchCV
from sklearn import datasets

def load_housing_data() -> DataFrame:
    input_df_pandas = datasets.fetch_california_housing(as_frame=True).frame
    # Set the columns to be upper case for consistency with Snowflake identifiers.
    input_df_pandas.columns = [c.upper() for c in input_df_pandas.columns]
    input_df = session.create_dataframe(input_df_pandas)

    return input_df

input_df = load_housing_data()

# Use all the columns besides the median value as the features
input_cols = [c for c in input_df.columns if not c.startswith("MEDHOUSEVAL")]
# Set the target median value as the only label columns
label_cols = [c for c in input_df.columns if c.startswith("MEDHOUSEVAL")]


DISTRIBUTIONS = dict(
            max_depth=[80, 90, 100, 110],
            min_samples_leaf=[1,3,10],
            min_samples_split=[1.0, 3,10],
            n_estimators=[100,200,400]
        )
estimator = RandomForestRegressor()
n_folds = 5

clf = GridSearchCV(estimator=estimator, param_grid=DISTRIBUTIONS, cv=n_folds, input_cols=input_cols, label_cols=label_col)
clf.fit(input_df)
Copy

Die Ausführung dieses Beispiels dauert bei einem Snowpark-optimierten Medium-Warehouse (Einzelknoten) etwas mehr als 7 Minuten, bei einem X-Large-Warehouse aber nur 3 Minuten.

Veranschaulichung der Leistungsverbesserungen, die durch verteilte Hyperparameter-Optimierung möglich sind

Bereitstellen und Ausführen Ihres Modells

Das Ergebnis des Trainings eines Modells ist ein Snowpark ML-Python-Modellobjekt. Sie können das trainierte Modell für Vorhersagen verwenden, indem Sie die Methode predict des Modells aufrufen. Dadurch wird eine temporäre benutzerdefinierte Funktion zur Ausführung des Modells in Ihrem virtuellen Snowflake-Warehouse erstellt. Diese Funktion wird am Ende Ihrer Snowpark ML-Sitzung automatisch gelöscht (z. B. wenn Ihr Skript endet oder wenn Sie Ihr Jupyter-Notebook schließen).

Um die benutzerdefinierte Funktion nach dem Ende Ihrer Sitzung beizubehalten, können Sie sie auch manuell erstellen. Weitere Informationen dazu finden Sie im Quickstart zu diesem Thema.

Die Snowpark ML-Modell-Registry, ein kommendes Feature, unterstützt ebenfalls persistente Modelle und erleichtert deren Suche und Bereitstellung. Eine Einführung in die Modell-Registry und andere Features von Snowpark ML finden Sie unter Quickstart.

Pipeline für mehrere Transformationen

Bei scikit-learn ist es üblich, eine Serie von Transformationen mithilfe einer Pipeline auszuführen. scikit-learn-Pipelines funktionieren nicht mit den Snowpark ML-Klassen, daher bietet Snowpark ML eine Snowpark Python-Version von sklearn.pipeline.Pipeline für die Ausführung einer Serie von Transformationen. Diese Klasse befindet sich im Paket snowflake.ml.modeling.pipeline und funktioniert genauso wie die Version von scikit-learn.

Abrufen des zugrunde liegenden Modells

Snowpark ML-Modelle können mit den folgenden Methoden (je nach Bibliothek) entpackt (unwrapped), d. h. in die zugrunde liegenden Modelle von Drittanbietern konvertiert werden:

  • to_sklearn

  • to_xgboost

  • to_lightgbm

Alle Attribute und Methoden des zugrunde liegenden Modells können dann aufgerufen und lokal für den Schätzer ausgeführt werden. Beispielsweise konvertieren wir im GridSearchCV-Beispiel den Grid-Search-Schätzer in ein Scikit-Learn-Objekt, um das beste Ergebnis zu erhalten.

best_score = grid_search_cv.to_sklearn().best_score_
Copy

Bekannte Einschränkungen

  • Die Schätzer und Transformer von Snowpark ML unterstützen derzeit weder spärliche Eingaben noch spärliche Antworten. Wenn Sie spärliche Daten haben, konvertieren Sie diese in ein dichtes Format, bevor Sie sie an die Schätzer oder Transformer von Snowpark ML übergeben.

  • Das Snowpark ML-Paket unterstützt derzeit noch keine Matrix-Datentypen. Jede Operation auf Schätzern und Transformern, die eine Matrix als Ergebnis liefern würde, schlägt fehl.

  • Es ist nicht garantiert, dass die Reihenfolge der Zeilen in den Ergebnisdaten mit der Reihenfolge der Zeilen in den Eingabedaten übereinstimmt.

Problembehandlung

Hinzufügen weiterer Details für die Protokollierung

Snowpark ML verwendet die Protokollierung von Snowpark Python. Standardmäßig protokolliert Snowpark ML Meldungen der INFO-Ebene in der Standardausgabe. Um detailliertere Protokolle zu erhalten, die Ihnen bei der Problembehandlung mit Snowpark ML helfen, können Sie den Protokolliergrad auf eine der unterstützten Stufen ändern.

DEBUG erzeugt Protokolle mit den meisten Details. So setzen Sie den Protokolliergrad auf DEBUG:

import logging, sys

logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
Copy

Lösungen für häufige Probleme

Die folgende Tabelle enthält einige Vorschläge zur Lösung möglicher Probleme mit Snowflake ML Modeling.

Problem oder Fehlermeldung

Mögliche Ursache

Lösung

NameError, wie „Name x ist nicht definiert“, ImportError oder ModuleNotFoundError

Typografischer Fehler im Modul- oder Klassennamen, oder Snowpark ML ist nicht installiert

Den korrekten Namen des Moduls und der Klasse finden Sie in der Tabelle der Snowpark ML Modeling-Klassen. Stellen Sie sicher, dass das Snowpark ML-Modul installiert ist (siehe Installieren von Snowpark ML).

KeyError („not in index“ oder „none of [Index[..]] are in the [Spalten]“)

Inkorrekter Spaltenname

Überprüfen und korrigieren Sie den Spaltennamen.

SnowparkSQLException, „does not exist or not authorize“

Die Tabelle existiert nicht, oder Sie haben nicht die erforderlichen Berechtigungen für diese Tabelle.

Stellen Sie sicher, dass die Tabelle existiert und die Rolle des Benutzers die erforderlichen Berechtigungen hat.

SnowparkSQLException, „invalid identifier PETALLENGTH“

Inkorrekte Anzahl von Spalten (normalerweise eine fehlende Spalte).

Überprüfen Sie die Anzahl der Spalten, die Sie beim Erstellen der Modellklasse angegeben haben, und stellen Sie sicher, dass Sie die korrekte Anzahl übergeben.

InvalidParameterError

Es wurde ein ungeeigneter Typ oder Wert als Parameter übergeben.

Überprüfen Sie in einer interaktiven Python-Sitzung mit der Funktion help die Hilfe der Klasse oder Methode, und korrigieren Sie die Werte.

TypeError, „unexpected keyword argument“

Typographischer Fehler im benannten Argument

Überprüfen Sie in einer interaktiven Python-Sitzung mit der Funktion help die Hilfe der Klasse oder Methode, und korrigieren Sie den Argumentnamen.

ValueError, „array with 0 sample(s)“

Das Datenset, das Sie übergeben haben, ist leer.

Stellen Sie sicher, dass das Datenset nicht leer ist.

SnowparkSQLException, „authentication token has expired“

Die Sitzung ist abgelaufen.

Wenn Sie ein Jupyter-Notebook verwenden, starten Sie den Kernel neu, um eine neue Sitzung zu erstellen.

ValueError wie „cannot convert string to float“

Datentypen stimmen nicht überein.

Überprüfen Sie in einer interaktiven Python-Sitzung mit der Funktion help die Hilfe der Klasse oder Methode, und korrigieren Sie die Werte.

SnowparkSQLException, „cannot create temporary table“

Eine Modellklasse wird innerhalb einer gespeicherten Prozedur verwendet, die nicht mit Aufruferrechten ausgeführt wird.

Erstellen Sie die gespeicherte Prozedur mit Aufruferrechten statt mit Eigentümerrechten.

SnowparkSQLException, „function available memory exceeded“

Ihr Datenset ist größer als 5 GB in einem Standard-Warehouse.

Wechseln Sie zu einem Snowpark-optimierten Warehouse.

OSError, „no space left on device“

Ihr Modell ist größer als etwa 500 MB in einem Standard-Warehouse.

Wechseln Sie zu einem Snowpark-optimierten Warehouse.

Inkompatible xgboost-Version oder Fehler beim Importieren von xgboost

Sie haben für die Installation pip verwendet, das nicht gut mit Abhängigkeiten umgehen kann.

Führen Sie ein Upgrade oder Downgrade des Pakets durch, wie in der Fehlermeldung gefordert.

AttributeError mit to_sklearn, to_xgboost oder to_lightgbm

Sie versuchen, eine dieser Methoden auf ein Modell eines anderen Typs anzuwenden.

Verwenden Sie to_sklearn mit scikit-learn-basierten Modellen usw.

Jupyter Notebook-Kernel stürzt auf arm-basiertem Mac (M1- oder M2-Chip) ab: „The Kernel crashed while executing code in the current cell or a previous cell“

XGBoost oder eine andere Bibliothek ist mit der falschen Architektur installiert.

Erstellen Sie eine neue conda-Umgebung mit CONDA_SUBDIR=osx-arm64 conda create --name snowpark-ml, und führen Sie eine Neuinstallation von Snowpark ML aus.

Weiterführende Informationen

In der Dokumentation der Originalbibliotheken finden Sie vollständige Informationen zu deren Funktionalität.

Quellenangabe

Einige Teile dieses Dokuments stammen aus der Scikit-learn-Dokumentation, die unter der BSD-3 „New“- oder „Revised“-Lizenz und Copyright © 2007-2023 The scikit-learn developers lizenziert ist. Alle Rechte vorbehalten.

Einige Teile dieses Dokuments stammen aus der XGboost-Dokumentation, die unter die Apache License 2.0, Januar 2004 und Copyright © 2019 fällt. Alle Rechte vorbehalten.

Einige Teile dieses Dokuments stammen aus der LightGBM-Dokumentation, die MIT-lizenziert ist und unter Copyright © Microsoft Corp. fällt. Alle Rechte vorbehalten.