snowflake-ml-python 1.0.1__py3-none-any.whl → 1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- snowflake/ml/_internal/env_utils.py +2 -1
- snowflake/ml/_internal/file_utils.py +35 -40
- snowflake/ml/_internal/telemetry.py +5 -8
- snowflake/ml/_internal/utils/identifier.py +74 -7
- snowflake/ml/_internal/utils/uri.py +7 -2
- snowflake/ml/model/_core_requirements.py +1 -1
- snowflake/ml/model/_deploy_client/image_builds/base_image_builder.py +15 -0
- snowflake/ml/model/_deploy_client/image_builds/client_image_builder.py +259 -0
- snowflake/ml/model/_deploy_client/image_builds/docker_context.py +89 -0
- snowflake/ml/model/_deploy_client/image_builds/gunicorn_run.sh +24 -0
- snowflake/ml/model/_deploy_client/image_builds/inference_server/main.py +118 -0
- snowflake/ml/model/_deploy_client/image_builds/templates/dockerfile_template +40 -0
- snowflake/ml/model/_deploy_client/snowservice/deploy.py +199 -0
- snowflake/ml/model/_deploy_client/snowservice/deploy_options.py +88 -0
- snowflake/ml/model/_deploy_client/snowservice/templates/service_spec_template +24 -0
- snowflake/ml/model/_deploy_client/utils/constants.py +47 -0
- snowflake/ml/model/_deploy_client/utils/snowservice_client.py +178 -0
- snowflake/ml/model/_deploy_client/warehouse/deploy.py +25 -28
- snowflake/ml/model/_deploy_client/warehouse/infer_template.py +7 -4
- snowflake/ml/model/_deployer.py +14 -27
- snowflake/ml/model/_env.py +4 -4
- snowflake/ml/model/_handlers/_base.py +3 -1
- snowflake/ml/model/_handlers/custom.py +14 -2
- snowflake/ml/model/_handlers/pytorch.py +186 -0
- snowflake/ml/model/_handlers/sklearn.py +14 -8
- snowflake/ml/model/_handlers/snowmlmodel.py +14 -9
- snowflake/ml/model/_handlers/torchscript.py +180 -0
- snowflake/ml/model/_handlers/xgboost.py +19 -9
- snowflake/ml/model/_model.py +27 -21
- snowflake/ml/model/_model_meta.py +33 -19
- snowflake/ml/model/model_signature.py +446 -66
- snowflake/ml/model/type_hints.py +28 -15
- snowflake/ml/modeling/calibration/calibrated_classifier_cv.py +79 -43
- snowflake/ml/modeling/cluster/affinity_propagation.py +79 -43
- snowflake/ml/modeling/cluster/agglomerative_clustering.py +79 -43
- snowflake/ml/modeling/cluster/birch.py +79 -43
- snowflake/ml/modeling/cluster/bisecting_k_means.py +79 -43
- snowflake/ml/modeling/cluster/dbscan.py +79 -43
- snowflake/ml/modeling/cluster/feature_agglomeration.py +79 -43
- snowflake/ml/modeling/cluster/k_means.py +79 -43
- snowflake/ml/modeling/cluster/mean_shift.py +79 -43
- snowflake/ml/modeling/cluster/mini_batch_k_means.py +79 -43
- snowflake/ml/modeling/cluster/optics.py +79 -43
- snowflake/ml/modeling/cluster/spectral_biclustering.py +79 -43
- snowflake/ml/modeling/cluster/spectral_clustering.py +79 -43
- snowflake/ml/modeling/cluster/spectral_coclustering.py +79 -43
- snowflake/ml/modeling/compose/column_transformer.py +79 -43
- snowflake/ml/modeling/compose/transformed_target_regressor.py +79 -43
- snowflake/ml/modeling/covariance/elliptic_envelope.py +79 -43
- snowflake/ml/modeling/covariance/empirical_covariance.py +79 -43
- snowflake/ml/modeling/covariance/graphical_lasso.py +79 -43
- snowflake/ml/modeling/covariance/graphical_lasso_cv.py +79 -43
- snowflake/ml/modeling/covariance/ledoit_wolf.py +79 -43
- snowflake/ml/modeling/covariance/min_cov_det.py +79 -43
- snowflake/ml/modeling/covariance/oas.py +79 -43
- snowflake/ml/modeling/covariance/shrunk_covariance.py +79 -43
- snowflake/ml/modeling/decomposition/dictionary_learning.py +79 -43
- snowflake/ml/modeling/decomposition/factor_analysis.py +79 -43
- snowflake/ml/modeling/decomposition/fast_ica.py +79 -43
- snowflake/ml/modeling/decomposition/incremental_pca.py +79 -43
- snowflake/ml/modeling/decomposition/kernel_pca.py +79 -43
- snowflake/ml/modeling/decomposition/mini_batch_dictionary_learning.py +79 -43
- snowflake/ml/modeling/decomposition/mini_batch_sparse_pca.py +79 -43
- snowflake/ml/modeling/decomposition/pca.py +79 -43
- snowflake/ml/modeling/decomposition/sparse_pca.py +79 -43
- snowflake/ml/modeling/decomposition/truncated_svd.py +79 -43
- snowflake/ml/modeling/discriminant_analysis/linear_discriminant_analysis.py +79 -43
- snowflake/ml/modeling/discriminant_analysis/quadratic_discriminant_analysis.py +79 -43
- snowflake/ml/modeling/ensemble/ada_boost_classifier.py +79 -43
- snowflake/ml/modeling/ensemble/ada_boost_regressor.py +79 -43
- snowflake/ml/modeling/ensemble/bagging_classifier.py +79 -43
- snowflake/ml/modeling/ensemble/bagging_regressor.py +79 -43
- snowflake/ml/modeling/ensemble/extra_trees_classifier.py +79 -43
- snowflake/ml/modeling/ensemble/extra_trees_regressor.py +79 -43
- snowflake/ml/modeling/ensemble/gradient_boosting_classifier.py +79 -43
- snowflake/ml/modeling/ensemble/gradient_boosting_regressor.py +79 -43
- snowflake/ml/modeling/ensemble/hist_gradient_boosting_classifier.py +79 -43
- snowflake/ml/modeling/ensemble/hist_gradient_boosting_regressor.py +79 -43
- snowflake/ml/modeling/ensemble/isolation_forest.py +79 -43
- snowflake/ml/modeling/ensemble/random_forest_classifier.py +79 -43
- snowflake/ml/modeling/ensemble/random_forest_regressor.py +79 -43
- snowflake/ml/modeling/ensemble/stacking_regressor.py +79 -43
- snowflake/ml/modeling/ensemble/voting_classifier.py +79 -43
- snowflake/ml/modeling/ensemble/voting_regressor.py +79 -43
- snowflake/ml/modeling/feature_selection/generic_univariate_select.py +79 -43
- snowflake/ml/modeling/feature_selection/select_fdr.py +79 -43
- snowflake/ml/modeling/feature_selection/select_fpr.py +79 -43
- snowflake/ml/modeling/feature_selection/select_fwe.py +79 -43
- snowflake/ml/modeling/feature_selection/select_k_best.py +79 -43
- snowflake/ml/modeling/feature_selection/select_percentile.py +79 -43
- snowflake/ml/modeling/feature_selection/sequential_feature_selector.py +79 -43
- snowflake/ml/modeling/feature_selection/variance_threshold.py +79 -43
- snowflake/ml/modeling/gaussian_process/gaussian_process_classifier.py +79 -43
- snowflake/ml/modeling/gaussian_process/gaussian_process_regressor.py +79 -43
- snowflake/ml/modeling/impute/iterative_imputer.py +79 -43
- snowflake/ml/modeling/impute/knn_imputer.py +79 -43
- snowflake/ml/modeling/impute/missing_indicator.py +79 -43
- snowflake/ml/modeling/kernel_approximation/additive_chi2_sampler.py +79 -43
- snowflake/ml/modeling/kernel_approximation/nystroem.py +79 -43
- snowflake/ml/modeling/kernel_approximation/polynomial_count_sketch.py +79 -43
- snowflake/ml/modeling/kernel_approximation/rbf_sampler.py +79 -43
- snowflake/ml/modeling/kernel_approximation/skewed_chi2_sampler.py +79 -43
- snowflake/ml/modeling/kernel_ridge/kernel_ridge.py +79 -43
- snowflake/ml/modeling/lightgbm/lgbm_classifier.py +79 -43
- snowflake/ml/modeling/lightgbm/lgbm_regressor.py +79 -43
- snowflake/ml/modeling/linear_model/ard_regression.py +79 -43
- snowflake/ml/modeling/linear_model/bayesian_ridge.py +79 -43
- snowflake/ml/modeling/linear_model/elastic_net.py +79 -43
- snowflake/ml/modeling/linear_model/elastic_net_cv.py +79 -43
- snowflake/ml/modeling/linear_model/gamma_regressor.py +79 -43
- snowflake/ml/modeling/linear_model/huber_regressor.py +79 -43
- snowflake/ml/modeling/linear_model/lars.py +79 -43
- snowflake/ml/modeling/linear_model/lars_cv.py +79 -43
- snowflake/ml/modeling/linear_model/lasso.py +79 -43
- snowflake/ml/modeling/linear_model/lasso_cv.py +79 -43
- snowflake/ml/modeling/linear_model/lasso_lars.py +79 -43
- snowflake/ml/modeling/linear_model/lasso_lars_cv.py +79 -43
- snowflake/ml/modeling/linear_model/lasso_lars_ic.py +79 -43
- snowflake/ml/modeling/linear_model/linear_regression.py +79 -43
- snowflake/ml/modeling/linear_model/logistic_regression.py +79 -43
- snowflake/ml/modeling/linear_model/logistic_regression_cv.py +79 -43
- snowflake/ml/modeling/linear_model/multi_task_elastic_net.py +79 -43
- snowflake/ml/modeling/linear_model/multi_task_elastic_net_cv.py +79 -43
- snowflake/ml/modeling/linear_model/multi_task_lasso.py +79 -43
- snowflake/ml/modeling/linear_model/multi_task_lasso_cv.py +79 -43
- snowflake/ml/modeling/linear_model/orthogonal_matching_pursuit.py +79 -43
- snowflake/ml/modeling/linear_model/passive_aggressive_classifier.py +79 -43
- snowflake/ml/modeling/linear_model/passive_aggressive_regressor.py +79 -43
- snowflake/ml/modeling/linear_model/perceptron.py +79 -43
- snowflake/ml/modeling/linear_model/poisson_regressor.py +79 -43
- snowflake/ml/modeling/linear_model/ransac_regressor.py +79 -43
- snowflake/ml/modeling/linear_model/ridge.py +79 -43
- snowflake/ml/modeling/linear_model/ridge_classifier.py +79 -43
- snowflake/ml/modeling/linear_model/ridge_classifier_cv.py +79 -43
- snowflake/ml/modeling/linear_model/ridge_cv.py +79 -43
- snowflake/ml/modeling/linear_model/sgd_classifier.py +79 -43
- snowflake/ml/modeling/linear_model/sgd_one_class_svm.py +79 -43
- snowflake/ml/modeling/linear_model/sgd_regressor.py +79 -43
- snowflake/ml/modeling/linear_model/theil_sen_regressor.py +79 -43
- snowflake/ml/modeling/linear_model/tweedie_regressor.py +79 -43
- snowflake/ml/modeling/manifold/isomap.py +79 -43
- snowflake/ml/modeling/manifold/mds.py +79 -43
- snowflake/ml/modeling/manifold/spectral_embedding.py +79 -43
- snowflake/ml/modeling/manifold/tsne.py +79 -43
- snowflake/ml/modeling/metrics/classification.py +6 -1
- snowflake/ml/modeling/metrics/regression.py +517 -9
- snowflake/ml/modeling/mixture/bayesian_gaussian_mixture.py +79 -43
- snowflake/ml/modeling/mixture/gaussian_mixture.py +79 -43
- snowflake/ml/modeling/model_selection/grid_search_cv.py +79 -43
- snowflake/ml/modeling/model_selection/randomized_search_cv.py +79 -43
- snowflake/ml/modeling/multiclass/one_vs_one_classifier.py +79 -43
- snowflake/ml/modeling/multiclass/one_vs_rest_classifier.py +79 -43
- snowflake/ml/modeling/multiclass/output_code_classifier.py +79 -43
- snowflake/ml/modeling/naive_bayes/bernoulli_nb.py +79 -43
- snowflake/ml/modeling/naive_bayes/categorical_nb.py +79 -43
- snowflake/ml/modeling/naive_bayes/complement_nb.py +79 -43
- snowflake/ml/modeling/naive_bayes/gaussian_nb.py +79 -43
- snowflake/ml/modeling/naive_bayes/multinomial_nb.py +79 -43
- snowflake/ml/modeling/neighbors/k_neighbors_classifier.py +79 -43
- snowflake/ml/modeling/neighbors/k_neighbors_regressor.py +79 -43
- snowflake/ml/modeling/neighbors/kernel_density.py +79 -43
- snowflake/ml/modeling/neighbors/local_outlier_factor.py +79 -43
- snowflake/ml/modeling/neighbors/nearest_centroid.py +79 -43
- snowflake/ml/modeling/neighbors/nearest_neighbors.py +79 -43
- snowflake/ml/modeling/neighbors/neighborhood_components_analysis.py +79 -43
- snowflake/ml/modeling/neighbors/radius_neighbors_classifier.py +79 -43
- snowflake/ml/modeling/neighbors/radius_neighbors_regressor.py +79 -43
- snowflake/ml/modeling/neural_network/bernoulli_rbm.py +79 -43
- snowflake/ml/modeling/neural_network/mlp_classifier.py +79 -43
- snowflake/ml/modeling/neural_network/mlp_regressor.py +79 -43
- snowflake/ml/modeling/pipeline/pipeline.py +24 -0
- snowflake/ml/modeling/preprocessing/one_hot_encoder.py +18 -19
- snowflake/ml/modeling/preprocessing/ordinal_encoder.py +2 -0
- snowflake/ml/modeling/preprocessing/polynomial_features.py +79 -43
- snowflake/ml/modeling/semi_supervised/label_propagation.py +79 -43
- snowflake/ml/modeling/semi_supervised/label_spreading.py +79 -43
- snowflake/ml/modeling/svm/linear_svc.py +79 -43
- snowflake/ml/modeling/svm/linear_svr.py +79 -43
- snowflake/ml/modeling/svm/nu_svc.py +79 -43
- snowflake/ml/modeling/svm/nu_svr.py +79 -43
- snowflake/ml/modeling/svm/svc.py +79 -43
- snowflake/ml/modeling/svm/svr.py +79 -43
- snowflake/ml/modeling/tree/decision_tree_classifier.py +79 -43
- snowflake/ml/modeling/tree/decision_tree_regressor.py +79 -43
- snowflake/ml/modeling/tree/extra_tree_classifier.py +79 -43
- snowflake/ml/modeling/tree/extra_tree_regressor.py +79 -43
- snowflake/ml/modeling/xgboost/xgb_classifier.py +79 -43
- snowflake/ml/modeling/xgboost/xgb_regressor.py +79 -43
- snowflake/ml/modeling/xgboost/xgbrf_classifier.py +79 -43
- snowflake/ml/modeling/xgboost/xgbrf_regressor.py +79 -43
- snowflake/ml/registry/model_registry.py +123 -121
- snowflake/ml/version.py +1 -1
- {snowflake_ml_python-1.0.1.dist-info → snowflake_ml_python-1.0.3.dist-info}/METADATA +50 -8
- snowflake_ml_python-1.0.3.dist-info/RECORD +259 -0
- snowflake_ml_python-1.0.1.dist-info/RECORD +0 -246
- {snowflake_ml_python-1.0.1.dist-info → snowflake_ml_python-1.0.3.dist-info}/WHEEL +0 -0
@@ -7,6 +7,7 @@
|
|
7
7
|
#
|
8
8
|
import inspect
|
9
9
|
import os
|
10
|
+
import posixpath
|
10
11
|
from typing import Iterable, Optional, Union, List, Any, Dict, Callable, Set
|
11
12
|
from uuid import uuid4
|
12
13
|
|
@@ -27,6 +28,7 @@ from snowflake.ml._internal.utils.temp_file_utils import cleanup_temp_files, get
|
|
27
28
|
from snowflake.snowpark import DataFrame, Session
|
28
29
|
from snowflake.snowpark.functions import pandas_udf, sproc
|
29
30
|
from snowflake.snowpark.types import PandasSeries
|
31
|
+
from snowflake.snowpark._internal.type_utils import convert_sp_to_sf_type
|
30
32
|
|
31
33
|
from snowflake.ml.model.model_signature import (
|
32
34
|
DataType,
|
@@ -261,7 +263,6 @@ class TweedieRegressor(BaseTransformer):
|
|
261
263
|
sample_weight_col: Optional[str] = None,
|
262
264
|
) -> None:
|
263
265
|
super().__init__()
|
264
|
-
self.id = str(uuid4()).replace("-", "_").upper()
|
265
266
|
deps: Set[str] = set([f'numpy=={np.__version__}', f'scikit-learn=={sklearn.__version__}', f'cloudpickle=={cp.__version__}'])
|
266
267
|
|
267
268
|
self._deps = list(deps)
|
@@ -289,6 +290,15 @@ class TweedieRegressor(BaseTransformer):
|
|
289
290
|
self.set_drop_input_cols(drop_input_cols)
|
290
291
|
self.set_sample_weight_col(sample_weight_col)
|
291
292
|
|
293
|
+
def _get_rand_id(self) -> str:
|
294
|
+
"""
|
295
|
+
Generate random id to be used in sproc and stage names.
|
296
|
+
|
297
|
+
Returns:
|
298
|
+
Random id string usable in sproc, table, and stage names.
|
299
|
+
"""
|
300
|
+
return str(uuid4()).replace("-", "_").upper()
|
301
|
+
|
292
302
|
def _infer_input_output_cols(self, dataset: Union[DataFrame, pd.DataFrame]) -> None:
|
293
303
|
"""
|
294
304
|
Infer `self.input_cols` and `self.output_cols` if they are not explicitly set.
|
@@ -367,7 +377,7 @@ class TweedieRegressor(BaseTransformer):
|
|
367
377
|
cp.dump(self._sklearn_object, local_transform_file)
|
368
378
|
|
369
379
|
# Create temp stage to run fit.
|
370
|
-
transform_stage_name = "SNOWML_TRANSFORM_{safe_id}".format(safe_id=self.
|
380
|
+
transform_stage_name = "SNOWML_TRANSFORM_{safe_id}".format(safe_id=self._get_rand_id())
|
371
381
|
stage_creation_query = f"CREATE OR REPLACE TEMPORARY STAGE {transform_stage_name};"
|
372
382
|
SqlResultValidator(
|
373
383
|
session=session,
|
@@ -380,11 +390,12 @@ class TweedieRegressor(BaseTransformer):
|
|
380
390
|
expected_value=f"Stage area {transform_stage_name} successfully created."
|
381
391
|
).validate()
|
382
392
|
|
383
|
-
|
393
|
+
# Use posixpath to construct stage paths
|
394
|
+
stage_transform_file_name = posixpath.join(transform_stage_name, os.path.basename(local_transform_file_name))
|
395
|
+
stage_result_file_name = posixpath.join(transform_stage_name, os.path.basename(local_transform_file_name))
|
384
396
|
local_result_file_name = get_temp_file_path()
|
385
|
-
stage_result_file_name = os.path.join(transform_stage_name, os.path.basename(local_transform_file_name))
|
386
397
|
|
387
|
-
fit_sproc_name = "SNOWML_FIT_{safe_id}".format(safe_id=self.
|
398
|
+
fit_sproc_name = "SNOWML_FIT_{safe_id}".format(safe_id=self._get_rand_id())
|
388
399
|
statement_params = telemetry.get_function_usage_statement_params(
|
389
400
|
project=_PROJECT,
|
390
401
|
subproject=_SUBPROJECT,
|
@@ -410,6 +421,7 @@ class TweedieRegressor(BaseTransformer):
|
|
410
421
|
replace=True,
|
411
422
|
session=session,
|
412
423
|
statement_params=statement_params,
|
424
|
+
anonymous=True
|
413
425
|
)
|
414
426
|
def fit_wrapper_sproc(
|
415
427
|
session: Session,
|
@@ -418,7 +430,8 @@ class TweedieRegressor(BaseTransformer):
|
|
418
430
|
stage_result_file_name: str,
|
419
431
|
input_cols: List[str],
|
420
432
|
label_cols: List[str],
|
421
|
-
sample_weight_col: Optional[str]
|
433
|
+
sample_weight_col: Optional[str],
|
434
|
+
statement_params: Dict[str, str]
|
422
435
|
) -> str:
|
423
436
|
import cloudpickle as cp
|
424
437
|
import numpy as np
|
@@ -485,15 +498,15 @@ class TweedieRegressor(BaseTransformer):
|
|
485
498
|
api_calls=[Session.call],
|
486
499
|
custom_tags=dict([("autogen", True)]),
|
487
500
|
)
|
488
|
-
sproc_export_file_name =
|
489
|
-
|
501
|
+
sproc_export_file_name = fit_wrapper_sproc(
|
502
|
+
session,
|
490
503
|
query,
|
491
504
|
stage_transform_file_name,
|
492
505
|
stage_result_file_name,
|
493
506
|
identifier.get_unescaped_names(self.input_cols),
|
494
507
|
identifier.get_unescaped_names(self.label_cols),
|
495
508
|
identifier.get_unescaped_names(self.sample_weight_col),
|
496
|
-
statement_params
|
509
|
+
statement_params,
|
497
510
|
)
|
498
511
|
|
499
512
|
if "|" in sproc_export_file_name:
|
@@ -503,7 +516,7 @@ class TweedieRegressor(BaseTransformer):
|
|
503
516
|
print("\n".join(fields[1:]))
|
504
517
|
|
505
518
|
session.file.get(
|
506
|
-
|
519
|
+
posixpath.join(stage_result_file_name, sproc_export_file_name),
|
507
520
|
local_result_file_name,
|
508
521
|
statement_params=statement_params
|
509
522
|
)
|
@@ -549,7 +562,7 @@ class TweedieRegressor(BaseTransformer):
|
|
549
562
|
|
550
563
|
# Register vectorized UDF for batch inference
|
551
564
|
batch_inference_udf_name = "SNOWML_BATCH_INFERENCE_{safe_id}_{method}".format(
|
552
|
-
safe_id=self.
|
565
|
+
safe_id=self._get_rand_id(), method=inference_method)
|
553
566
|
|
554
567
|
# Need to do this since if we use self._sklearn_object directly in the UDF, Snowpark
|
555
568
|
# will try to pickle all of self which fails.
|
@@ -641,7 +654,7 @@ class TweedieRegressor(BaseTransformer):
|
|
641
654
|
return transformed_pandas_df.to_dict("records")
|
642
655
|
|
643
656
|
batch_inference_table_name = "SNOWML_BATCH_INFERENCE_INPUT_TABLE_{safe_id}".format(
|
644
|
-
safe_id=self.
|
657
|
+
safe_id=self._get_rand_id()
|
645
658
|
)
|
646
659
|
|
647
660
|
pass_through_columns = self._get_pass_through_columns(dataset)
|
@@ -697,26 +710,37 @@ class TweedieRegressor(BaseTransformer):
|
|
697
710
|
# input cols need to match unquoted / quoted
|
698
711
|
input_cols = self.input_cols
|
699
712
|
unquoted_input_cols = identifier.get_unescaped_names(self.input_cols)
|
713
|
+
quoted_input_cols = identifier.get_escaped_names(unquoted_input_cols)
|
700
714
|
|
701
715
|
estimator = self._sklearn_object
|
702
716
|
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
717
|
+
features_required_by_estimator = getattr(estimator, "feature_names_in_") if hasattr(estimator, "feature_names_in_") else unquoted_input_cols
|
718
|
+
missing_features = []
|
719
|
+
features_in_dataset = set(dataset.columns)
|
720
|
+
columns_to_select = []
|
721
|
+
for i, f in enumerate(features_required_by_estimator):
|
722
|
+
if (
|
723
|
+
i >= len(input_cols)
|
724
|
+
or (input_cols[i] != f and unquoted_input_cols[i] != f and quoted_input_cols[i] != f)
|
725
|
+
or (input_cols[i] not in features_in_dataset and unquoted_input_cols[i] not in features_in_dataset
|
726
|
+
and quoted_input_cols[i] not in features_in_dataset)
|
727
|
+
):
|
728
|
+
missing_features.append(f)
|
729
|
+
elif input_cols[i] in features_in_dataset:
|
730
|
+
columns_to_select.append(input_cols[i])
|
731
|
+
elif unquoted_input_cols[i] in features_in_dataset:
|
732
|
+
columns_to_select.append(unquoted_input_cols[i])
|
733
|
+
else:
|
734
|
+
columns_to_select.append(quoted_input_cols[i])
|
735
|
+
|
736
|
+
if len(missing_features) > 0:
|
737
|
+
raise ValueError(
|
738
|
+
"The feature names should match with those that were passed during fit.\n"
|
739
|
+
f"Features seen during fit call but not present in the input: {missing_features}\n"
|
740
|
+
f"Features in the input dataframe : {input_cols}\n"
|
741
|
+
)
|
742
|
+
input_df = dataset[columns_to_select]
|
743
|
+
input_df.columns = features_required_by_estimator
|
720
744
|
|
721
745
|
transformed_numpy_array = getattr(estimator, inference_method)(
|
722
746
|
input_df
|
@@ -797,11 +821,18 @@ class TweedieRegressor(BaseTransformer):
|
|
797
821
|
Transformed dataset.
|
798
822
|
"""
|
799
823
|
if isinstance(dataset, DataFrame):
|
824
|
+
expected_type_inferred = "float"
|
825
|
+
# when it is classifier, infer the datatype from label columns
|
826
|
+
if expected_type_inferred == "" and 'predict' in self.model_signatures:
|
827
|
+
expected_type_inferred = convert_sp_to_sf_type(
|
828
|
+
self.model_signatures['predict'].outputs[0].as_snowpark_type()
|
829
|
+
)
|
830
|
+
|
800
831
|
output_df = self._batch_inference(
|
801
832
|
dataset=dataset,
|
802
833
|
inference_method="predict",
|
803
834
|
expected_output_cols_list=self.output_cols,
|
804
|
-
expected_output_cols_type=
|
835
|
+
expected_output_cols_type=expected_type_inferred,
|
805
836
|
)
|
806
837
|
elif isinstance(dataset, pd.DataFrame):
|
807
838
|
output_df = self._sklearn_inference(
|
@@ -872,10 +903,10 @@ class TweedieRegressor(BaseTransformer):
|
|
872
903
|
|
873
904
|
def _get_output_column_names(self, output_cols_prefix: str) -> List[str]:
|
874
905
|
""" Returns the list of output columns for predict_proba(), decision_function(), etc.. functions.
|
875
|
-
Returns
|
906
|
+
Returns a list with output_cols_prefix as the only element if the estimator is not a classifier.
|
876
907
|
"""
|
877
908
|
if getattr(self._sklearn_object, "classes_", None) is None:
|
878
|
-
return []
|
909
|
+
return [output_cols_prefix]
|
879
910
|
|
880
911
|
classes = self._sklearn_object.classes_
|
881
912
|
if isinstance(classes, numpy.ndarray):
|
@@ -1100,7 +1131,7 @@ class TweedieRegressor(BaseTransformer):
|
|
1100
1131
|
cp.dump(self._sklearn_object, local_score_file)
|
1101
1132
|
|
1102
1133
|
# Create temp stage to run score.
|
1103
|
-
score_stage_name = "SNOWML_SCORE_{safe_id}".format(safe_id=self.
|
1134
|
+
score_stage_name = "SNOWML_SCORE_{safe_id}".format(safe_id=self._get_rand_id())
|
1104
1135
|
session = dataset._session
|
1105
1136
|
stage_creation_query = f"CREATE OR REPLACE TEMPORARY STAGE {score_stage_name};"
|
1106
1137
|
SqlResultValidator(
|
@@ -1114,8 +1145,9 @@ class TweedieRegressor(BaseTransformer):
|
|
1114
1145
|
expected_value=f"Stage area {score_stage_name} successfully created."
|
1115
1146
|
).validate()
|
1116
1147
|
|
1117
|
-
|
1118
|
-
|
1148
|
+
# Use posixpath to construct stage paths
|
1149
|
+
stage_score_file_name = posixpath.join(score_stage_name, os.path.basename(local_score_file_name))
|
1150
|
+
score_sproc_name = "SNOWML_SCORE_{safe_id}".format(safe_id=self._get_rand_id())
|
1119
1151
|
statement_params = telemetry.get_function_usage_statement_params(
|
1120
1152
|
project=_PROJECT,
|
1121
1153
|
subproject=_SUBPROJECT,
|
@@ -1141,6 +1173,7 @@ class TweedieRegressor(BaseTransformer):
|
|
1141
1173
|
replace=True,
|
1142
1174
|
session=session,
|
1143
1175
|
statement_params=statement_params,
|
1176
|
+
anonymous=True
|
1144
1177
|
)
|
1145
1178
|
def score_wrapper_sproc(
|
1146
1179
|
session: Session,
|
@@ -1148,7 +1181,8 @@ class TweedieRegressor(BaseTransformer):
|
|
1148
1181
|
stage_score_file_name: str,
|
1149
1182
|
input_cols: List[str],
|
1150
1183
|
label_cols: List[str],
|
1151
|
-
sample_weight_col: Optional[str]
|
1184
|
+
sample_weight_col: Optional[str],
|
1185
|
+
statement_params: Dict[str, str]
|
1152
1186
|
) -> float:
|
1153
1187
|
import cloudpickle as cp
|
1154
1188
|
import numpy as np
|
@@ -1198,14 +1232,14 @@ class TweedieRegressor(BaseTransformer):
|
|
1198
1232
|
api_calls=[Session.call],
|
1199
1233
|
custom_tags=dict([("autogen", True)]),
|
1200
1234
|
)
|
1201
|
-
score =
|
1202
|
-
|
1235
|
+
score = score_wrapper_sproc(
|
1236
|
+
session,
|
1203
1237
|
query,
|
1204
1238
|
stage_score_file_name,
|
1205
1239
|
identifier.get_unescaped_names(self.input_cols),
|
1206
1240
|
identifier.get_unescaped_names(self.label_cols),
|
1207
1241
|
identifier.get_unescaped_names(self.sample_weight_col),
|
1208
|
-
statement_params
|
1242
|
+
statement_params,
|
1209
1243
|
)
|
1210
1244
|
|
1211
1245
|
cleanup_temp_files([local_score_file_name])
|
@@ -1223,18 +1257,20 @@ class TweedieRegressor(BaseTransformer):
|
|
1223
1257
|
if self._sklearn_object._estimator_type == 'classifier':
|
1224
1258
|
outputs = _infer_signature(dataset[self.label_cols], "output") # label columns is the desired type for output
|
1225
1259
|
outputs = _rename_features(outputs, self.output_cols) # rename the output columns
|
1226
|
-
self._model_signature_dict["predict"] = ModelSignature(inputs,
|
1260
|
+
self._model_signature_dict["predict"] = ModelSignature(inputs,
|
1261
|
+
([] if self._drop_input_cols else inputs) + outputs)
|
1227
1262
|
# For regressor, the type of predict is float64
|
1228
1263
|
elif self._sklearn_object._estimator_type == 'regressor':
|
1229
1264
|
outputs = [FeatureSpec(dtype=DataType.DOUBLE, name=c) for c in self.output_cols]
|
1230
|
-
self._model_signature_dict["predict"] = ModelSignature(inputs,
|
1231
|
-
|
1265
|
+
self._model_signature_dict["predict"] = ModelSignature(inputs,
|
1266
|
+
([] if self._drop_input_cols else inputs) + outputs)
|
1232
1267
|
for prob_func in PROB_FUNCTIONS:
|
1233
1268
|
if hasattr(self, prob_func):
|
1234
1269
|
output_cols_prefix: str = f"{prob_func}_"
|
1235
1270
|
output_column_names = self._get_output_column_names(output_cols_prefix)
|
1236
1271
|
outputs = [FeatureSpec(dtype=DataType.DOUBLE, name=c) for c in output_column_names]
|
1237
|
-
self._model_signature_dict[prob_func] = ModelSignature(inputs,
|
1272
|
+
self._model_signature_dict[prob_func] = ModelSignature(inputs,
|
1273
|
+
([] if self._drop_input_cols else inputs) + outputs)
|
1238
1274
|
|
1239
1275
|
@property
|
1240
1276
|
def model_signatures(self) -> Dict[str, ModelSignature]:
|
@@ -7,6 +7,7 @@
|
|
7
7
|
#
|
8
8
|
import inspect
|
9
9
|
import os
|
10
|
+
import posixpath
|
10
11
|
from typing import Iterable, Optional, Union, List, Any, Dict, Callable, Set
|
11
12
|
from uuid import uuid4
|
12
13
|
|
@@ -27,6 +28,7 @@ from snowflake.ml._internal.utils.temp_file_utils import cleanup_temp_files, get
|
|
27
28
|
from snowflake.snowpark import DataFrame, Session
|
28
29
|
from snowflake.snowpark.functions import pandas_udf, sproc
|
29
30
|
from snowflake.snowpark.types import PandasSeries
|
31
|
+
from snowflake.snowpark._internal.type_utils import convert_sp_to_sf_type
|
30
32
|
|
31
33
|
from snowflake.ml.model.model_signature import (
|
32
34
|
DataType,
|
@@ -256,7 +258,6 @@ class Isomap(BaseTransformer):
|
|
256
258
|
sample_weight_col: Optional[str] = None,
|
257
259
|
) -> None:
|
258
260
|
super().__init__()
|
259
|
-
self.id = str(uuid4()).replace("-", "_").upper()
|
260
261
|
deps: Set[str] = set([f'numpy=={np.__version__}', f'scikit-learn=={sklearn.__version__}', f'cloudpickle=={cp.__version__}'])
|
261
262
|
|
262
263
|
self._deps = list(deps)
|
@@ -287,6 +288,15 @@ class Isomap(BaseTransformer):
|
|
287
288
|
self.set_drop_input_cols(drop_input_cols)
|
288
289
|
self.set_sample_weight_col(sample_weight_col)
|
289
290
|
|
291
|
+
def _get_rand_id(self) -> str:
|
292
|
+
"""
|
293
|
+
Generate random id to be used in sproc and stage names.
|
294
|
+
|
295
|
+
Returns:
|
296
|
+
Random id string usable in sproc, table, and stage names.
|
297
|
+
"""
|
298
|
+
return str(uuid4()).replace("-", "_").upper()
|
299
|
+
|
290
300
|
def _infer_input_output_cols(self, dataset: Union[DataFrame, pd.DataFrame]) -> None:
|
291
301
|
"""
|
292
302
|
Infer `self.input_cols` and `self.output_cols` if they are not explicitly set.
|
@@ -365,7 +375,7 @@ class Isomap(BaseTransformer):
|
|
365
375
|
cp.dump(self._sklearn_object, local_transform_file)
|
366
376
|
|
367
377
|
# Create temp stage to run fit.
|
368
|
-
transform_stage_name = "SNOWML_TRANSFORM_{safe_id}".format(safe_id=self.
|
378
|
+
transform_stage_name = "SNOWML_TRANSFORM_{safe_id}".format(safe_id=self._get_rand_id())
|
369
379
|
stage_creation_query = f"CREATE OR REPLACE TEMPORARY STAGE {transform_stage_name};"
|
370
380
|
SqlResultValidator(
|
371
381
|
session=session,
|
@@ -378,11 +388,12 @@ class Isomap(BaseTransformer):
|
|
378
388
|
expected_value=f"Stage area {transform_stage_name} successfully created."
|
379
389
|
).validate()
|
380
390
|
|
381
|
-
|
391
|
+
# Use posixpath to construct stage paths
|
392
|
+
stage_transform_file_name = posixpath.join(transform_stage_name, os.path.basename(local_transform_file_name))
|
393
|
+
stage_result_file_name = posixpath.join(transform_stage_name, os.path.basename(local_transform_file_name))
|
382
394
|
local_result_file_name = get_temp_file_path()
|
383
|
-
stage_result_file_name = os.path.join(transform_stage_name, os.path.basename(local_transform_file_name))
|
384
395
|
|
385
|
-
fit_sproc_name = "SNOWML_FIT_{safe_id}".format(safe_id=self.
|
396
|
+
fit_sproc_name = "SNOWML_FIT_{safe_id}".format(safe_id=self._get_rand_id())
|
386
397
|
statement_params = telemetry.get_function_usage_statement_params(
|
387
398
|
project=_PROJECT,
|
388
399
|
subproject=_SUBPROJECT,
|
@@ -408,6 +419,7 @@ class Isomap(BaseTransformer):
|
|
408
419
|
replace=True,
|
409
420
|
session=session,
|
410
421
|
statement_params=statement_params,
|
422
|
+
anonymous=True
|
411
423
|
)
|
412
424
|
def fit_wrapper_sproc(
|
413
425
|
session: Session,
|
@@ -416,7 +428,8 @@ class Isomap(BaseTransformer):
|
|
416
428
|
stage_result_file_name: str,
|
417
429
|
input_cols: List[str],
|
418
430
|
label_cols: List[str],
|
419
|
-
sample_weight_col: Optional[str]
|
431
|
+
sample_weight_col: Optional[str],
|
432
|
+
statement_params: Dict[str, str]
|
420
433
|
) -> str:
|
421
434
|
import cloudpickle as cp
|
422
435
|
import numpy as np
|
@@ -483,15 +496,15 @@ class Isomap(BaseTransformer):
|
|
483
496
|
api_calls=[Session.call],
|
484
497
|
custom_tags=dict([("autogen", True)]),
|
485
498
|
)
|
486
|
-
sproc_export_file_name =
|
487
|
-
|
499
|
+
sproc_export_file_name = fit_wrapper_sproc(
|
500
|
+
session,
|
488
501
|
query,
|
489
502
|
stage_transform_file_name,
|
490
503
|
stage_result_file_name,
|
491
504
|
identifier.get_unescaped_names(self.input_cols),
|
492
505
|
identifier.get_unescaped_names(self.label_cols),
|
493
506
|
identifier.get_unescaped_names(self.sample_weight_col),
|
494
|
-
statement_params
|
507
|
+
statement_params,
|
495
508
|
)
|
496
509
|
|
497
510
|
if "|" in sproc_export_file_name:
|
@@ -501,7 +514,7 @@ class Isomap(BaseTransformer):
|
|
501
514
|
print("\n".join(fields[1:]))
|
502
515
|
|
503
516
|
session.file.get(
|
504
|
-
|
517
|
+
posixpath.join(stage_result_file_name, sproc_export_file_name),
|
505
518
|
local_result_file_name,
|
506
519
|
statement_params=statement_params
|
507
520
|
)
|
@@ -547,7 +560,7 @@ class Isomap(BaseTransformer):
|
|
547
560
|
|
548
561
|
# Register vectorized UDF for batch inference
|
549
562
|
batch_inference_udf_name = "SNOWML_BATCH_INFERENCE_{safe_id}_{method}".format(
|
550
|
-
safe_id=self.
|
563
|
+
safe_id=self._get_rand_id(), method=inference_method)
|
551
564
|
|
552
565
|
# Need to do this since if we use self._sklearn_object directly in the UDF, Snowpark
|
553
566
|
# will try to pickle all of self which fails.
|
@@ -639,7 +652,7 @@ class Isomap(BaseTransformer):
|
|
639
652
|
return transformed_pandas_df.to_dict("records")
|
640
653
|
|
641
654
|
batch_inference_table_name = "SNOWML_BATCH_INFERENCE_INPUT_TABLE_{safe_id}".format(
|
642
|
-
safe_id=self.
|
655
|
+
safe_id=self._get_rand_id()
|
643
656
|
)
|
644
657
|
|
645
658
|
pass_through_columns = self._get_pass_through_columns(dataset)
|
@@ -695,26 +708,37 @@ class Isomap(BaseTransformer):
|
|
695
708
|
# input cols need to match unquoted / quoted
|
696
709
|
input_cols = self.input_cols
|
697
710
|
unquoted_input_cols = identifier.get_unescaped_names(self.input_cols)
|
711
|
+
quoted_input_cols = identifier.get_escaped_names(unquoted_input_cols)
|
698
712
|
|
699
713
|
estimator = self._sklearn_object
|
700
714
|
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
715
|
+
features_required_by_estimator = getattr(estimator, "feature_names_in_") if hasattr(estimator, "feature_names_in_") else unquoted_input_cols
|
716
|
+
missing_features = []
|
717
|
+
features_in_dataset = set(dataset.columns)
|
718
|
+
columns_to_select = []
|
719
|
+
for i, f in enumerate(features_required_by_estimator):
|
720
|
+
if (
|
721
|
+
i >= len(input_cols)
|
722
|
+
or (input_cols[i] != f and unquoted_input_cols[i] != f and quoted_input_cols[i] != f)
|
723
|
+
or (input_cols[i] not in features_in_dataset and unquoted_input_cols[i] not in features_in_dataset
|
724
|
+
and quoted_input_cols[i] not in features_in_dataset)
|
725
|
+
):
|
726
|
+
missing_features.append(f)
|
727
|
+
elif input_cols[i] in features_in_dataset:
|
728
|
+
columns_to_select.append(input_cols[i])
|
729
|
+
elif unquoted_input_cols[i] in features_in_dataset:
|
730
|
+
columns_to_select.append(unquoted_input_cols[i])
|
731
|
+
else:
|
732
|
+
columns_to_select.append(quoted_input_cols[i])
|
733
|
+
|
734
|
+
if len(missing_features) > 0:
|
735
|
+
raise ValueError(
|
736
|
+
"The feature names should match with those that were passed during fit.\n"
|
737
|
+
f"Features seen during fit call but not present in the input: {missing_features}\n"
|
738
|
+
f"Features in the input dataframe : {input_cols}\n"
|
739
|
+
)
|
740
|
+
input_df = dataset[columns_to_select]
|
741
|
+
input_df.columns = features_required_by_estimator
|
718
742
|
|
719
743
|
transformed_numpy_array = getattr(estimator, inference_method)(
|
720
744
|
input_df
|
@@ -793,11 +817,18 @@ class Isomap(BaseTransformer):
|
|
793
817
|
Transformed dataset.
|
794
818
|
"""
|
795
819
|
if isinstance(dataset, DataFrame):
|
820
|
+
expected_type_inferred = ""
|
821
|
+
# when it is classifier, infer the datatype from label columns
|
822
|
+
if expected_type_inferred == "" and 'predict' in self.model_signatures:
|
823
|
+
expected_type_inferred = convert_sp_to_sf_type(
|
824
|
+
self.model_signatures['predict'].outputs[0].as_snowpark_type()
|
825
|
+
)
|
826
|
+
|
796
827
|
output_df = self._batch_inference(
|
797
828
|
dataset=dataset,
|
798
829
|
inference_method="predict",
|
799
830
|
expected_output_cols_list=self.output_cols,
|
800
|
-
expected_output_cols_type=
|
831
|
+
expected_output_cols_type=expected_type_inferred,
|
801
832
|
)
|
802
833
|
elif isinstance(dataset, pd.DataFrame):
|
803
834
|
output_df = self._sklearn_inference(
|
@@ -870,10 +901,10 @@ class Isomap(BaseTransformer):
|
|
870
901
|
|
871
902
|
def _get_output_column_names(self, output_cols_prefix: str) -> List[str]:
|
872
903
|
""" Returns the list of output columns for predict_proba(), decision_function(), etc.. functions.
|
873
|
-
Returns
|
904
|
+
Returns a list with output_cols_prefix as the only element if the estimator is not a classifier.
|
874
905
|
"""
|
875
906
|
if getattr(self._sklearn_object, "classes_", None) is None:
|
876
|
-
return []
|
907
|
+
return [output_cols_prefix]
|
877
908
|
|
878
909
|
classes = self._sklearn_object.classes_
|
879
910
|
if isinstance(classes, numpy.ndarray):
|
@@ -1098,7 +1129,7 @@ class Isomap(BaseTransformer):
|
|
1098
1129
|
cp.dump(self._sklearn_object, local_score_file)
|
1099
1130
|
|
1100
1131
|
# Create temp stage to run score.
|
1101
|
-
score_stage_name = "SNOWML_SCORE_{safe_id}".format(safe_id=self.
|
1132
|
+
score_stage_name = "SNOWML_SCORE_{safe_id}".format(safe_id=self._get_rand_id())
|
1102
1133
|
session = dataset._session
|
1103
1134
|
stage_creation_query = f"CREATE OR REPLACE TEMPORARY STAGE {score_stage_name};"
|
1104
1135
|
SqlResultValidator(
|
@@ -1112,8 +1143,9 @@ class Isomap(BaseTransformer):
|
|
1112
1143
|
expected_value=f"Stage area {score_stage_name} successfully created."
|
1113
1144
|
).validate()
|
1114
1145
|
|
1115
|
-
|
1116
|
-
|
1146
|
+
# Use posixpath to construct stage paths
|
1147
|
+
stage_score_file_name = posixpath.join(score_stage_name, os.path.basename(local_score_file_name))
|
1148
|
+
score_sproc_name = "SNOWML_SCORE_{safe_id}".format(safe_id=self._get_rand_id())
|
1117
1149
|
statement_params = telemetry.get_function_usage_statement_params(
|
1118
1150
|
project=_PROJECT,
|
1119
1151
|
subproject=_SUBPROJECT,
|
@@ -1139,6 +1171,7 @@ class Isomap(BaseTransformer):
|
|
1139
1171
|
replace=True,
|
1140
1172
|
session=session,
|
1141
1173
|
statement_params=statement_params,
|
1174
|
+
anonymous=True
|
1142
1175
|
)
|
1143
1176
|
def score_wrapper_sproc(
|
1144
1177
|
session: Session,
|
@@ -1146,7 +1179,8 @@ class Isomap(BaseTransformer):
|
|
1146
1179
|
stage_score_file_name: str,
|
1147
1180
|
input_cols: List[str],
|
1148
1181
|
label_cols: List[str],
|
1149
|
-
sample_weight_col: Optional[str]
|
1182
|
+
sample_weight_col: Optional[str],
|
1183
|
+
statement_params: Dict[str, str]
|
1150
1184
|
) -> float:
|
1151
1185
|
import cloudpickle as cp
|
1152
1186
|
import numpy as np
|
@@ -1196,14 +1230,14 @@ class Isomap(BaseTransformer):
|
|
1196
1230
|
api_calls=[Session.call],
|
1197
1231
|
custom_tags=dict([("autogen", True)]),
|
1198
1232
|
)
|
1199
|
-
score =
|
1200
|
-
|
1233
|
+
score = score_wrapper_sproc(
|
1234
|
+
session,
|
1201
1235
|
query,
|
1202
1236
|
stage_score_file_name,
|
1203
1237
|
identifier.get_unescaped_names(self.input_cols),
|
1204
1238
|
identifier.get_unescaped_names(self.label_cols),
|
1205
1239
|
identifier.get_unescaped_names(self.sample_weight_col),
|
1206
|
-
statement_params
|
1240
|
+
statement_params,
|
1207
1241
|
)
|
1208
1242
|
|
1209
1243
|
cleanup_temp_files([local_score_file_name])
|
@@ -1221,18 +1255,20 @@ class Isomap(BaseTransformer):
|
|
1221
1255
|
if self._sklearn_object._estimator_type == 'classifier':
|
1222
1256
|
outputs = _infer_signature(dataset[self.label_cols], "output") # label columns is the desired type for output
|
1223
1257
|
outputs = _rename_features(outputs, self.output_cols) # rename the output columns
|
1224
|
-
self._model_signature_dict["predict"] = ModelSignature(inputs,
|
1258
|
+
self._model_signature_dict["predict"] = ModelSignature(inputs,
|
1259
|
+
([] if self._drop_input_cols else inputs) + outputs)
|
1225
1260
|
# For regressor, the type of predict is float64
|
1226
1261
|
elif self._sklearn_object._estimator_type == 'regressor':
|
1227
1262
|
outputs = [FeatureSpec(dtype=DataType.DOUBLE, name=c) for c in self.output_cols]
|
1228
|
-
self._model_signature_dict["predict"] = ModelSignature(inputs,
|
1229
|
-
|
1263
|
+
self._model_signature_dict["predict"] = ModelSignature(inputs,
|
1264
|
+
([] if self._drop_input_cols else inputs) + outputs)
|
1230
1265
|
for prob_func in PROB_FUNCTIONS:
|
1231
1266
|
if hasattr(self, prob_func):
|
1232
1267
|
output_cols_prefix: str = f"{prob_func}_"
|
1233
1268
|
output_column_names = self._get_output_column_names(output_cols_prefix)
|
1234
1269
|
outputs = [FeatureSpec(dtype=DataType.DOUBLE, name=c) for c in output_column_names]
|
1235
|
-
self._model_signature_dict[prob_func] = ModelSignature(inputs,
|
1270
|
+
self._model_signature_dict[prob_func] = ModelSignature(inputs,
|
1271
|
+
([] if self._drop_input_cols else inputs) + outputs)
|
1236
1272
|
|
1237
1273
|
@property
|
1238
1274
|
def model_signatures(self) -> Dict[str, ModelSignature]:
|