Registro de modelo Snowflake

Nota

A API do registro de modelos descrita neste tópico está geralmente disponível a partir da versão 1.5.0 do pacote.

O Registro de modelo Snowflake permite que você gerencie com segurança modelos e seus metadados no Snowflake, independentemente da origem. O registro de modelo armazena modelos de aprendizado de máquina como objetos ao nível de esquema de primeira classe no Snowflake para que eles possam ser facilmente encontrados e usados por outras pessoas em sua organização. É possível criar registros e armazenar modelos neles usando classes Python na biblioteca de ML Snowpark. Os modelos podem ter diversas versões e você pode designar uma versão como padrão.

Após armazenar um modelo, você pode invocar seus métodos (equivalentes a funções ou procedimentos armazenados) para executar operações de modelo, como inferência, em um warehouse virtual Snowflake.

Dica

Para ver um exemplo de um fluxo de trabalho de ponta a ponta Snowpark ML, incluindo o Snowflake Model Registry, consulte Introdução ao aprendizado de máquina com o Snowpark ML.

Se você tiver modelos no Microsoft Azure Machine Learning ou no Amazon SageMaker, consulte Implantação dos modelos do Azure ML e SageMaker para Snowpark ML.

As classes mais importantes na API Python Snowflake Model Registry são:

O Snowflake Model Registry oferece suporte aos seguintes tipos de modelos.

Este tópico descreve como executar operações de registro em Python usando Snowpark ML. Você também pode realizar diversas operações de registro em SQL; consulte Comandos de modelo.

Privilégios obrigatórios

Para criar um modelo, você deve possuir o esquema onde o modelo foi criado ou ter o privilégio CREATE MODEL nele. Para usar um modelo, você deve possuir o modelo ou ter o privilégio USAGE nele. O privilégio USAGE permite que os beneficiários usem o modelo para inferência sem poder ver nenhum de seus componentes internos.

Se a função de um usuário tiver USAGE em um modelo, ele aparece em uma página de registro de modelos do Snowsight. Para obter mais detalhes, consulte Privilégios de controle de acesso.

Nota

Atualmente, os modelos não oferecem suporte à replicação.

Limitações e problemas atuais

O Registro de modelo Snowflake atualmente tem as seguintes limitações:

  • O registro não pode ser usado em Snowflake Native Apps.

  • Os modelos não podem ser compartilhados ou clonados e são ignorados durante a replicação.

Versões 1.5.0 e 1.5.1 do pacote snowflake-ml-python têm os seguintes problemas conhecidos. Até que esses problemas sejam resolvidos, use a solução alternativa fornecida.

  • Na versão 8.23 e anteriores do Snowflake, a biblioteca não funciona em procedimentos armazenados de direitos do proprietário. Em vez disso, use procedimentos armazenados de direitos do chamador.

  • Em procedimentos armazenados, o registro de um modelo requer a incorporação de uma cópia da biblioteca do Snowpark ML local no modelo. Especifique a opção embed_local_ml_library na chamada log_model, conforme mostrado:

    registry.log_model(..., options={"embed_local_ml_library": True, ...})
    
    Copy

Os seguintes limites se aplicam a modelos e versões de modelo.

Modelos

  • Máximo de 1.000 versões

Versões do modelo

  • Máximo de 10 métodos

  • Máximo de 10 importações

  • Máximo de 500 argumentos por método

  • Metadados máximos (incluindo métricas) de 100 KB

  • Tamanho máximo total do modelo de 5 GB

  • Tamanho máximo do arquivo de configuração de 250 KB, incluindo conda.yml e outros arquivos de manifesto que log_model gera internamente. (Se um modelo tiver muitas funções e todas elas tiverem muitos argumentos, por exemplo, esse limite poderá ser excedido.)

Abertura do registro de modelo do Snowflake

Os modelos são objetos Snowflake de primeira classe e podem ser organizados em um banco de dados e esquema junto com outros objetos Snowflake. O Registro de modelo Snowflake fornece uma classe Python para gerenciar modelos dentro de um esquema. Assim, qualquer esquema Snowflake pode ser usado como registro. Não é necessário inicializar ou preparar um esquema para essa finalidade. Snowflake recomenda a criação de um ou mais esquemas dedicados para essa finalidade, como ML.REGISTRY. Você pode criar o esquema usando CREATE SCHEMA.

Antes de poder criar ou modificar modelos no registro, você deve abrir o registro. A abertura do registro retorna uma referência a ele, que você pode usar para adicionar novos modelos e obter referências a modelos existentes.

from snowflake.ml.registry import Registry

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

Registro de modelos e versões

