Snowpark ML Modeling: desenvolvimento de modelo de ML

Nota

A API do Snowpark ML Modeling está disponível em geral a partir da versão do pacote 1.1.1.

A API do Snowpark ML Modeling usa estruturas Python familiares, como scikit-learn e XGBoost para pré-processamento de dados, engenharia de recursos e modelos de treinamento dentro do Snowflake.

Os benefícios do desenvolvimento de modelos com Snowpark ML Modeling incluem:

  • Engenharia de recursos e pré-processamento: melhore o desempenho e a escalabilidade com execução distribuída para funções de pré-processamento do scikit-learn usadas com frequência.

  • Treinamento de modelo: acelere o treinamento para modelos scikit-learn, XGBoost e LightGBM sem a necessidade de criar manualmente procedimentos armazenados ou funções definidas pelo usuário (UDFs), aproveitando a otimização de hiperparâmetros distribuídos.

A Snowpark ML Modeling API fornece estimadores e transformadores que possuem APIs semelhantes àquelas nas bibliotecas scikit-learn, xgboost e lightgbm. Você pode usar essas APIs para criar e treinar modelos de machine learning que podem ser usados com Snowpark ML Operations, como o registro de modelo do Snowpark.

Dica

Consulte Introdução ao aprendizado de máquina com Snowpark ML para ver um exemplo de fluxo de trabalho completo no Snowpark ML, incluindo a API de modelagem.

Nota

Este tópico pressupõe que o Snowpark ML e suas dependências de modelagem já estejam instalados. Consulte Instalação do Snowpark ML.

Exemplos

Revise os exemplos a seguir para ter uma ideia das semelhanças da API do Snowpark ML Modeling com as bibliotecas de aprendizado de máquina com as quais você talvez esteja familiarizado.

Pré-processamento

Este exemplo ilustra o uso de funções de pré-processamento e transformação de dados do Snowpark ML Modeling. As duas funções de pré-processamento usadas no exemplo (MixMaxScaler e OrdinalEncoder) usam o mecanismo de processamento distribuído do Snowflake para fornecer melhorias significativas de desempenho em relação às implementações do lado do cliente ou de procedimentos armazenados. Para obter mais detalhes, consulte Pré-processamento distribuído.

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

Treinamento

Este exemplo mostra como treinar um modelo de classificador xgboost simples usando o Snowpark ML Modeling e, em seguida, executar previsões. A API do Snowpark ML é semelhante ao xgboost aqui, com apenas algumas diferenças na forma como as colunas são especificadas. Para obter detalhes sobre essas diferenças, consulte Diferenças gerais da 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

Pré-processamento de recursos e treinamento em dados não sintéticos

Este exemplo usa dados de partículas gama de alta energia de um telescópio atmosférico Cherenkov baseado em terra. O telescópio observa partículas gama de alta energia, aproveitando a radiação emitida pelas partículas carregadas produzidas nas chuvas eletromagnéticas iniciadas pelos raios gama. O detector registra a radiação Cherenkov (de comprimentos de onda visíveis a ultravioleta) que vaza pela atmosfera, permitindo a reconstrução dos parâmetros da chuva gama. O telescópio também detecta raios hádrons que são abundantes em chuvas cósmicas e produzem sinais que imitam os raios gama.

O objetivo é desenvolver um modelo de classificação para distinguir entre raios gama e raios hádrons. O modelo permite que os cientistas filtrem o ruído de fundo e se concentrem nos sinais genuínos de raios gama. Os raios gama permitem aos cientistas observar eventos cósmicos como o nascimento e a morte de estrelas, explosões cósmicas e o comportamento da matéria em condições extremas.

Os dados das partículas estão disponíveis para download no MAGIC Gamma Telescope. Baixe e descompacte os dados, defina a variável DATA_FILE_PATH para apontar para o arquivo de dados e execute o código abaixo para carregá-lo no Snowflake.

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

