Snowflake Model Registry : modèles personnalisés partitionnés

De nombreux ensembles de données peuvent être facilement partitionnés en plusieurs sous-ensembles indépendants. Par exemple, un ensemble de données contenant des données de vente pour une chaîne de magasins peut être partitionné par numéro de magasin. Un modèle distinct peut ensuite être entraîné pour chaque partition. Les opérations d’entraînement et d’inférence sur les partitions peuvent être parallélisées, réduisant ainsi le temps d’exécution de ces opérations. De plus, étant donné que les magasins individuels diffèrent probablement quelque peu dans la manière dont leurs caractéristiques affectent leurs ventes, cette approche peut en fait conduire à des inférences plus précises au niveau du magasin.

Snowflake Model Registry prend en charge le traitement distribué de l’entraînement et de l’inférence des données partitionnées lorsque :

  • L’ensemble de données contient une colonne qui identifie de manière fiable les partitions dans les données.

  • Les données de chaque partition individuelle ne sont pas corrélées avec les données des autres partitions et contiennent suffisamment de lignes pour entraîner le modèle.

  • Le modèle est sans état : il effectue à la fois l’ajustement (entraînement) et l’inférence (prédiction) à chaque fois qu’il est appelé et ne conserve pas les poids ou autres états du modèle entre les appels.

Avec Snowflake Model Registry, vous implémentez un entraînement et une inférence partitionnés à l’aide de modèles personnalisés. Lors de l’utilisation du modèle, le registre partitionne l’ensemble de données, ajuste et prédit les partitions en parallèle à l’aide de tous les nœuds et cœurs de votre entrepôt, puis combine les résultats en un seul ensemble de données.

Note

L’entraînement et l’inférence partitionnés nécessitent Snowpark ML (paquet snowflake-ml-python) version 1.5.0 ou ultérieure.

Définition et journalisation du modèle personnalisé

Comme expliqué dans Écrire la classe de modèle personnalisée, vous déclarez des méthodes d’inférence de modèle personnalisées avec le décorateur @custom_model.partitioned_inference_api (Snowpark ML version 1.5.4 ou ultérieure) ou @custom_model.inference_api décorateur (Snowpark ML versions 1.5.0 à 1.5.3).

class ExampleForecastingModel(custom_model.CustomModel):

  @custom_model.partitioned_inference_api
  def predict(self, input: pd.DataFrame) -> pd.DataFrame:
      # All data in the partition will be loaded in the input dataframe.
      #… implement model logic here …
      return output_df

my_model = ExampleForecastingModel()
Copy

Lors de la journalisation du modèle, fournissez un function_type de TABLE_FUNCTION dans le dictionnaire options avec les autres options que votre modèle nécessite.

reg = Registry(session=sp_session, database_name="ML", schema_name="REGISTRY")
mv = reg.log_model(my_model,
  model_name="my_model",
  version_name="v1",
  options={"function_type": "TABLE_FUNCTION"},    ###
  conda_dependencies=["scikit-learn"],
  sample_input_data=train_features
)
Copy

Si votre modèle personnalisé possède également des fonctions régulières (non tabulaires) comme méthodes, vous pouvez à la place utiliser le dictionnaire method_options pour spécifier le type de chaque méthode.

model_version = reg.log_model(my_model,
    model_name="my_model",
    version_name="v1",
    options={
      "method_options": {                                 ###
        "METHOD1": {"function_type": "TABLE_FUNCTION"},   ###
        "METHOD2": {"function_type": "FUNCTION"}          ###
      }
    }
    conda_dependencies=["scikit-learn"],
    sample_input_data=train_features
)
Copy

Effectuer l’entraînement et l’inférence

Utilisez la méthode run d’un objet ModelVersion Python pour appeler les méthodes de fonction de table de manière partitionnée, en transmettant partition_column pour spécifier le nom de la colonne qui contient une valeur numérique ou une chaîne qui identifie la partition de chaque enregistrement. Comme d’habitude, vous pourrez passer devant un Snowpark ou un DataFrame pandas (ce dernier est utile pour les tests locaux). Vous recevrez le même type de DataFrame en conséquence. Dans ces exemples, nous partitionnons sur un numéro de magasin.

mv.run(
  input_df,
  function_name="PREDICT",
  partition_column="STORE_NUMBER"
)
Copy

Vous pouvez également appeler ces méthodes à l’aide de données partitionnées à partir de SQL, comme indiqué ici.

SELECT OUTPUT1, OUTPUT2, PARTITION_COLUMN
  FROM input_table,
      table(
          MY_MODEL!PREDICT(input_table.INPUT1, input_table.INPUT2)
          OVER (PARTITION BY input_table.STORE_NUMBER)
      )
  ORDER BY input_table.STORE_NUMBER;
Copy

Les données d’entrée sont automatiquement réparties entre les nœuds et les cœurs de votre entrepôt et les partitions sont traitées en parallèle.

Astuce

De nombreux ensembles de données peuvent être partitionnés de plusieurs manières. Étant donné que la colonne de partition est spécifiée lorsque vous appelez le modèle, et non lorsque vous l’enregistrez, vous pouvez facilement essayer différents schémas de partitionnement sans modifier le modèle. Par exemple, dans l’ensemble de données hypothétiques sur les ventes en magasin, vous pouvez effectuer une partition par numéro de magasin ou par État ou province pour voir lequel prédit le plus efficacement.

Cela signifie également que vous n’avez pas besoin d’un modèle distinct pour le traitement non partitionné. Si vous ne spécifiez pas de colonne de partition, aucun partitionnement n’est effectué et toutes les données sont traitées ensemble comme d’habitude.

Exemple

Voir le Guide de démarrage rapide du modèle personnalisé partitionné pour un exemple, y compris des données d’échantillon.