Adicionar um modelo ao registro é chamado de registro em log do modelo. Registre em log um modelo chamando o método log_model do registro. Este método serializa o modelo – um objeto Python – e cria um objeto modelo Snowflake a partir dele. Este método também adiciona metadados, como uma descrição, ao modelo, conforme especificado na chamada log_model.

Cada modelo pode ter versões ilimitadas. Para registrar versões adicionais do modelo em log, chame log_model novamente com o mesmo model_name, mas com um version_name diferente.

Você não pode adicionar tags a um modelo quando ele é adicionado ao registro, porque tags são atributos do modelo e log_model adiciona uma versão específica do modelo, criando um modelo apenas quando adiciona sua primeira versão. Você pode atualizar as tags do modelo depois de registrar a primeira versão do modelo em log.

No exemplo a seguir, clf, abreviação de “classificador”, é o objeto do modelo Python, que já foi criado em outro lugar em seu código. Você pode adicionar um comentário no momento do registro, conforme mostrado aqui. A combinação de nome e versão deve ser exclusiva no esquema. Você pode especificar listas de conda_dependencies; os pacotes especificados serão implantados com o modelo.

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

Os argumentos de log_model são descritos aqui.

Argumentos exigidos

Argumento

Descrição

model

O objeto de modelo Python de um tipo de modelo compatível. Deve ser serializável (“selecionável”).

model_name

O nome do modelo, usado com version_name para identificar o modelo no registro. O nome não pode ser alterado depois que o modelo for registrado. Deve ser um identificador Snowflake válido.

Nota

A combinação do nome do modelo e da versão deve ser exclusiva no esquema.

Argumentos opcionais

Argumento

Descrição

version_name

Cadeia de caracteres especificando a versão do modelo, usada com model_name para identificar o modelo no registro. Deve ser um identificador Snowflake válido. Se ausente, um nome de versão legível por humanos será gerado automaticamente.

code_paths

Lista de caminhos para diretórios de código a serem importados ao carregar ou implantar o modelo.

comment

Comentário, por exemplo, uma descrição do modelo.

conda_dependencies

Lista de pacotes Conda exigidos pelo seu modelo. Este argumento especifica nomes de pacotes e versões opcionais em formato Conda, ou seja, "[channel::]package [operator version]". Se você não especificar um canal, o canal Snowflake será assumido.

ext_modules

Lista de módulos externos para combinar com o modelo. Compatível com scikit-learn, Snowpark ML, PyTorch, TorchScript e modelos personalizados.

metrics

Dicionário com métricas vinculadas à versão do modelo.

options

Dicionário com opções para criação de modelo. As seguintes opções estão disponíveis para todos os tipos de modelo:

  • embed_local_ml_library: se uma cópia da biblioteca local do Snowpark ML deve ser incorporada ao modelo. Padrão: False.

  • relax_version: se deve relaxar as restrições de versão das dependências. Isso substitui os especificadores de versão como ==x.y.z por especificadores como <=x.y, <(x+1). Padrão: True.

  • method_options: Um dicionário de opções por método, onde a chave é o nome de um método e o valor é um dicionário com uma ou mais das opções descritas aqui. As opções disponíveis são:

    • case_sensitive: indica se o método e sua assinatura diferenciam maiúsculas de minúsculas. Os métodos que diferenciam maiúsculas de minúsculas devem ser colocados entre aspas duplas quando usados em SQL. Esta opção também permite caracteres não alfabéticos em nomes de métodos. Padrão: False.

    • max_batch_size: tamanho máximo do lote que o método aceitará quando chamado no warehouse. Padrão: None (o tamanho do lote é determinado automaticamente).

Tipos de modelos individuais podem oferecer suporte a opções adicionais. Consulte Notas sobre tipos de modelos específicos.

pip_requirements

Lista de especificações de pacote para os pacotes PyPI exigidos pelo seu modelo.

python_version

A versão do Python na qual o modelo será executado. O padrão é None, que designa a versão mais recente disponível no warehouse.

sample_input_data

Um DataFrame com os dados de entrada de amostra. Os nomes dos recurso exigidos pelo modelo e seus tipos são extraídos deste DataFrame. Este argumento ou signatures devem ser fornecidos para todos os modelos, exceto os modelos Snowpark ML e MLFlow e pipelines Hugging Face.

signatures

Modele assinaturas de métodos como um mapeamento do nome do método de destino para assinaturas de entrada e saída. Este argumento ou sample_input_data devem ser fornecidos para todos os modelos, exceto os modelos Snowpark ML e MLFlow e pipelines Hugging Face.

task

A tarefa que define o problema que o modelo pretende resolver. Se não for especificado, o melhor esforço será feito para inferir a tarefa do modelo a partir da classe do modelo ou ela será definida como type_hints.Task.UNKNOWN. Verifique snowflake.ml.model.type_hints para todas as opções de tarefa.