Depois de carregar os dados, use o código a seguir para treinar e prever, usando as etapas a seguir.

  • Pré-processamento os dados:

    • Substitua os valores ausentes pela média.

    • Centralize os dados usando um escalonador padrão.

  • Treine um classificador xgboost para determinar o tipo de eventos.

  • Teste a precisão do modelo em conjuntos de dados de treinamento e teste.

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

Otimização de hiperparâmetros distribuídos

Este exemplo mostra como executar a otimização de hiperparâmetros distribuídos usando a implementação do Snowpark ML do GridSearchCV do scikit-learn. As execuções individuais são executadas em paralelo usando recursos de computação de warehouse distribuídos. Para obter detalhes sobre otimização de hiperparâmetros distribuídos, consulte Otimização de hiperparâmetros distribuídos.

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

Para realmente ver o poder da otimização distribuída, treine em um milhão de linhas de dados.

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

Classes do Snowpark ML Modeling

Todas as classes do Snowpark ML Modeling e de pré-processamento estão no namespace snowflake.ml.modeling. Os módulos do Snowpark ML têm o mesmo nome que os módulos correspondentes do namespace sklearn. Por exemplo, o módulo Snowpark ML correspondente a sklearn.calibration é snowflake.ml.modeling.calibration. O módulos xgboost e lightgbm correspondem a snowflake.ml.modeling.xgboost e snowflake.ml.modeling.lightgbm, respectivamente.

A API do Snowpark ML Modeling fornece wrappers para classes scikit-learn, xgboost e lightgbm subjacentes, a maioria dos quais são executados como procedimentos armazenados (executando em um único nó de warehouse) no warehouse virtual. Nem todas as classes do scikit-learn são suportadas no Snowpark ML. Consulte a Referência da API do Snowpark ML para obter uma lista das classes disponíveis atualmente.

Algumas classes (incluindo classes de pré-processamento e métricas) suportam a execução distribuída e podem fornecer benefícios significativos de desempenho em comparação com a execução local das mesmas operações. Para obter mais informações, consulte Pré-processamento distribuído e Otimização de hiperparâmetros distribuídos. A tabela abaixo lista as classes específicas que oferecem suporte à execução distribuída.

Nome do módulo Snowpark ML

Classes distribuídas

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

Diferenças gerais da API

Dica

Consulte a Referência de API do Snowpark ML para obter detalhes completos da API de modelagem.

O Snowpark ML Modeling inclui pré-processamento de dados, transformação e algoritmos de previsão baseados em scikit-learn, xgboost e lightgbm. As classes Snowpark Python são substituições para as classes correspondentes dos pacotes originais, com assinaturas semelhantes. No entanto, estas APIs são projetadas para funcionar com o Snowpark DataFrames em vez das matrizes NumPy.

Embora a API do Snowpark ML Modeling seja semelhante ao scikit-learn, existem algumas diferenças importantes. Esta seção explica como chamar os métodos __init__ (construtor), fit e predict para as classes estimador e transformador fornecidas no Snowpark ML.

  • O construtor de todas as classes do Snowpark ML Python aceitam cinco parâmetros adicionais — input_cols, output_cols, sample_weight_col, label_cols e drop_input_cols — além dos parâmetros aceitos pelas classes equivalentes em scikit-learn, xgboost ou lightgbm. São cadeias de caracteres, ou sequências de cadeias de caracteres, que especificam os nomes das colunas de entrada, colunas de saída, coluna de peso de amostra e colunas de rótulo em um DataFrame do Snowpark ou Pandas.

  • Os métodos fit e predict no Snowpark ML aceitam um único DataFrame em vez de matrizes separadas que representam dados de entrada, rótulos e pesos. Com o Snowpark ML, você especifica os nomes das colunas a serem usadas para essas finalidades ao instanciar a classe; esses nomes são usados para encontrar as colunas necessárias no DataFrame que você passa para fit ou predict. Consulte fit e predict.

  • Os métodos transform e predict no Snowpark ML retornam um DataFrame contendo todas as colunas do DataFrame passado para o método, com a saída da previsão armazenada em colunas adicionais. (Você pode transformar no local especificando os nomes das colunas de entrada que correspondem aos nomes das colunas de saída ou descartar as colunas de entrada passando drop_input_cols = True.) Os equivalentes scikit-learn, xgboost e lightgbm retornam matrizes contendo apenas os resultados.

  • Os transformadores Snowpark Python não têm um método fit_transform. No entanto, como no scikit-learn, a validação de parâmetros é realizada apenas no método fit, então você deve chamar fit em algum momento antes de transform, mesmo quando o transformador não tem nenhum encaixe. fit retorna o transformador, então as chamadas de método podem ser encadeadas; por exemplo, Binarizer(threshold=0.5).fit(df).transform(df).

  • Os transformadores Snowpark ML não têm um método inverse_transform. Este método é desnecessário com o Snowpark ML porque a representação original permanece disponível nas colunas de entrada do DataFrame de entrada, que são preservadas, a menos que você execute explicitamente uma transformação no local especificando os mesmos nomes para as colunas de entrada e saída.

