Spécification des signatures de modèles¶
Pour garantir une expérience cohérente quel que soit l’endroit où un modèle est exécuté, le registre de modèles de Snowflake doit connaître le schéma d’entrée et de sortie des méthodes d’inférence du modèle : c’est-à-dire le nom et le type de toutes les colonnes du DataFrame d’entrée ou de sortie. Cela permet de mapper ces colonnes entre les types de données Python et SQL si nécessaire. Ce schéma est appelé signature par analogie avec les arguments d’une fonction et leurs types.
Pour certains cadres ML, le registre des modèles peut déduire ces schémas, soit à partir des structures de données du modèle lui-même, soit à partir d’un échantillon de données d’entrée. Cependant, les modèles acceptent ou renvoient souvent des objets dépourvus de ces informations, tels que les tableaux NumPy. Dans ces cas, Snowpark ML déduit les noms des fonctions d’entrée comme input_feature_1
, input_feature_2
, et ainsi de suite. De même, les fonctionnalités de sortie sont nommées output_feature_1
, output_feature_2
, etc.
Pour utiliser des noms plus significatifs dans vos modèles personnalisés, vous pouvez procéder de l’une des manières suivantes :
Mettez à jour
sample_input_data
avec les noms des colonnes, généralement en le convertissant au format pandas ou Snowpark DataFrame.Transmettez explicitement les signatures à
log_model
. Lorsqu’un modèle ne produit pas de noms dans ses sorties, les signatures explicites peuvent être la seule option.
Déduire une signature¶
Tout comme le registre des modèles, vous pouvez générer des signatures automatiquement. Utilisez snowflake.ml.model.model_signature.infer_signature
pour déduire une signature basée sur les noms d’entrée, de sortie et de colonne de l’échantillon fourni, puis appliquez cette signature aux méthodes appropriées lors de l’enregistrement du modèle, comme dans l’exemple ci-dessous :
import pandas as pd
from sklearn import svm, datasets
from snowflake.ml.model import model_signature
digits = datasets.load_digits()
target_digit = 6
def one_vs_all(dataset, digit):
return [x == digit for x in dataset]
train_features = digits.data[:10]
train_labels = one_vs_all(digits.target[:10], target_digit)
clf = svm.SVC(gamma=0.001, C=10.0, probability=True)
clf.fit(train_features, train_labels)
sig = model_signature.infer_signature(
train_features,
labels_df,
input_feature_names=['column1', 'column2', ...],
output_feature_names=['is_target_digit'])
# Supply a signature for every function the model exposes, in this case only `predict`.
mv = reg.log_model(
clf,
model_name='my_model',
version_name='v1',
signatures={"predict": sig}
)
Cet exemple applique la signature à une seule méthode, mais vous pouvez déduire une signature pour chaque méthode exposée par votre modèle. Vous pouvez utiliser le même objet de signature (sig
dans l’exemple) pour toutes les méthodes qui ont la même signature.
Construction d’une signature¶
Vous pouvez également construire manuellement une signature à l’aide de snowflake.ml.model.model_signature.ModelSignature
. Les types scalaires et tensoriels (y compris les tenseurs en escalier) sont pris en charge.
Exemple :
from snowflake.ml.model.model_signature import ModelSignature, FeatureSpec, DataType
sig = ModelSignature(
inputs=[
FeatureSpec(dtype=DataType.DOUBLE, name=f_0),
FeatureSpec(dtype=DataType.INT64, name=sparse_0_fixed_len, shape=(5, 5)),
FeatureSpec(dtype=DataType.INT64, name=sparse_1_variable_len, shape=(-1,)),
],
outputs=[
FeatureSpec(dtype=DataType.FLOAT, name=output),
]
)
Transmettez ensuite l’objet de signature, sig
, à log_model
avec l’argument signatures
comme dans l’exemple ci-dessus pour les méthodes auxquelles il s’applique.
Mappages de types de données¶
Cette section décrit l’équivalence des types dans le registre de modèles de Snowflake pour les systèmes de types pris en charge.
Types de données de colonnes¶
Le tableau suivant montre l’équivalence entre le type de signature de modèle (SQL), le type pandas DataFrames (NumPy) et le type Snowpark Python.
Type de signature du modèle (SQL) |
Type pandas DataFrame (NumPy) |
Type Snowpark Python |
---|---|---|
INT8 |
|
|
INT16 |
|
|
INT32 |
|
|
INT64 |
|
|
FLOAT |
|
|
DOUBLE |
|
|
UINT8 |
|
|
UINT16 |
|
|
UINT32 |
|
|
UINT64 |
|
|
BOOL |
|
|
STRING |
|
|
BYTES |
|
|
TIMESTAMP_NTZ |
|
|
La représentation des fonctions tensorielles dont la forme est spécifiée utilise np.object_
.
Valeurs manquantes¶
Si sample_input_data
est utilisé pour déduire la signature du modèle, il ne doit généralement pas contenir de valeurs NULL. Le registre des modèles tente de déduire les signatures à partir des données fournies, mais il n’y parvient pas toujours complètement. La meilleure pratique consiste à empêcher les valeurs NULLs d’être incluses dans les données de l’échantillon le plus tôt possible, par exemple immédiatement après l’entrée des données.
Conversion depuis NumPy¶
Si le type de données NumPy peut être converti en toute sécurité en un type NumPy indiqué dans Types de données de colonnes, il est considéré comme le type de données correspondant.
Conversion depuis PyTorch¶
Type PyTorch |
Type de signature du modèle (SQL) |
---|---|
|
UINT8 |
|
INT8 |
|
INT16 |
|
INT32 |
|
INT64 |
|
FLOAT |
|
DOUBLE |
|
BOOL |
Conversion depuis Snowpark¶
Outre les mappages indiqués dans Types de données de colonnes, les conversions suivantes s’appliquent :
DecimalType
avec une échelle de 0 correspond à INT64.DecimalType
avec une échelle supérieure à 0 correspond à DOUBLE.