log_model retorna um objeto snowflake.ml.model.ModelVersion, que representa a versão do modelo que foi adicionado ao registro.

Após o registro, o modelo em si não pode ser modificado (embora você possa alterar seus metadados). Para excluir um modelo e todas as suas versões, use o método excluir_modelo do registro.

Como trabalhar com artefatos de modelo

Depois que um modelo é registrado, seus artefatos (os arquivos que dão suporte ao modelo, incluindo seus objetos Python serializados e vários arquivos de metadados, como seu manifesto) ficam disponíveis em um estágio interno. Os artefatos não podem ser modificados, mas você pode visualizar ou baixar os artefatos dos modelos que possui.

Nota

Ter o privilégio USAGE em um modelo não permite que você acesse seus artefatos; a propriedade é necessária.

Você pode acessar artefatos do modelo de um estágio usando, por exemplo, o comando GET ou seu equivalente em Snowpark Python, FileOperation.get.

No entanto, você não pode abordar artefatos de modelo usando a sintaxe usual do caminho de estágio. Em vez disso, use um snow:// URL, uma maneira mais geral de especificar a localização de objetos no Snowflake. Por exemplo, uma versão dentro de um modelo pode ser especificada por um URL do formulário snow://model/<nome_do_modelo>/versions/<nome_da_versão>/.

Sabendo o nome do modelo e a versão que você deseja, você pode usar o comando LIST para visualizar os artefatos do modelo da seguinte forma:

LIST 'snow://model/my_model/versions/V3/';
Copy

A saída é semelhante a:

name                                      size                  md5                      last_modified
versions/V3/MANIFEST.yml           30639    2f6186fb8f7d06e737a4dfcdab8b1350        Thu, 18 Jan 2024 09:24:37 GMT
versions/V3/functions/apply.py      2249    e9df6db11894026ee137589a9b92c95d        Thu, 18 Jan 2024 09:24:37 GMT
versions/V3/functions/predict.py    2251    132699b4be39cc0863c6575b18127f26        Thu, 18 Jan 2024 09:24:37 GMT
versions/V3/model.zip             721663    e92814d653cecf576f97befd6836a3c6        Thu, 18 Jan 2024 09:24:37 GMT
versions/V3/model/env/conda.yml          332        1574be90b7673a8439711471d58ec746        Thu, 18 Jan 2024 09:24:37 GMT
versions/V3/model/model.yaml       25718    33e3d9007f749bb2e98f19af2a57a80b        Thu, 18 Jan 2024 09:24:37 GMT

Para recuperar um desses artefatos, use o comando SQL GET.

GET 'snow://model/model_my_model/versions/V3/MANIFEST.yml'
Copy

Ou o equivalente com Snowpark Python:

session.file.get('snow://model/my_model/versions/V3/MANIFEST.yml', 'model_artifacts')
Copy

Nota

Os nomes e a organização dos artefatos de um modelo podem variar dependendo do tipo do modelo e podem mudar. A lista de artefatos do exemplo anterior tem a intenção de ser ilustrativa, não autoritativa.

Exclusão de modelos

Use o método delete_model do registro para excluir um modelo e todas as suas versões.

reg.delete_model("mymodel")
Copy

Dica

Você também pode excluir modelos em SQL usando DROP MODEL.

Como obter modelos do registro

Para obter informações sobre cada modelo, use o método show_models:

model_df = reg.show_models()
Copy

Dica

Em SQL, use SHOW MODELS para obter uma lista de modelos.

O resultado de show_models é um pandas DataFrame. As colunas disponíveis estão listadas aqui:

Coluna

Descrição

created_on

Data e hora em que o modelo foi criado.

name

Nome do modelo.

database_name

Banco de dados no qual o modelo é armazenado.

schema_name

Esquema no qual o modelo é armazenado.

owner

Função proprietária do modelo.

comment

Comentário para o modelo.

versions

Matriz JSON listando versões do modelo.

default_version_name

Versão do modelo utilizado quando se refere ao modelo sem versão.

Para obter uma lista dos modelos no registro, cada um como uma instância Model, use o método models:

model_list = reg.models()
Copy

Para obter uma referência a um modelo específico do registro por nome, use o método get_model do registro.

m = reg.get_model("MyModel")
Copy

Nota

As instâncias de Model não são cópias do objeto de modelo Python original registrado; elas são referências ao objeto de modelo subjacente no registro.

Após ter uma referência para um modelo, seja um da lista retornada pelo método models ou uma recuperada usando get_model, é possível trabalhar com seus metadados e suas versões.

Exibição e atualização dos metadados de um modelo