Você pode converter qualquer objeto de modelagem do Snowpark ML no objeto scikit-learn, xgboost ou lightgbm correspondente, permitindo usar todos os métodos e atributos do tipo subjacente. Consulte Recuperação do modelo subjacente.

Criação de um modelo

Além dos parâmetros aceitos pelas classes de modelo scikit-learn individuais, todas as classes do Snowpark ML Modeling aceitam os seguintes parâmetros adicionais na instanciação.

Esses parâmetros são todos tecnicamente opcionais, mas muitas vezes você desejará especificar input_cols, output_cols ou ambos. label_cols e sample_weight_col são obrigatórios em situações específicas indicadas na tabela, mas podem ser omitidos em outros casos.

Dica

Todos os nomes de colunas devem seguir os requisitos de identificador do Snowflake. Para preservar maiúsculas e minúsculas ou usar caracteres especiais (além do cifrão e do sublinhado) ao criar uma tabela, os nomes das colunas devem ser colocados entre aspas duplas. Use nomes de colunas em letras maiúsculas sempre que possível para manter a compatibilidade com Pandas DataFrames que diferencia maiúsculas de minúsculas.

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

Parâmetro

Descrição

input_cols

Uma cadeia de caracteres ou lista de cadeias de caracteres que representam nomes de colunas que contêm recursos.

Se você omitir este parâmetro, todas as colunas no DataFrame de entrada, exceto as colunas especificadas pelos parâmetros sample_weight_col, label_cols e passthrough_cols, são consideradas colunas de entrada.

label_cols

Uma cadeia de caracteres ou lista de cadeia de caracteres que representa os nomes das colunas que contêm rótulos.

Você deve especificar colunas de rótulos para estimadores supervisionados porque não é possível inferir essas colunas. Essas colunas de rótulos são usadas como destinos para previsões de modelo e devem ser claramente diferenciadas de input_cols.

output_cols

Uma cadeia de caracteres ou lista de cadeia de caracteres que representa os nomes de colunas que armazenarão a saída das operações predict e transform. O comprimento do output_cols deve corresponder ao número esperado de colunas de saída da classe específica do preditor ou transformador usada.

Se você omitir esse parâmetro, os nomes das colunas de saída serão derivados adicionando um prefixo OUTPUT_ para os nomes das colunas do rótulo para estimadores supervisionados ou OUTPUT_IDX para estimadores não supervisionados. Esses nomes de colunas de saída inferidas funcionam para preditores, mas output_cols deve ser definido explicitamente para transformadores. Em geral, especificar explicitamente os nomes das colunas de saída é mais claro, especialmente se você não especificar os nomes das colunas de entrada.

Para transformar no local, passe os mesmos nomes para input_cols e output_cols.

passthrough_cols

Uma cadeia de caracteres ou uma lista de cadeia de caracteres indicando nomes de colunas a serem excluídas do treinamento, transformação e inferência. As colunas de passagem permanecem inalteradas entre DataFrames de entrada e saída.