Você pode visualizar e atualizar os atributos de metadados de um modelo no registro, incluindo seu nome, comentário, tags e métricas.

Recuperação e atualização de comentários

Use o atributo comment do modelo para recuperar e atualizar o comentário do modelo:

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

Nota

O atributo description é um sinônimo de comment. O código anterior também pode ser escrito desta forma:

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

Dica

Você também pode definir o comentário de um modelo em SQL usando ALTER MODEL.

Recuperação e atualização de tags

Tags são metadados usados para registrar a finalidade de um modelo, algoritmo, conjunto de dados de treinamento, estágio do ciclo de vida ou outras informações que você escolher. Você pode definir tags quando o modelo for registrado ou a qualquer momento posteriormente. Você também pode atualizar os valores das tags existentes ou remover totalmente as tags.

Nota

É necessário definir os nomes de todas as tags (e potencialmente seus possíveis valores) usando primeiro CREATE TAG. Consulte Marcação de objetos.

Para obter todas as tags de um modelo como um dicionário Python, use show_tags:

print(m.show_tags())
Copy

Para adicionar uma nova tag ou alterar o valor de uma tag existente, use set_tag:

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

Para recuperar o valor de uma tag, use get_tag:

m.get_tag("live_version")
Copy

Para remover uma tag, use unset_tag:

m.unset_tag("live_version")
Copy

Dica

Você também pode definir o comentário de um modelo em SQL usando ALTER MODEL.

Renomeação de um modelo

Use o método rename para renomear ou mover um modelo. Especifique um nome totalmente qualificado como o novo nome para mover o modelo para um banco de dados ou esquema diferente.

m.rename("MY_MODEL_TOO")
Copy

Dica

Você também pode renomear um modelo em SQL usando ALTER MODEL.

Como trabalhar com versões de modelo

Um modelo pode ter versões ilimitadas, cada uma identificada por uma cadeia de caracteres. Você pode usar qualquer convenção de nomenclatura de versão que desejar. Registrar um modelo na verdade registra uma versão específica do modelo. Para registrar versões adicionais de um modelo, chame log_model novamente com o mesmo model_name, mas com um version_name diferente.

Dica

Em SQL, use SHOW VERSIONS IN MODEL para ver as versões de um modelo.

Uma versão de um modelo é representada por uma instância da classe snowflake.ml.model.ModelVersion.

Para obter uma lista de todas as versões de um modelo, chame o método versions do objeto modelo. O resultado é uma lista de instâncias ModelVersion:

version_list = m.versions()
Copy

Para obter informações sobre cada modelo como um DataFrame, chame o método show_versions do modelo.

version_df = m.show_versions()
Copy

O DataFrame resultante contém as colunas a segui:

Coluna

Descrição

created_on

Data e hora em que a versão do modelo foi criada.

name

Nome da versão.

database_name

Banco de dados no qual a versão está armazenada.

schema_name

Esquema no qual a versão está armazenada.

model_name

Nome do modelo ao qual esta versão pertence.

is_default_version

Valor booleano que indica se esta versão é a versão padrão do modelo.

functions

Matriz JSON dos nomes das funções disponíveis nesta versão.

metadata

Objeto JSON contendo metadados como pares chave-valor ({} se nenhum metadado for especificado).

user_data

Objeto JSON da seção user_data do manifesto de definição do modelo ({} se nenhum dado do usuário for especificado).

Exclusão das versões do modelo

É possível excluir uma versão do modelo usando o método do modelo delete_version:

m.delete_version("rc1")
Copy

Dica

Também é possível excluir uma versão do modelo em SQL usando ALTER MODEL … DROP VERSION.

Versão padrão

Uma versão de um modelo pode ser designada como modelo padrão. Recupere ou defina o atributo default do modelo para obter a versão padrão atual (como um objeto ModelVersion) ou para alterá-la (usando uma cadeia de caracteres):

default_version = m.default
m.default = "v2"
Copy

Dica

Em SQL, use ALTER MODEL para definir a versão padrão.

Aliases da versão de modelo

É possível atribuir um alias a uma versão do modelo usando o comando SQL ALTER MODEL. Você pode usar um alias sempre que um nome de versão for necessário, como ao obter uma referência a uma versão de modelo, em Python ou em SQL. Um determinado alias pode ser atribuído a apenas uma versão de modelo por vez.

Além dos aliases que você cria, os seguintes aliases de sistema estão disponíveis em todos os modelos:

  • DEFAULT refere-se à versão padrão do modelo.

  • FIRST refere-se à versão mais antiga do modelo em termos de tempo de criação.

  • LAST refere-se à versão mais recente do modelo no momento da criação.