Esta opção é útil quando você deseja evitar o uso de colunas específicas, como colunas de índice, durante o treinamento ou inferência, mas não passa input_cols. Quando você não passa input_cols, essas colunas normalmente seriam consideradas entradas.

sample_weight_col

Uma cadeia de caracteres representando o nome da coluna contendo os pesos dos exemplos.

Este argumento é necessário para conjuntos de dados ponderados.

drop_input_cols

Um valor booleano que indica se as colunas de entrada são removidas do DataFrame de resultado. O padrão é False.

Exemplo

O construtor DecisionTreeClassifier não possui nenhum argumento necessário no scikit-learn; todos os argumentos têm valores padrão. Portanto, no scikit-learn, você pode escrever:

from sklearn.tree import DecisionTreeClassifier

model = DecisionTreeClassifier()
Copy

No Snowpark ML, você deve especificar os nomes das colunas (ou aceitar os padrões não especificando-os). Neste exemplo, eles são especificados explicitamente.

Você pode inicializar um Snowpark ML DecisionTreeClassifier passando os argumentos diretamente para o construtor ou definindo-os como atributos do modelo após a instanciação. (Os atributos podem ser alterados a qualquer momento.)

  • Como argumentos do construtor:

    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
  • Definindo os atributos do modelo:

    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

O método fit de um classificador do Snowpark ML leva um único DataFrame do Snowpark ou Pandas contendo todas as colunas, incluindo recursos, rótulos e pesos. Isso é diferente do método fit do scikit-learn, que usa entradas separadas para recursos, rótulos e pesos.

No scikit-learn, a chamada do método DecisionTreeClassifier.fit fica assim:

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

No Snowpark ML, você só precisa passar o DataFrame. Você já definiu os nomes de coluna de entrada, rótulo e peso na inicialização ou usando métodos setter, conforme mostrado em Criação de um modelo.

model.fit(df)
Copy

predict

O método predict de uma classe do Snowpark ML também leva um único DataFrame do Snowpark ou Pandas contendo todas as colunas de recursos. O resultado é um DataFrame que contém todas as colunas no DataFrame de entrada inalterado e as colunas de saída anexadas. Você deve extrair as colunas de saída deste DataFrame. Isso é diferente do predict no scikit-learn, que retorna apenas os resultados.

Exemplo

No scikit-learn, predict retorna apenas os resultados da previsão:

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

Para obter apenas os resultados da previsão no Snowpark ML, extraia as colunas de saída do DataFrame retornado. Aqui, output_column_names é uma lista contendo os nomes das colunas de saída:

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

Pré-processamento distribuído

Muitas das funções de pré-processamento e transformação de dados no Snowpark ML são implementadas usando o mecanismo de execução distribuída do Snowflake, que gera benefícios significativos de desempenho em comparação com a execução de nó único (ou seja, procedimentos armazenados). Para descobrir quais funções oferecem suporte à execução distribuída, consulte Classes do Snowpark ML Modeling.

O gráfico abaixo mostra números de desempenho ilustrativos em grandes conjuntos de dados públicos, executados em um warehouse médio otimizado para Snowpark, comparando o scikit-learn executado em procedimentos armazenados com as implementações distribuídas do Snowpark ML. Em muitos cenários, seu código pode ser executado de 25 a 50 vezes mais rápido ao usar Snowpark ML Modeling.

Ilustração de melhorias de desempenho possíveis através do pré-processamento distribuído

Como os ajustes são distribuídos

O método fit de um transformador de pré-processamento do Snowpark ML aceita um DataFrame do Snowpark ou pandas, ajusta o conjunto de dados e retorna o transformador ajustado.

  • Para DataFrames do Snowpark, o ajuste distribuído usa o mecanismo SQL. O transformador gera consultas SQL para calcular os estados necessários (como média, máximo ou contagem). Essas consultas são então executadas pelo Snowflake e os resultados são materializados localmente. Para estados complexos que não podem ser calculados em SQL, o transformador busca resultados intermediários do Snowflake e executa cálculos locais sobre metadados.

    Para transformadores complexos que exigem tabelas de estado temporárias durante a transformação (por exemplo, OneHotEncoder ou OrdinalEncoder), essas tabelas são representadas localmente usando pandas DataFrames.

  • pandas DataFrames são ajustados localmente, semelhante ao ajuste com o scikit-learn. O transformador cria um transformador scikit-learn correspondente com os parâmetros fornecidos. Em seguida, o transformador scikit-learn é ajustado e o transformador do Snowpark ML deriva os estados necessários do objeto scikit-learn.

Como as transformações são distribuídas

O método transform de um transformador de pré-processamento do Snowpark ML aceita um DataFrame do Snowpark ou Pandas, transforma o conjunto de dados e retorna um conjunto de dados transformado.

  • Para DataFrames do Snowpark, a transformação distribuída é executada usando o mecanismo SQL. O transformador ajustado gera um DataFrame do Snowpark com consultas SQL subjacentes que representam o conjunto de dados transformado. O método transform executa avaliação lenta para transformações simples (por exemplo, StandardScaler ou MinMaxScaler), de modo que nenhuma transformação seja realmente executada durante o método transform.

    No entanto, certas transformações complexas envolvem execução. Isso inclui transformadores que exigem tabelas de estado temporárias (como OneHotEncoder e OrdinalEncoder) durante a transformação. Para tal transformador, o transformador cria uma tabela temporária do Pandas DataFrame (que armazena o estado do objeto) para junções e outras operações. Outro caso é quando determinados parâmetros são definidos. Por exemplo, quando o transformador é configurado para lidar com valores desconhecidos encontrados durante a transformação gerando erros, ele materializa os dados, incluindo colunas, valores desconhecidos e assim por diante.

  • Pandas DataFrames são transformados localmente, semelhante à transformação com scikit-learn. O transformador cria um transformador scikit-learn correspondente usando to_sklearn API e executa a transformação na memória.

Otimização de hiperparâmetros distribuídos

O ajuste de hiperparâmetros é parte integrante do fluxo de trabalho da ciência de dados. A Snowpark ML API fornece implementações distribuídas do scikit-learn GridSearchCV e RandomizedSearchCV APIs para permitir o ajuste eficiente de hiperparâmetros em warehouses de nó único e de vários nós.

Dica

Snowpark ML permite a otimização distribuída de hiperparâmetros por padrão. Para desativá-lo, use a seguinte importação do Python.

import snowflake.ml.modeling.parameters.disable_distributed_hpo
Copy

Nota

O menor warehouse virtual Snowflake (XS) ou warehouse otimizado para Snowpark (M) tem um nó. Cada tamanho sucessivamente maior duplica o número de nós.

Para warehouses de nó único (XS), a capacidade total do nó é utilizada por padrão usando a estrutura de multiprocessamento joblib do scikit-learn.

Dica

Em um warehouse de nó único (warehouse padrão XS ou warehouse M otimizado para Snowpark), se você encontrar erros de falta de memória, tente reduzir o paralelismo especificando o parâmetro n_jobs. O valor padrão n_jobs, -1, usa todos os núcleos.

Para warehouses com vários nós, as operações fit dentro do trabalho de ajuste de validação cruzada são distribuídas entre os nós. Nenhuma alteração de código é necessária para aumentar a escala. Os ajustes do estimador são executados em paralelo em todos os núcleos disponíveis em todos os nós do warehouse.

Os ajustes do estimador são executados em paralelo em todos os CPUs disponíveis em todas as máquinas do warehouse

Como ilustração, considere o conjunto de dados habitacionais da Califórnia fornecido com a biblioteca scikit-learn. Os dados incluem 20.640 linhas de dados com as seguintes informações:

  • MedInc: renda mediana no grupo de quarteirões

  • HouseAge: idade média da residência no grupo de quarteirões

  • AveRooms: número médio de cômodos por domicílio

  • AveBedrms: número médio de quartos por domicílio

  • População: a população do grupo de quarteirões

  • AveOccup: número médio de membros da família

  • Latitude e Longitude