Os nomes de alias que você criar não devem ser iguais a nenhum nome de versão ou alias existente no modelo, incluindo aliases do sistema.

Como obter uma referência para uma versão do modelo

Para obter uma referência a uma versão específica de um modelo como uma instância ModelVersion, use o método version do modelo. Use o atributo default do modelo para obter a versão padrão do modelo:

m = reg.get_model("MyModel")

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

Após ter uma referência a uma versão específica de um modelo (como a variável mv neste exemplo), é possível recuperar ou atualizar seus comentários ou métricas e chamar os métodos (ou funções) do modelo, conforme mostrado nas seções a seguir.

Recuperação e atualização de comentários

Assim como acontece com os modelos, as versões do modelo podem ter comentários, que podem ser acessados e definidos por meio do atributo comment ou description da versão do modelo.

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

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

Dica

Também é possível alterar o comentário de uma versão do modelo em SQL usando ALTER MODEL … MODIFY VERSION.

Recuperação e atualização de métricas

Métricas são pares chave-valor usados para rastrear a precisão da previsão e outras características da versão do modelo. Você pode definir métricas ao criar uma versão do modelo ou defini-las usando o método set_metric. Um valor de métrica pode ser qualquer objeto Python que possa ser serializado para JSON, incluindo números, cadeias de caracteres, listas e dicionários. Ao contrário das tags, os nomes das métricas e os valores possíveis não precisam ser definidos antecipadamente.

Uma métrica de precisão de teste pode ser gerada usando accuracy_score do sklearn:

from sklearn import metrics

test_accuracy = metrics.accuracy_score(test_labels, prediction)
Copy

A matriz de confusão pode ser gerada de forma semelhante usando o sklearn:

test_confusion_matrix = metrics.confusion_matrix(test_labels, prediction)
Copy

Então é possível definir esses valores como métricas:

# 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

Para recuperar as métricas de uma versão do modelo como um dicionário Python, use show_metrics:

metrics = mv.show_metrics()
Copy

Para excluir uma métrica, chame delete_metric:

mv.delete_metric("test_accuracy")
Copy

Dica

Também é possível modificar as métricas de uma versão do modelo (que são armazenadas como metadados) em SQL usando ALTER MODEL … MODIFY VERSION.

Recuperação de explicações do modelo

O registro do modelo é capaz de explicar os resultados de um modelo, informando quais recursos de entrada contribuem mais para as previsões, calculando os valores de Shapley. Este recurso de versão está disponível por padrão em todas as exibições de modelo criadas no Snowflake 8.31 e posteriores por meio do método explain do modelo subjacente. É possível chamar explain de SQL ou por meio de um método run de exibição de modelo em Python.

Para obter detalhes sobre esse recurso, consulte Explicabilidade do modelo.

Exportação de uma versão do modelo

Use mv.export para exportar os arquivos de um modelo para um diretório local; o diretório é criado se não existir:

mv.export("~/mymodel/")
Copy

Por padrão, os arquivos exportados incluem o código, o ambiente para carregar o modelo e os pesos do modelo. Para exportar também os arquivos necessários para executar o modelo em um warehouse, especifique export_mode = ExportMode.FULL:

mv.export("~/mymodel/", export_mode=ExportMode.FULL)
Copy

Carregamento da versão do modelo

Use mv.load para carregar o objeto do modelo Python original que foi adicionado originalmente ao registro. É possível então usar o modelo para inferência como se o tivesse definido em seu código Python:

clf = mv.load()
Copy

Para garantir a funcionalidade adequada de um modelo carregado do registro, o ambiente Python de destino (ou seja, as versões do interpretador Python e de todas as bibliotecas) deve ser idêntico ao ambiente do qual o modelo foi registrado. Especifique force=True na chamada load para forçar o carregamento do modelo mesmo que o ambiente seja diferente.

Dica

Para garantir que seu ambiente seja o mesmo onde o modelo está hospedado, baixe uma cópia do ambiente conda do registro do modelo:

conda_env = session.file.get("snow://model/<modelName>/versions/<versionName>/runtimes/python_runtime/env/conda.yml", ".")
open("~/conda.yml", "w").write(conda_env)
Copy

Em seguida, crie um novo ambiente conda a partir deste arquivo:

conda env create --name newenv --file=~/conda.yml
conda activate newenv
Copy

O argumento options opcional é um dicionário de opções para carregar o modelo. Atualmente, o argumento oferece suporte apenas à opção use_gpu.

Opção

Tipo

Descrição

Padrão

use_gpu

bool

Habilita a lógica de carregamento específica da GPU.

False

O exemplo a seguir ilustra o uso do argumento options:

clf = mv.load(options={"use_gpu": True})
Copy

Como chamar métodos de modelo