O alvo do conjunto de dados é a renda média, expressa em centenas de milhares de dólares.

Neste exemplo, fazemos a validação cruzada de pesquisa em grade em um regressor aleatório para encontrar a melhor combinação de hiperparâmetros para prever a renda mediana.

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

Este exemplo é executado em pouco mais de 7 minutos em um warehouse Medium (nó único) otimizado para Snowpark e leva apenas 3 minutos para ser executado em um warehouse X-Large.

Ilustração de melhorias de desempenho possíveis pela otimização distribuída de hiperparâmetros

Como implantar e executar seu modelo

O resultado do treinamento de um modelo é um objeto de modelo Python do Snowpark ML. Você pode usar o modelo treinado para fazer previsões chamando o método predict do modelo. Isso cria uma função temporária definida pelo usuário para executar o modelo em seu warehouse virtual Snowflake. Esta função é excluída automaticamente no fim de sua sessão do Snowpark ML (por exemplo, quando seu script termina ou quando você fecha seu Jupyter Notebook).

Para manter a função definida pelo usuário após o término da sessão, você pode criá-la manualmente. Consulte o Guia de início rápido sobre o tópico para obter mais informações.

O registro de modelo do Snowpark ML, um recurso futuro, também oferece suporte a modelos persistentes e facilita sua localização e implantação. Consulte o Guia de início rápido para obter uma introdução ao registro do modelo junto com outros recursos do Snowpark ML.

Pipeline para múltiplas transformações

Com o scikit-learn, é comum executar uma série de transformações usando um pipeline. Os pipelines do scikit-learn não funcionam com classes do Snowpark ML, portanto, o Snowpark ML fornece uma versão Snowpark Python de sklearn.pipeline.Pipeline para executar uma série de transformações. Esta classe está no pacote snowflake.ml.modeling.pipeline e funciona da mesma forma que a versão scikit-learn.

Recuperação do modelo subjacente

Os modelos do Snowpark ML podem ser “desencapsulados”, ou seja, convertidos em modelos subjacentes de terceiros, com os seguintes métodos (dependendo da biblioteca):

  • to_sklearn

  • to_xgboost

  • to_lightgbm

Todos os atributos e métodos do modelo subjacente podem então ser acessados e executados localmente no estimador. Por exemplo, no exemplo GridSearchCV, convertemos o estimador de pesquisa em grade em um objeto scikit-learn para recuperar a melhor pontuação.

best_score = grid_search_cv.to_sklearn().best_score_
Copy

Limitações conhecidas

  • Os estimadores e transformadores do Snowpark ML atualmente não oferecem suporte às entradas esparsas ou respostas esparsas. Se você tiver dados esparsos, converta-os em um formato denso antes de passá-los para os estimadores ou transformadores do Snowpark ML.

  • O pacote Snowpark ML atualmente não oferece suporte a tipos de dados de matriz. Qualquer operação em estimadores e transformadores que produzam uma matriz como resultado falha.

  • Não há garantia de que a ordem das linhas nos dados de resultado corresponda à ordem das linhas nos dados de entrada.

Solução de problemas

Adição de mais detalhes ao registro

Snowpark ML usa o registro em log do Snowpark Python. Por padrão, o Snowpark ML faz o registro em log de mensagens de nível INFO para a saída padrão. Para obter registros mais detalhados, que podem ajudar a solucionar problemas com o Snowpark ML, altere o nível para um dos níveis compatíveis.

DEBUG produz logs com mais detalhes. Para definir o nível de registro em log como DEBUG:

import logging, sys

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

Soluções para problemas comuns

A tabela a seguir fornece algumas sugestões para resolver possíveis problemas com o Snowflake ML Modeling.

Problema ou mensagem de erro

Possível causa

Resolução