As versões do modelo podem ter métodos, que são funções anexadas que podem ser executadas para realizar inferência ou outras operações do modelo. As versões de um modelo podem ter métodos diferentes e as assinaturas desses métodos também podem ser diferentes.

Para chamar um método de uma versão de modelo, use mv.run, especificando o nome da função a ser chamada e passando um DataFrame Snowpark ou pandas que contenha os dados de inferência e quaisquer outros parâmetros necessários. O método é executado em um warehouse Snowflake.

O valor de retorno do método é um DataFrame Snowpark ou panda, dependendo do tipo de DataFrame passado. DataFrames Snowpark são avaliados lentamente, então o método é executado somente quando o método do DataFrame collect, show ou to_pandas for chamado.

Nota

Invocar um método executa-o no warehouse especificado na sessão que você está usando para se conectar ao registro. Consulte Especificação de um warehouse.

O exemplo a seguir ilustra a execução do método predict de um modelo. O método predict deste modelo não requer nenhum parâmetro além dos dados de inferência (test_features aqui). Se assim fosse, eles seriam passados como argumentos adicionais após os dados de inferência:

remote_prediction = mv.run(test_features, function_name="predict")
remote_prediction.show()   # assuming test_features is Snowpark DataFrame
Copy

Para ver quais métodos podem ser chamados em um determinado modelo, chame mv.show_functions. O valor de retorno deste método é uma lista de objetos ModelFunctionInfo. Cada um desses objetos inclui os seguintes atributos:

  • name: o nome da função que pode ser chamada em Python ou SQL.

  • target_method: o nome do método Python no modelo registrado original.

Dica

Você também pode chamar métodos de modelo em SQL. Consulte Métodos de modelo.

Compartilhamento de modelos

O registro de modelo pode armazenar dois tipos de modelos. É possível distingui-los usando a coluna MODEL_TYPE na saída de SHOW MODELS.

  • CORTEX_FINETUNED: Modelos gerados com o Cortex Fine-tuning sem código do usuário. Para compartilhar esse tipo de modelo, use o compartilhamento de dados.

  • USER_MODEL: Modelos com código do usuário, como modelos desenvolvidos usando classes de modelagem do Snowpark ML. Esses modelos não podem ser compartilhados no momento. A capacidade de compartilhar modelos com código de usuário estará disponível em um lançamento futuro.

Considerações sobre custo

O uso do registro de modelo do Snowflake incorre em custos padrão baseados no consumo do Snowflake. Isso inclui:

  • Custo de armazenamento de artefatos, metadados e funções do modelo. Para obter informações gerais sobre os custos de armazenamento, consulte Exploração do custo de armazenamento.

  • Custo de cópia de arquivos entre estágios para o Snowflake. Consulte COPY FILES.

  • Custo de operações de objetos de modelo sem servidor por meio da interface Snowsight UI ou SQL ou Python, como mostra os modelos e versões de modelo e alteração de comentários, tags e métricas do modelo.

  • Custos de computação do warehouse, que variam de acordo com o tipo de modelo e a quantidade de dados usados na inferência. Para obter informações gerais sobre os custos de computação do Snowflake, consulte Explicação dos custos de computação. Os custos de computação do warehouse são incorridos para:

    • Operações de criação de modelo e versão

    • Invocação dos métodos de um modelo

Notas sobre tipos de modelos específicos

Esta seção fornece informações adicionais sobre como registrar tipos específicos de modelos no registro de modelo do Snowflake.

Snowpark ML

O registro oferece suporte a modelos criados usando as APIs de modelagem do Snowpark ML (modelos derivados de snowpark.ml.modeling.framework.base.BaseEstimator). As seguintes opções adicionais podem ser usadas no dicionário options quando você chamar log_model:

Opção

Descrição

target_methods

Uma lista dos nomes dos métodos disponíveis no objeto modelo. Os modelos Snowpark ML têm os seguintes métodos de destino por padrão, assumindo que o método existe: predict, transform, predict_proba, predict_log_proba, decision_function.

Você não precisa especificar sample_input_data ou signatures ao registrar um modelo Snowpark ML; estes são inferidos automaticamente durante o ajuste.

Exemplo

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

O registro oferece suporte a modelos criados usando scikit-learn (modelos derivados de sklearn.base.BaseEstimator ou sklearn.pipeline.Pipeline). As seguintes opções adicionais podem ser usadas no dicionário options quando você chamar log_model:

Opção

Descrição

target_methods

Uma lista dos nomes dos métodos disponíveis no objeto modelo. Os modelos scikit-learn têm os seguintes métodos de destino por padrão, assumindo que o método existe: predict, transform, predict_proba, predict_log_proba, decision_function.