NameError, como «nome x não está definido», ImportError ou ModuleNotFoundError

Erro tipográfico no nome do módulo ou da classe ou o Snowpark ML não está instalado.

Consulte a tabela Classes do Snowpark ML Modeling para obter o módulo e o nome da classe corretos. Certifique-se de que o módulo Snowpark ML esteja instalado (consulte Instalação do Snowpark ML).

KeyError («não está no índice» ou «nenhum dos [Índice[..]] está em [colunas]»)

Nome de coluna incorreto.

Verifique e corrija o nome da coluna.

SnowparkSQLException, «não existe ou não está autorizado»

A tabela não existe ou você não tem privilégios suficientes na tabela.

Certifique-se de que a tabela exista e que a função do usuário tenha os privilégios.

SnowparkSQLException, «identificador inválido PETALLENGTH»

Número incorreto de colunas (geralmente uma coluna ausente).

Verifique o número de colunas especificado quando você criou a classe de modelo e certifique-se de passar o número correto.

InvalidParameterError

Um tipo ou valor inadequado foi passado como parâmetro.

Verifique a ajuda da classe ou método usando a função help em uma sessão Python interativa e corrija os valores.

TypeError, «unexpected keyword argument»

Erro tipográfico no argumento nomeado.

Verifique a ajuda da classe ou método usando a função help em uma sessão Python interativa e corrija o nome do argumento.

ValueError, «array with 0 sample(s)»

O conjunto de dados passado está vazio.

Certifique-se de que o conjunto de dados não esteja vazio.

SnowparkSQLException, «authentication token has expired»

A sessão expirou.

Se você estiver usando um Jupyter Notebook, reinicie o kernel para criar uma nova sessão.

ValueError, como «cannot convert string to float»

Incompatibilidade de tipo de dados.

Verifique a ajuda da classe ou método usando a função help em uma sessão Python interativa e corrija os valores.

SnowparkSQLException, «cannot create temporary table»

Uma classe de modelo está sendo usada dentro de um procedimento armazenado que não é executado com os direitos do chamador.

Crie o procedimento armazenado com os direitos do chamador em vez dos direitos do proprietário.

SnowparkSQLException, «function available memory exceeded»

Seu conjunto de dados é maior que 5 GB em um warehouse padrão.

Mude para um warehouse otimizado para Snowpark.

OSError, «no space left on device»

Seu modelo é maior que cerca de 500 MB em um warehouse padrão.

Mude para um warehouse otimizado para Snowpark.

Versão xgboost incompatível ou erro ao importar xgboost

Você instalou usando pip, que não lida bem com dependências.

Atualize ou faça downgrade do pacote conforme solicitado pela mensagem de erro.

AttributeError envolvendo to_sklearn, to_xgboost ou to_lightgbm

Uma tentativa de usar um desses métodos em um modelo de um tipo diferente.

Use to_sklearn com modelos baseados em scikit-learn etc.

O kernel do notebook Jupyter trava em um Mac baseado em ARM (chip M1 ou M2): “O kernel travou ao executar o código na célula atual ou em uma célula anterior.”

XGBoost ou outra biblioteca está instalada com a arquitetura incorreta.

Recrie o novo ambiente conda com CONDA_SUBDIR=osx-arm64 conda create --name snowpark-ml e reinstale o Snowpark ML.

Leitura adicional

Consulte a documentação das bibliotecas originais para obter informações completas sobre sua funcionalidade.

Aviso

Algumas partes deste documento são derivadas da documentação do Scikit-learn, que é licenciada sob a licença BSD-3 «Nova» ou «Revisada» e Copyright © 2007-2023 The scikit-learn developers. Todos os direitos reservados.

Algumas partes deste documento são derivadas da documentação XGboost, que é coberta pela licença Apache 2.0, janeiro de 2004 e Copyright © 2019. Todos os direitos reservados.

Algumas partes deste documento são derivadas da documentação LightGBM, que é licenciado para MIT e Copyright © Microsoft Corp. Todos os direitos reservados.