Você deve especificar o parâmetro sample_input_data ou signatures ao registrar um modelo scikit-learn para que o registro conheça as assinaturas dos métodos de destino.

Exemplo

from sklearn import datasets, ensemble

iris_X, iris_y = datasets.load_iris(return_X_y=True, as_frame=True)
clf = ensemble.RandomForestClassifier(random_state=42)
clf.fit(iris_X, iris_y)
model_ref = registry.log_model(
    clf,
    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

O registro oferece suporte a modelos criados usando XGBoost (modelos derivados de xgboost.XGBModel ou xgboost.Booster). As seguintes opções adicionais podem ser usadas no dicionário options quando você chamar log_model:

Opção

Descrição

target_methods

Uma lista dos nomes dos métodos disponíveis no objeto modelo. Os modelos derivados de XGBModel têm os seguintes métodos de destino por padrão, assumindo que o método existe: predict, predict_proba. (Antes da v1.4.0, apply também foi incluído.) Os modelos derivados de Booster possuem o método predict por padrão.

cuda_version

A versão do tempo de execução CUDA a ser usada ao implantar em uma plataforma com GPU; o padrão é 11.7. Se definido manualmente como None, o modelo não poderá ser implementado em uma plataforma com GPU.

Você deve especificar o parâmetro sample_input_data ou signatures ao registrar um modelo XGBoost para que o registro conheça as assinaturas dos métodos de destino.

Exemplo

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

O registro oferece suporte aos modelos PyTorch (classes derivadas de torch.nn.Module ou torch.jit.ModuleScript) se o método forward do modelo aceitar uma ou mais instâncias torch.Tensor como entrada e retornar um torch.Tensor ou uma tupla delas. O registro converte entre pandas DataFrames e tensores ao chamar o modelo e retornar os resultados. Os tensores correspondem às colunas no dataframe.

Por exemplo, suponha que seu modelo aceite dois tensores como este:

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

Se você quiser passar torch.Tensor([[1,2],[3,4]]) como tensor_1 e torch.Tensor([[5,6], [7,8]]) como tensor_2, crie um DataFrame como este para passar ao modelo:

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

Então o tensors DataFrame fica assim:

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

Da mesma forma, se seu modelo retornar dois tensores, como (torch.Tensor([[1,2],[3,4]]), torch.Tensor([[5,6], [7,8]])), o resultado será um DataFrame como o acima.

Ao fornecer dados de entrada de amostra para um modelo PyTorch, é necessário fornecer uma lista de tensores (que serão convertidos em DataFrame pandas) ou um DataFrame. Uma lista pode conter um único tensor, mas um tensor por si só não é aceito.

Registro do modelo

As seguintes opções adicionais podem ser usadas no dicionário options quando você chamar log_model:

Opção

Descrição

target_methods

Uma lista dos nomes dos métodos disponíveis no objeto modelo. O padrão dos modelos PyTorch é forward.

cuda_version

A versão do tempo de execução CUDA a ser usada ao implantar em uma plataforma com GPU; o padrão é 11.7. Se definido manualmente como None, o modelo não poderá ser implementado em uma plataforma com GPU.

Você deve especificar o parâmetro sample_input_data ou signatures ao registrar um modelo PyTorch para que o registro conheça as assinaturas dos métodos de destino.

Exemplo

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

Modelos que estendem tensorflow.Module ou tensorflow.keras.Model são suportados quando aceitam e retornam tensores e são compiláveis ou compilados.

  • O método __call__ para um tensorflow.Module ou o método call para um tensorflow.keras.Model aceita um ou mais tensorflow.Tensor ou tensorflow.Variable como entrada e retorna um tensorflow.Tensor ou tensorflow.Variable ou uma tupla de um dos esses tipos.

  • Se seu modelo estender Module, ele deverá ser compilável, o que significa que o método __call__ é decorado com @tensorflow.function; consulte a documentação do tf.function. Se estender Model, deverá ser compilado; consulte a documentação de compilação.

O registro converte entre pandas DataFrames e tensores ao chamar o modelo e retornar os resultados. Os tensores correspondem às colunas no dataframe.

Por exemplo, suponha que seu modelo aceite dois tensores como este:

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

Se você quiser passar tf.Tensor([[1,2],[3,4]]) como tensor_1 e tf.Tensor([[5,6], [7,8]]) como tensor_2, crie um DataFrame como este para passar ao modelo:

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

Então o tensors DataFrame fica assim:

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

Da mesma forma, se seu modelo retornar dois tensores, como (tf.Tensor([[1,2],[3,4]]), tf.Tensor([[5,6], [7,8]])), o resultado será um DataFrame como o acima.

Ao fornecer dados de entrada de amostra para um modelo TensorFlow, é necessário fornecer uma lista de tensores (que serão convertidos em DataFrame pandas) ou um DataFrame. Uma lista pode conter um único tensor, mas um tensor por si só não é aceito.

Registro do modelo

As seguintes opções adicionais podem ser usadas no dicionário options quando você chamar log_model:

Opção

Descrição

target_methods

Uma lista dos nomes dos métodos disponíveis no objeto modelo. O padrão dos modelos TensorFlow é forward.

cuda_version

A versão do tempo de execução CUDA a ser usada ao implantar em uma plataforma com GPU; o padrão é 11.7. Se definido manualmente como None, o modelo não poderá ser implementado em uma plataforma com GPU.

Você deve especificar o parâmetro sample_input_data ou signatures ao registrar um modelo TensorFlow para que o registro conheça as assinaturas dos métodos de destino.

Exemplo

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

Modelos MLFlow que fornecem um tipo PyFunc são suportados. Se o seu modelo MLFlow tiver uma assinatura, o argumento signature será inferido do modelo. Caso contrário, você deverá fornecer signature ou sample_input_data.

As seguintes opções adicionais podem ser usadas no dicionário options quando você chamar log_model:

Opção

Descrição

model_uri

O URI dos artefatos do modelo MLFlow. Deve ser fornecido se não estiver disponível nos metadados do modelo como model.metadata.get_model_info().model_uri.

ignore_mlflow_metadata

Se True, os metadados do modelo não serão importados para o objeto de modelo no registro. Padrão: False

ignore_mlflow_dependencies

Se True, as dependências nos metadados do modelo serão ignoradas, o que é útil devido às limitações disponíveis do pacote nos warehouses do Snowflake. Padrão: False

Exemplo

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

Pipeline do Hugging Face

Nota

Para obter detalhes sobre a entrada e saída esperadas de tipos específicos de pipelines Hugging Face, consulte Assinaturas inferidas para pipelines Hugging Face.

O registro oferece suporte a classes de modelo Hugging Face definidas como transformadores que derivam de transformers.Pipeline. O código a seguir é um exemplo de registro de um modelo compatível:

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

Importante

Um modelo baseado em huggingface_pipeline.HuggingFacePipelineModel contém apenas dados de configuração; os pesos do modelo são baixados do Hugging Face Hub sempre que o modelo é usado.

O registro de modelo atualmente oferece suporte à implementação de modelos apenas em warehouses. Os warehouses não oferecem suporte ao acesso à rede externa sem configuração especial. Mesmo que as integrações de acesso externo necessárias tenham sido criadas, neste momento não há como especificar quais integrações um modelo específico precisa.

A prática recomendada atual é usar transformers.Pipeline conforme mostrado no exemplo acima. Isso baixa os pesos do modelo para o seu sistema local e carrega o modelo inteiro para o warehouse. Isso resulta em um modelo independente que não precisa de acesso à Internet.

O registro infere o argumento signatures somente se o pipeline contiver uma tarefa da seguinte lista:

  • conversational

  • fill-mask

  • question-answering

  • summarization

  • table-question-answering

  • text2text-generation

  • text-classification (também chamado de sentiment-analysis)

  • text-generation

  • token-classification (também chamado de ner)

  • translation

  • translation_xx_to_yy

  • zero-shot-classification

O argumento sample_input_data é completamente ignorado para modelos Hugging Face. Especifique o argumento signatures ao registrar um modelo Hugging Face que não está na lista acima, para que o registro saiba as assinaturas dos métodos de destino.

Para ver a assinatura inferida, use o método show_functions. O código a seguir, por exemplo, é o resultado de lmv.show_functions() onde lmv é o modelo registrado acima:

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

Com essas informações, é possível chamar o modelo da seguinte forma:

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

Notas de uso

  • Muitos modelos Hugging Face são grandes e não cabem em um warehouse padrão. Use um warehouse otimizado para Snowpark ou escolha uma versão menor do modelo. Por exemplo, em vez de usar o modelo Llama-2-70b-chat-hf, tente Llama-2-7b-chat-hf.

  • Os warehouses Snowflake não têm GPUs. Use apenas modelos Hugging Face otimizados para CPU.

  • Alguns transformadores Hugging Face retornam uma matriz de dicionários por linha de entrada. O registro converte essa saída em uma cadeia de caracteres contendo uma representação JSON da matriz. Por exemplo, a saída de resposta a perguntas com múltiplas saídas é semelhante a esta:

    [{"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

Você deve especificar o parâmetro sample_input_data ou signatures ao registrar um modelo Hugging Face para que o registro conheça as assinaturas dos métodos de destino.

Exemplo

# 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

Resultado:

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