bigquery-data-science 0.7.0__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.
- bigquery_data_science/__init__.py +58 -0
- bigquery_data_science/_skills/PLANS.md +76 -0
- bigquery_data_science/_skills/bigquery-ai/SKILL.md +66 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_agg.md +528 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_classify.md +450 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_count_tokens.md +180 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_detect_anomalies.md +322 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_embed.md +425 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_evaluate.md +368 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_forecast.md +437 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_generate.md +693 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_generate_bool.md +248 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_generate_double.md +254 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_generate_embedding.md +402 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_generate_int.md +252 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_generate_table.md +447 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_generate_text.md +356 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_if.md +373 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_key_drivers.md +331 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_parse_document.md +416 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_predict.md +559 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_score.md +310 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_search.md +465 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ai_similarity.md +371 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/catalog_search.md +951 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/content_analysis.md +284 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/content_moderation.md +369 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/data_enrichment.md +426 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/document_intelligence.md +470 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/document_rag.md +453 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/image_deduplication.md +770 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/log_analysis.md +668 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/metric_diagnostics.md +568 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ml_annotate_image.md +680 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ml_generate_embedding.md +217 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ml_generate_text.md +223 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ml_process_document.md +392 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ml_transcribe.md +815 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ml_translate.md +600 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/ml_understand_text.md +673 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/multimodal_analysis.md +266 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/rag_pipeline.md +593 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/semantic_search.md +510 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/tabular_prediction.md +485 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/time_series_intelligence.md +489 -0
- bigquery_data_science/_skills/bigquery-ai/narrative/vector_search.md +672 -0
- bigquery_data_science/_skills/bigquery-ai/reference/augmented-analytics.md +77 -0
- bigquery_data_science/_skills/bigquery-ai/reference/cloud-ai-service-models.md +88 -0
- bigquery_data_science/_skills/bigquery-ai/reference/document-processing.md +95 -0
- bigquery_data_science/_skills/bigquery-ai/reference/embeddings-and-search.md +166 -0
- bigquery_data_science/_skills/bigquery-ai/reference/general-purpose-generation.md +87 -0
- bigquery_data_science/_skills/bigquery-ai/reference/managed-functions.md +72 -0
- bigquery_data_science/_skills/bigquery-ai/reference/predictive-ai.md +113 -0
- bigquery_data_science/_skills/bigquery-ai/reference/workflows.md +56 -0
- bigquery_data_science/_skills/bigquery-ai/skill.manifest.json +109 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/INDEX.md +71 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aiagg.md +67 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aicausal_effect-covered-in-bigquery-ml.md +17 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aiclassify.md +72 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aicount_tokens.md +53 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aidetect_anomalies.md +63 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aiembed.md +85 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aievaluate.md +114 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aiforecast.md +123 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aigenerate.md +69 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aigenerate_bool.md +53 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aigenerate_double.md +45 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aigenerate_embedding.md +108 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aigenerate_int.md +45 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aigenerate_table.md +64 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aigenerate_text.md +167 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aiif.md +56 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aikey_drivers.md +76 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aiparse_document.md +91 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aipredict.md +74 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aiscore.md +52 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aisearch.md +66 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/aisimilarity.md +79 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/choosing-between-these-and-the-ai-functions.md +11 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/hybrid-search-capability.md +165 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/mlannotate_image.md +24 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/mlgenerate_embedding.md +34 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/mlgenerate_text.md +65 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/mlprocess_document.md +125 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/mltranscribe.md +26 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/mltranslate.md +27 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/mlunderstand_text.md +32 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/multimodal-input-patterns-by-function.md +128 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/object-tables.md +109 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/objectref-and-objectrefruntime-schema-reference.md +50 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/objfetch_metadata.md +49 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/objget_access_url.md +66 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/objget_read_url.md +40 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/objlist.md +34 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/objmake_ref.md +58 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/per-row-failures-and-the-retry-pattern.md +19 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/setup-apis-connection-roles.md +39 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/two-input-shapes.md +22 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/vector_search.md +78 -0
- bigquery_data_science/_skills/bigquery-ai/syntax/what-the-five-have-in-common.md +27 -0
- bigquery_data_science/_skills/bigquery-data-science/SKILL.md +69 -0
- bigquery_data_science/_skills/bigquery-data-science/reference/namespace-matrix.md +112 -0
- bigquery_data_science/_skills/bigquery-data-science/skill.manifest.json +13 -0
- bigquery_data_science/_skills/bigquery-ml/SKILL.md +70 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/airflow_with_kfp.md +379 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/anomaly_fraud_detection.md +195 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/arima_plus.md +635 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/arima_plus_xreg.md +453 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/autoencoder.md +470 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/automl_classifier.md +291 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/automl_regressor.md +274 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/boosted_tree_classifier.md +449 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/boosted_tree_regressor.md +400 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/bucketizing.md +201 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/causal_effect.md +773 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/churn_retention.md +271 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/cloud_workflows.md +370 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/composer_airflow.md +475 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/contribution_analysis.md +346 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/cross_validation.md +185 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/customer_segmentation.md +233 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/dataform.md +372 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/dbt.md +283 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/difference_in_differences.md +280 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/distance.md +195 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/dnn_classifier.md +326 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/dnn_regressor.md +308 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/embeddings_classification.md +426 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/encoding.md +238 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/ensembling.md +278 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/evaluation.md +445 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/exploration.md +779 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/export.md +321 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/feature_engineering.md +280 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/feature_store.md +652 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/feature_store_workflow.md +426 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/ga4_churn_prediction.md +285 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/hierarchical_forecasting.md +441 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/image.md +791 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/imported.md +426 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/kmeans.md +348 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/linear_regression.md +372 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/logistic_regression.md +390 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/matrix_factorization.md +404 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/model_monitoring.md +609 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/pca.md +357 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/price_elasticity_dml.md +286 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/propensity_score_matching.md +350 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/random_forest_classifier.md +445 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/random_forest_regressor.md +409 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/recommendation.md +281 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/regression_based_forecasting.md +491 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/remote.md +428 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/scalers.md +325 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/scheduled_queries.md +284 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/sql_scripting.md +243 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/survival_analysis.md +363 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/synthetic_control.md +221 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/text.md +215 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/time_series.md +669 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/transform_only.md +273 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/uplift_cate.md +241 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/vertex_kfp.md +360 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/wide_and_deep_classifier.md +316 -0
- bigquery_data_science/_skills/bigquery-ml/narrative/wide_and_deep_regressor.md +298 -0
- bigquery_data_science/_skills/bigquery-ml/reference/classification.md +80 -0
- bigquery_data_science/_skills/bigquery-ml/reference/model-management.md +90 -0
- bigquery_data_science/_skills/bigquery-ml/reference/preprocessing-functions.md +234 -0
- bigquery_data_science/_skills/bigquery-ml/reference/regression.md +79 -0
- bigquery_data_science/_skills/bigquery-ml/reference/unsupervised-and-specialized.md +101 -0
- bigquery_data_science/_skills/bigquery-ml/reference/workflows-and-pipelines.md +111 -0
- bigquery_data_science/_skills/bigquery-ml/skill.manifest.json +177 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/1-model_type-catalog.md +28 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/2-task-mlevaluate-metric-columns.md +26 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/3-capability-matrix-per-model-type.md +21 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/4-explainability-weights-functions.md +14 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/5-connection-matrix.md +11 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/6-which-model-free-function-no-create-model-no-connection.md +15 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/7-point-in-time-feature-retrieval-which-of-the-two.md +11 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/INDEX.md +111 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/aicausal_effect.md +85 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/arima_plus-forecasting-lifecycle-functions.md +14 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/arima_plus-univariate-time-series-forecasting.md +132 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/arima_plus_xreg-multivariate-time-series-with-external-regressors.md +103 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/autoencoder.md +102 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/automl_classifier-automl_regressor.md +88 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/boosted_tree_classifier-boosted_tree_regressor.md +117 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/contribution_analysis.md +113 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/dnn_classifier-dnn_regressor.md +107 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/dnn_linear_combined_classifier-dnn_linear_combined_regressor-wide-and-deep.md +98 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/explainability-functions-mlexplain_predict-mlglobal_explain-mlfeature_importance.md +7 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/exploratory-data-analysis-mldescribe_data-mlcorrelation.md +11 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/export-model.md +92 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/feature-engineering-standalone-preprocessing-functions.md +13 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/image-preprocessing-functions-mldecode_image-mlresize_image-mlconvert_image_type-mlconvert_color_space.md +63 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/imported-models-tensorflow-tensorflow_lite-onnx-xgboost.md +36 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/kmeans.md +87 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/linear_reg-logistic_reg-generalized-linear-models.md +101 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/matrix_factorization.md +162 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mladvanced_weights.md +76 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlarima_coefficients.md +30 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlarima_evaluate.md +49 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlbag_of_words.md +47 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlbucketize.md +47 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlcentroids.md +46 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlconfusion_matrix.md +56 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlconvert_color_space.md +53 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlconvert_image_type.md +39 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlcorrelation.md +78 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mldecode_image.md +44 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mldescribe_data.md +74 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mldetect_anomalies.md +86 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mldistance.md +48 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlentity_features_at_time.md +56 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlevaluate.md +72 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlexplain_forecast.md +50 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlexplain_predict.md +66 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlfeature_cross.md +46 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlfeature_importance.md +47 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlfeature_info.md +50 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlfeatures_at_time.md +51 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlforecast.md +76 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlgenerate_embedding-from-a-bqml-pca-autoencoder-matrix_factorization-model.md +64 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlglobal_explain.md +63 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlhash_bucketize.md +47 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlholiday_info.md +46 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlimputer.md +46 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mllp_norm.md +47 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlmetrics.md +80 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlngrams.md +37 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlone_hot_encoder-mlmulti_hot_encoder-mllabel_encoder.md +67 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlpolynomial_expand.md +47 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlpredict.md +67 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlprincipal_component_info.md +42 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlprincipal_components.md +40 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlquantile_bucketize.md +43 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlrecommend.md +60 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlreconstruction_loss.md +48 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlresize_image.md +45 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlroc_curve.md +63 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mltf_idf.md +37 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mltfdv_describe.md +34 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mltfdv_validate.md +48 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mltraining_info.md +78 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mltransform-applying-a-saved-transform.md +52 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mltranspose-not-a-function-pointer.md +32 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mltrial_info.md +60 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlvalidate_data_drift.md +99 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlvalidate_data_skew.md +50 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/mlweights.md +84 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/model-free-time-series-decomposition-mltrend-mlseasonality-mldetect_change_points.md +100 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/model-introspection-mlfeature_info-mltraining_info-mltrial_info.md +7 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/model-monitoring-data-validation.md +23 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/numerical-scalers-mlstandard_scaler-mlmin_max_scaler-mlmax_abs_scaler-mlrobust_scaler-mlnormalizer.md +77 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/onnx.md +55 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/pca.md +91 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/point-in-time-feature-retrieval-mlfeatures_at_time-mlentity_features_at_time.md +25 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/quick-comparison.md +14 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/random_forest_classifier-random_forest_regressor.md +123 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/remote-remote-model-over-a-vertex-ai-endpoint-the-mechanism.md +87 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/tensorflow.md +48 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/tensorflow_lite.md +29 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/text-preprocessing-functions-mlngrams-mltf_idf-mlbag_of_words.md +18 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/timesfm-built-in-foundation-forecaster-see-bigquery-ai.md +28 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/transform_only.md +91 -0
- bigquery_data_science/_skills/bigquery-ml/syntax/xgboost.md +72 -0
- bigquery_data_science/_skills/pinned-models.json +28 -0
- bigquery_data_science/catalog.py +1107 -0
- bigquery_data_science/cli.py +786 -0
- bigquery_data_science/installer.py +282 -0
- bigquery_data_science/mcp_server.py +317 -0
- bigquery_data_science/tooling/__init__.py +15 -0
- bigquery_data_science/tooling/convert_notebook.py +176 -0
- bigquery_data_science/tooling/link_policy.py +247 -0
- bigquery_data_science/tooling/manifest.py +152 -0
- bigquery_data_science/tooling/markdown_anchors.py +84 -0
- bigquery_data_science/tooling/narrative_drift.py +163 -0
- bigquery_data_science/tooling/pinned_models.py +216 -0
- bigquery_data_science/tooling/reference_structure.py +85 -0
- bigquery_data_science/tooling/sync_syntax.py +407 -0
- bigquery_data_science/tooling/validate.py +208 -0
- bigquery_data_science-0.7.0.dist-info/METADATA +306 -0
- bigquery_data_science-0.7.0.dist-info/RECORD +286 -0
- bigquery_data_science-0.7.0.dist-info/WHEEL +4 -0
- bigquery_data_science-0.7.0.dist-info/entry_points.txt +5 -0
- bigquery_data_science-0.7.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
> **Source (`statmike/bigquery-data-science`):** **Notebook:** [`bigquery-ml/functions/scalers/scalers.ipynb`](https://github.com/statmike/bigquery-data-science/blob/main/bigquery-ml/functions/scalers/scalers.ipynb) · **SQL:** [`bigquery-ml/functions/scalers/scalers.sql`](https://github.com/statmike/bigquery-data-science/blob/main/bigquery-ml/functions/scalers/scalers.sql)
|
|
2
|
+
|
|
3
|
+
# Scalers — BigQuery ML Model-Free Functions
|
|
4
|
+
|
|
5
|
+
Five manual feature-preprocessing functions that rescale numerical inputs into ML-ready features: `ML.STANDARD_SCALER`, `ML.MIN_MAX_SCALER`, `ML.MAX_ABS_SCALER`, `ML.ROBUST_SCALER` (all **analytic** — require an empty `OVER()`), and `ML.NORMALIZER` (a row-wise **scalar** function — no `OVER()`, operates on an `ARRAY`). No model is trained by these functions themselves — they transform data directly, standalone or inside a `CREATE MODEL ... TRANSFORM(...)` clause.
|
|
6
|
+
|
|
7
|
+
**When to use these:**
|
|
8
|
+
- Put numerical features on a common scale for distance/gradient-based models (`KMEANS`, `LINEAR_REG`/`LOGISTIC_REG`, `DNN_*`, `PCA`).
|
|
9
|
+
- `ML.MIN_MAX_SCALER` when a bounded `[0, 1]` range is specifically required (e.g. feeding a sigmoid-activated network layer).
|
|
10
|
+
- `ML.ROBUST_SCALER` when a column has outliers (centers on median, scales by IQR — unaffected by extreme values).
|
|
11
|
+
- `ML.MAX_ABS_SCALER` to preserve sign/sparsity (no centering, no shift toward zero).
|
|
12
|
+
- `ML.NORMALIZER` to give each row's feature vector unit norm (e.g. for embedding-like vectors feeding `VECTOR_SEARCH`/`ML.DISTANCE` — see `functions/distance` (`functions/distance/`)).
|
|
13
|
+
|
|
14
|
+
**Data:** [`bigquery-public-data.ml_datasets.penguins`](https://console.cloud.google.com/marketplace/product/bigquery-public-datasets) — the same 3-4 numeric measurements used by `models/kmeans` (K-Means), `models/pca` (PCA), `models/autoencoder` (Autoencoder), and `models/transform_only` (Transform-Only), so results here connect directly to those notebooks.
|
|
15
|
+
|
|
16
|
+
**Featured in:** `models/transform_only` (`models/transform_only/`) (chains `ML.STANDARD_SCALER`/`ML.ROBUST_SCALER` into one reusable pipeline), `models/logistic_regression` (`models/logistic_regression/`) (`ML.STANDARD_SCALER` inline in a `TRANSFORM` clause).
|
|
17
|
+
|
|
18
|
+
**References:** `RESOURCES.md` (Full reference) | [Manual feature preprocessing docs](https://cloud.google.com/bigquery/docs/manual-preprocessing) | `setup` (Setup guide)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
Set your project and location, authenticate, and create a shared dataset. No connection needed — every function here runs entirely in-warehouse.
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
PROJECT_ID = 'statmike-mlops-349915' # <-- Replace with your project ID
|
|
27
|
+
LOCATION = 'US' # BigQuery dataset location
|
|
28
|
+
DATASET_ID = 'bq_ml' # Shared dataset across all bigquery-ml notebooks
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Environment
|
|
32
|
+
|
|
33
|
+
> **Already set up the project environment?** The cell below is a no-op — packages are already in your kernel. See the `setup` (Setup Reference) for details.
|
|
34
|
+
>
|
|
35
|
+
> **Running standalone** (Colab, Colab Enterprise, Vertex AI Workbench)? The cell below installs required packages into your current kernel.
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from google.cloud import bigquery
|
|
39
|
+
import pandas as pd
|
|
40
|
+
|
|
41
|
+
client = bigquery.Client(project=PROJECT_ID)
|
|
42
|
+
pd.set_option('display.max_colwidth', None)
|
|
43
|
+
|
|
44
|
+
# Create the shared dataset (idempotent)
|
|
45
|
+
dataset_ref = bigquery.DatasetReference(PROJECT_ID, DATASET_ID)
|
|
46
|
+
dataset = bigquery.Dataset(dataset_ref)
|
|
47
|
+
dataset.location = LOCATION
|
|
48
|
+
client.create_dataset(dataset, exists_ok=True)
|
|
49
|
+
print(f'Dataset {PROJECT_ID}.{DATASET_ID} ready')
|
|
50
|
+
|
|
51
|
+
# Register %%bigquery cell magic (auto-loaded in Colab, needed elsewhere)
|
|
52
|
+
%load_ext bigquery_magics
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
## Step 1 — `ML.STANDARD_SCALER`: z-score, and a real "matches AVG/STDDEV" gotcha
|
|
57
|
+
|
|
58
|
+
Analytic function, requires `OVER()`. Computes `(x - AVG(x)) / STDDEV(x)` across all rows — but which `STDDEV`?
|
|
59
|
+
|
|
60
|
+
> **GOTCHA (verified live):** `ML.STANDARD_SCALER` uses the **population** standard deviation (`STDDEV_POP`, divides by N), not the **sample** standard deviation BigQuery's plain `STDDEV()`/`STDDEV_SAMP()` computes by default (divides by N-1). The two differ by a small but real amount. If you ever try to "sanity check" `ML.STANDARD_SCALER` by hand-computing `(x - AVG(x)) / STDDEV(x)`, it will **not** match — you need `STDDEV_POP(x)` specifically.
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
query = """
|
|
64
|
+
SELECT
|
|
65
|
+
culmen_length_mm,
|
|
66
|
+
ML.STANDARD_SCALER(culmen_length_mm) OVER() AS standard_scaled,
|
|
67
|
+
(culmen_length_mm - AVG(culmen_length_mm) OVER()) / STDDEV_SAMP(culmen_length_mm) OVER() AS manual_sample_stddev,
|
|
68
|
+
(culmen_length_mm - AVG(culmen_length_mm) OVER()) / STDDEV_POP(culmen_length_mm) OVER() AS manual_population_stddev
|
|
69
|
+
FROM `bigquery-public-data.ml_datasets.penguins`
|
|
70
|
+
WHERE culmen_length_mm IS NOT NULL
|
|
71
|
+
ORDER BY culmen_length_mm
|
|
72
|
+
LIMIT 5
|
|
73
|
+
"""
|
|
74
|
+
client.query(query).to_dataframe()
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
## Step 2 — `ML.MIN_MAX_SCALER`: bounded `[0, 1]`, and a verified prediction-time capping behavior
|
|
79
|
+
|
|
80
|
+
`(x - MIN) / (MAX - MIN)` — the only scaler here with a hard, bounded output range.
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
query = """
|
|
84
|
+
SELECT
|
|
85
|
+
culmen_length_mm,
|
|
86
|
+
ML.MIN_MAX_SCALER(culmen_length_mm) OVER() AS min_max_scaled
|
|
87
|
+
FROM `bigquery-public-data.ml_datasets.penguins`
|
|
88
|
+
WHERE culmen_length_mm IS NOT NULL
|
|
89
|
+
ORDER BY culmen_length_mm
|
|
90
|
+
LIMIT 5
|
|
91
|
+
"""
|
|
92
|
+
client.query(query).to_dataframe()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**GOTCHA (verified live via a real model):** when `ML.MIN_MAX_SCALER` is embedded in a `TRANSFORM` clause, values outside the training min/max are **capped** to 0 or 1 at prediction time — not extrapolated past the bounds. Trained on `culmen_length_mm` in `[32.1, 59.6]`:
|
|
96
|
+
|
|
97
|
+
In production, this means any value beyond the training range collapses to the same `0`/`1` as the actual training min/max — the model can no longer distinguish a mildly out-of-range input from an extreme one (`60.0` and `600.0` would both map to exactly `1.0`).
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
query = """
|
|
101
|
+
CREATE OR REPLACE MODEL `{project}.{dataset}.scratch_minmax_capping_demo`
|
|
102
|
+
TRANSFORM(
|
|
103
|
+
species,
|
|
104
|
+
ML.MIN_MAX_SCALER(culmen_length_mm) OVER() AS culmen_length_scaled
|
|
105
|
+
)
|
|
106
|
+
OPTIONS(model_type='LOGISTIC_REG', input_label_cols=['species']) AS
|
|
107
|
+
SELECT species, culmen_length_mm
|
|
108
|
+
FROM `bigquery-public-data.ml_datasets.penguins`
|
|
109
|
+
WHERE culmen_length_mm IS NOT NULL
|
|
110
|
+
""".format(project=PROJECT_ID, dataset=DATASET_ID)
|
|
111
|
+
client.query(query).result()
|
|
112
|
+
|
|
113
|
+
query = """
|
|
114
|
+
SELECT culmen_length_mm, culmen_length_scaled
|
|
115
|
+
FROM ML.TRANSFORM(
|
|
116
|
+
MODEL `{project}.{dataset}.scratch_minmax_capping_demo`,
|
|
117
|
+
(SELECT * FROM UNNEST([32.1, 59.6, 20.0, 100.0]) AS culmen_length_mm)
|
|
118
|
+
)
|
|
119
|
+
""".format(project=PROJECT_ID, dataset=DATASET_ID)
|
|
120
|
+
df = client.query(query).to_dataframe()
|
|
121
|
+
|
|
122
|
+
client.query(f"DROP MODEL IF EXISTS `{PROJECT_ID}.{DATASET_ID}.scratch_minmax_capping_demo`").result()
|
|
123
|
+
df
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
## Step 3 — `ML.MAX_ABS_SCALER`: preserves sign, no centering
|
|
128
|
+
|
|
129
|
+
Divides by the max absolute value only — unlike the other scalers, it never shifts the data toward zero, so sign and relative sparsity survive intact. Best for data where the sign itself is meaningful. Switching to a small literal array here (rather than a `penguins` column) on purpose — every physical measurement in this dataset is positive, so sign preservation wouldn't be visible on real data; a column with genuine negative values is needed to see the effect.
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
query = """
|
|
133
|
+
SELECT x, ML.MAX_ABS_SCALER(x) OVER() AS max_abs_scaled
|
|
134
|
+
FROM UNNEST([-10.0, -5.0, 0.0, 5.0, 8.0, 10.0]) AS x
|
|
135
|
+
ORDER BY x
|
|
136
|
+
"""
|
|
137
|
+
client.query(query).to_dataframe()
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
## Step 4 — `ML.ROBUST_SCALER`: outlier-robust, with all 3 optional parameters
|
|
142
|
+
|
|
143
|
+
`(x - median) / (q_hi - q_lo)` by default — centers on the median and scales by the interquartile range instead of mean/stddev, so extreme outliers don't distort the result. All three parameters are optional: `quantile_range` (default `[25, 75]`), `with_median` (default `TRUE`), `with_quantile_range` (default `TRUE`).
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
query = """
|
|
147
|
+
SELECT
|
|
148
|
+
culmen_length_mm,
|
|
149
|
+
ML.ROBUST_SCALER(culmen_length_mm) OVER() AS robust_default,
|
|
150
|
+
ML.ROBUST_SCALER(culmen_length_mm, [10, 90]) OVER() AS robust_custom_quantile_range,
|
|
151
|
+
ML.ROBUST_SCALER(culmen_length_mm, [25, 75], FALSE) OVER() AS robust_no_median,
|
|
152
|
+
ML.ROBUST_SCALER(culmen_length_mm, [25, 75], TRUE, FALSE) OVER() AS robust_no_scaling
|
|
153
|
+
FROM `bigquery-public-data.ml_datasets.penguins`
|
|
154
|
+
WHERE culmen_length_mm IS NOT NULL
|
|
155
|
+
ORDER BY culmen_length_mm
|
|
156
|
+
LIMIT 5
|
|
157
|
+
"""
|
|
158
|
+
client.query(query).to_dataframe()
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Outlier robustness, proven side by side:** inject one extreme outlier (`500`) into an otherwise tightly-clustered column (`10`-`14`). `ML.STANDARD_SCALER`'s mean/stddev get dragged toward the outlier, compressing every normal point into an indistinguishable narrow band. `ML.ROBUST_SCALER`'s median/IQR ignore the outlier entirely — normal points stay well-spread.
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
query = """
|
|
165
|
+
WITH data AS (
|
|
166
|
+
SELECT x FROM UNNEST([10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 500.0]) AS x
|
|
167
|
+
)
|
|
168
|
+
SELECT
|
|
169
|
+
x,
|
|
170
|
+
ROUND(ML.STANDARD_SCALER(x) OVER(), 3) AS standard_scaled,
|
|
171
|
+
ROUND(ML.ROBUST_SCALER(x) OVER(), 3) AS robust_scaled
|
|
172
|
+
FROM data
|
|
173
|
+
ORDER BY x
|
|
174
|
+
"""
|
|
175
|
+
client.query(query).to_dataframe()
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
## Step 5 — `ML.NORMALIZER`: row-wise unit-norm scaling of an `ARRAY` (no `OVER()`)
|
|
180
|
+
|
|
181
|
+
The odd one out: a **scalar** function, not analytic — it doesn't look at other rows at all, so it takes no `OVER()`. Normalizes each row's `ARRAY` to unit p-norm independently. Default `p=2` (Euclidean); also accepts `p=1` (Manhattan), `p=0`, or `p=+inf` (via `CAST('+inf' AS FLOAT64)`).
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
query = """
|
|
185
|
+
SELECT arr,
|
|
186
|
+
ML.NORMALIZER(arr) AS p2_default,
|
|
187
|
+
ML.NORMALIZER(arr, 1) AS p1_manhattan,
|
|
188
|
+
ML.NORMALIZER(arr, 0) AS p0,
|
|
189
|
+
ML.NORMALIZER(arr, CAST('+inf' AS FLOAT64)) AS p_inf
|
|
190
|
+
FROM (SELECT [3.0, 4.0] AS arr)
|
|
191
|
+
"""
|
|
192
|
+
client.query(query).to_dataframe()
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Applied to a real per-penguin feature vector — each **row** gets unit norm, not each column. This is semantically different from the column scalers above: `ML.NORMALIZER` normalizes *across* the elements of one row's array.
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
query = """
|
|
199
|
+
SELECT
|
|
200
|
+
species,
|
|
201
|
+
[culmen_length_mm, culmen_depth_mm, flipper_length_mm] AS measurements,
|
|
202
|
+
ML.NORMALIZER([culmen_length_mm, culmen_depth_mm, flipper_length_mm]) AS normalized
|
|
203
|
+
FROM `bigquery-public-data.ml_datasets.penguins`
|
|
204
|
+
WHERE culmen_length_mm IS NOT NULL AND culmen_depth_mm IS NOT NULL AND flipper_length_mm IS NOT NULL
|
|
205
|
+
LIMIT 3
|
|
206
|
+
"""
|
|
207
|
+
client.query(query).to_dataframe()
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
## Step 6 — NULLs pass through untouched — scalers don't impute
|
|
212
|
+
|
|
213
|
+
`body_mass_g` has 2 `NULL` rows in this dataset. Scalers don't handle missing values — a `NULL` input produces a `NULL` output (not an error, not `0`). Downloaded into a pandas DataFrame, that `NULL` renders as `NaN` — normal numeric-dtype behavior, not a BQML bug. Pair scalers with `ML.IMPUTER` first if `NULL`s need a real value (see `functions/feature_engineering` (`functions/feature_engineering/`)).
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
query = """
|
|
217
|
+
SELECT body_mass_g, ML.STANDARD_SCALER(body_mass_g) OVER() AS scaled
|
|
218
|
+
FROM `bigquery-public-data.ml_datasets.penguins`
|
|
219
|
+
ORDER BY body_mass_g IS NULL DESC
|
|
220
|
+
LIMIT 3
|
|
221
|
+
"""
|
|
222
|
+
client.query(query).to_dataframe()
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
## Step 7 — All four analytic scalers side by side, one column
|
|
227
|
+
|
|
228
|
+
The same `culmen_length_mm` values through all four analytic scalers at once — a direct visual comparison of output range and shape.
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
query = """
|
|
232
|
+
SELECT
|
|
233
|
+
culmen_length_mm,
|
|
234
|
+
ROUND(ML.STANDARD_SCALER(culmen_length_mm) OVER(), 3) AS standard,
|
|
235
|
+
ROUND(ML.MIN_MAX_SCALER(culmen_length_mm) OVER(), 3) AS min_max,
|
|
236
|
+
ROUND(ML.MAX_ABS_SCALER(culmen_length_mm) OVER(), 3) AS max_abs,
|
|
237
|
+
ROUND(ML.ROBUST_SCALER(culmen_length_mm) OVER(), 3) AS robust
|
|
238
|
+
FROM `bigquery-public-data.ml_datasets.penguins`
|
|
239
|
+
WHERE culmen_length_mm IS NOT NULL
|
|
240
|
+
ORDER BY culmen_length_mm
|
|
241
|
+
LIMIT 5
|
|
242
|
+
"""
|
|
243
|
+
client.query(query).to_dataframe()
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
## Step 8 — Embedded in a real `CREATE MODEL TRANSFORM` — auto-applies at `ML.PREDICT`
|
|
248
|
+
|
|
249
|
+
Contrast with `models/transform_only` (`models/transform_only/`): that notebook builds a **standalone** `TRANSFORM_ONLY` pipeline, which must be explicitly re-applied via `ML.TRANSFORM` before every downstream `ML.PREDICT` (and silently mispredicts if you forget — see its Step 7). **This** model embeds the `TRANSFORM` directly on the estimator itself, so `ML.PREDICT` on raw, unscaled input automatically applies the exact same scaling used at training time — no separate step, no risk of that gotcha.
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
query = """
|
|
253
|
+
CREATE OR REPLACE MODEL `{project}.{dataset}.scalers_downstream_logistic_regression`
|
|
254
|
+
TRANSFORM(
|
|
255
|
+
species,
|
|
256
|
+
ML.STANDARD_SCALER(culmen_length_mm) OVER() AS culmen_length_scaled,
|
|
257
|
+
ML.STANDARD_SCALER(culmen_depth_mm) OVER() AS culmen_depth_scaled,
|
|
258
|
+
ML.ROBUST_SCALER(flipper_length_mm) OVER() AS flipper_length_scaled
|
|
259
|
+
)
|
|
260
|
+
OPTIONS(model_type = 'LOGISTIC_REG', input_label_cols = ['species']) AS
|
|
261
|
+
SELECT species, culmen_length_mm, culmen_depth_mm, flipper_length_mm
|
|
262
|
+
FROM `bigquery-public-data.ml_datasets.penguins`
|
|
263
|
+
WHERE culmen_length_mm IS NOT NULL AND culmen_depth_mm IS NOT NULL AND flipper_length_mm IS NOT NULL
|
|
264
|
+
""".format(project=PROJECT_ID, dataset=DATASET_ID)
|
|
265
|
+
client.query(query).result()
|
|
266
|
+
print('Model scalers_downstream_logistic_regression created')
|
|
267
|
+
|
|
268
|
+
query = f"SELECT * FROM ML.EVALUATE(MODEL `{PROJECT_ID}.{DATASET_ID}.scalers_downstream_logistic_regression`)"
|
|
269
|
+
client.query(query).to_dataframe()
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
`ML.PREDICT` on **raw, unscaled** `culmen_length_mm`/`culmen_depth_mm`/`flipper_length_mm` values — no `ML.TRANSFORM` call needed first, since the scaling is baked into the model:
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
query = f"""
|
|
276
|
+
SELECT species, predicted_species
|
|
277
|
+
FROM ML.PREDICT(
|
|
278
|
+
MODEL `{PROJECT_ID}.{DATASET_ID}.scalers_downstream_logistic_regression`,
|
|
279
|
+
(SELECT species, culmen_length_mm, culmen_depth_mm, flipper_length_mm
|
|
280
|
+
FROM `bigquery-public-data.ml_datasets.penguins`
|
|
281
|
+
WHERE culmen_length_mm IS NOT NULL AND culmen_depth_mm IS NOT NULL AND flipper_length_mm IS NOT NULL
|
|
282
|
+
LIMIT 5)
|
|
283
|
+
)
|
|
284
|
+
"""
|
|
285
|
+
client.query(query).to_dataframe()
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
## Examples — `%%bigquery` Magics
|
|
290
|
+
|
|
291
|
+
The same operations using IPython magic commands — write SQL directly in cells without Python string wrapping.
|
|
292
|
+
|
|
293
|
+
```sql
|
|
294
|
+
%%bigquery --project {PROJECT_ID}
|
|
295
|
+
|
|
296
|
+
SELECT
|
|
297
|
+
culmen_length_mm,
|
|
298
|
+
ML.STANDARD_SCALER(culmen_length_mm) OVER() AS standard_scaled,
|
|
299
|
+
ML.ROBUST_SCALER(culmen_length_mm) OVER() AS robust_scaled
|
|
300
|
+
FROM `bigquery-public-data.ml_datasets.penguins`
|
|
301
|
+
WHERE culmen_length_mm IS NOT NULL
|
|
302
|
+
ORDER BY culmen_length_mm
|
|
303
|
+
LIMIT 5
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
## Examples — BigFrames
|
|
308
|
+
|
|
309
|
+
`bigframes.ml.preprocessing` has real classes for **three** of the five: `StandardScaler`, `MinMaxScaler`, `MaxAbsScaler` (verified via `inspect.signature` — all no-arg constructors, `.fit()`/`.transform()` pattern). There is **no** `RobustScaler` or `Normalizer` class in BigFrames — use SQL `TRANSFORM` for full parity on those two.
|
|
310
|
+
|
|
311
|
+
```python
|
|
312
|
+
import bigframes.pandas as bpd
|
|
313
|
+
from bigframes.ml.preprocessing import StandardScaler
|
|
314
|
+
|
|
315
|
+
bpd.close_session() # Reset session to apply project/location settings
|
|
316
|
+
bpd.options.bigquery.project = PROJECT_ID
|
|
317
|
+
bpd.options.bigquery.location = LOCATION
|
|
318
|
+
|
|
319
|
+
df = bpd.read_gbq(
|
|
320
|
+
"SELECT culmen_length_mm FROM `bigquery-public-data.ml_datasets.penguins` WHERE culmen_length_mm IS NOT NULL"
|
|
321
|
+
)
|
|
322
|
+
scaler = StandardScaler()
|
|
323
|
+
scaler.fit(df[['culmen_length_mm']])
|
|
324
|
+
scaler.transform(df[['culmen_length_mm']]).peek()
|
|
325
|
+
```
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
> **Source (`statmike/bigquery-data-science`):** **Notebook:** [`bigquery-ml/pipelines/scheduled_queries/scheduled_queries.ipynb`](https://github.com/statmike/bigquery-data-science/blob/main/bigquery-ml/pipelines/scheduled_queries/scheduled_queries.ipynb) · **SQL:** [`bigquery-ml/pipelines/scheduled_queries/scheduled_queries.sql`](https://github.com/statmike/bigquery-data-science/blob/main/bigquery-ml/pipelines/scheduled_queries/scheduled_queries.sql)
|
|
2
|
+
|
|
3
|
+
# Scheduled Queries — BigQuery ML Pipeline
|
|
4
|
+
|
|
5
|
+
Takes `pipelines/sql_scripting` (`pipelines/sql_scripting/`)'s exact drift-check → conditional-retrain → `SELECT ERROR()` script — **unchanged** — and schedules it via the BigQuery Data Transfer API, the same mechanism behind BigQuery Studio's "Scheduled queries" UI. No new BQML logic here: this notebook's real content is the scheduling/triggering/alerting layer wrapped around a script that doesn't know or care how it gets invoked.
|
|
6
|
+
|
|
7
|
+
Modernizes [MLOps/Model Monitoring/bqml-model-monitoring-tutorial.ipynb](https://github.com/statmike/vertex-ai-mlops/blob/main/MLOps/Model%20Monitoring/bqml-model-monitoring-tutorial.ipynb)'s "From Job To Scheduled Query" section.
|
|
8
|
+
|
|
9
|
+
**Workflow operationalized:** `workflows/ga4_churn_prediction` (`workflows/ga4_churn_prediction/`)
|
|
10
|
+
**Builds on:** `pipelines/sql_scripting` (`pipelines/sql_scripting/`) (the script being scheduled) · **API:** `google.cloud.bigquery_datatransfer` (`TransferConfig`, `ScheduleOptions`, `EmailPreferences`, `StartManualTransferRunsRequest`)
|
|
11
|
+
|
|
12
|
+
**Data:** [`bigquery-public-data.ga4_obfuscated_sample_ecommerce`](https://console.cloud.google.com/marketplace/product/bigquery-public-datasets)
|
|
13
|
+
|
|
14
|
+
**References:** `RESOURCES.md` (Full reference) | [Scheduling queries docs](https://cloud.google.com/bigquery/docs/scheduling-queries) | `setup` (Setup guide)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
## Setup
|
|
18
|
+
|
|
19
|
+
Set your project and location, authenticate, and create a shared dataset. No connection needed.
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
PROJECT_ID = 'statmike-mlops-349915' # <-- Replace with your project ID
|
|
23
|
+
LOCATION = 'US' # BigQuery dataset location
|
|
24
|
+
DATASET_ID = 'bq_ml' # Shared dataset across all bigquery-ml notebooks
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Environment
|
|
28
|
+
|
|
29
|
+
> **Already set up the project environment?** The cell below is a no-op — packages are already in your kernel. See the `setup` (Setup Reference) for details.
|
|
30
|
+
>
|
|
31
|
+
> **Running standalone** (Colab, Colab Enterprise, Vertex AI Workbench)? The cell below installs required packages into your current kernel.
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from google.cloud import bigquery
|
|
35
|
+
import pandas as pd
|
|
36
|
+
|
|
37
|
+
client = bigquery.Client(project=PROJECT_ID)
|
|
38
|
+
pd.set_option('display.max_colwidth', None)
|
|
39
|
+
|
|
40
|
+
# Create the shared dataset (idempotent)
|
|
41
|
+
dataset_ref = bigquery.DatasetReference(PROJECT_ID, DATASET_ID)
|
|
42
|
+
dataset = bigquery.Dataset(dataset_ref)
|
|
43
|
+
dataset.location = LOCATION
|
|
44
|
+
client.create_dataset(dataset, exists_ok=True)
|
|
45
|
+
print(f'Dataset {PROJECT_ID}.{DATASET_ID} ready')
|
|
46
|
+
|
|
47
|
+
# Register %%bigquery cell magic (auto-loaded in Colab, needed elsewhere)
|
|
48
|
+
%load_ext bigquery_magics
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
## Step 1 — Self-contained feature table + an initial "production" model
|
|
53
|
+
|
|
54
|
+
Identical setup to `pipelines/sql_scripting` (`pipelines/sql_scripting/`): its own copies of the GA4 churn feature table and initial model, since each pipeline notebook is self-contained (the workflow notebook's own cleanup drops its artifacts).
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
query = """
|
|
58
|
+
CREATE OR REPLACE TABLE `{project}.{dataset}.ga4_churn_pipeline_features` AS
|
|
59
|
+
WITH events AS (
|
|
60
|
+
SELECT
|
|
61
|
+
user_pseudo_id,
|
|
62
|
+
PARSE_DATE('%Y%m%d', event_date) AS event_date,
|
|
63
|
+
event_name,
|
|
64
|
+
device.category AS device_category,
|
|
65
|
+
geo.country AS country,
|
|
66
|
+
traffic_source.medium AS traffic_medium,
|
|
67
|
+
(SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'engagement_time_msec') AS engagement_time_msec
|
|
68
|
+
FROM `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
|
|
69
|
+
),
|
|
70
|
+
first_visit AS (
|
|
71
|
+
SELECT user_pseudo_id, MIN(event_date) AS first_date
|
|
72
|
+
FROM events
|
|
73
|
+
GROUP BY user_pseudo_id
|
|
74
|
+
HAVING first_date BETWEEN '2020-11-01' AND '2020-12-24'
|
|
75
|
+
),
|
|
76
|
+
feature_window AS (
|
|
77
|
+
SELECT e.*, f.first_date
|
|
78
|
+
FROM events e
|
|
79
|
+
JOIN first_visit f USING (user_pseudo_id)
|
|
80
|
+
WHERE e.event_date BETWEEN f.first_date AND DATE_ADD(f.first_date, INTERVAL 6 DAY)
|
|
81
|
+
),
|
|
82
|
+
label_window AS (
|
|
83
|
+
SELECT DISTINCT e.user_pseudo_id
|
|
84
|
+
FROM events e
|
|
85
|
+
JOIN first_visit f USING (user_pseudo_id)
|
|
86
|
+
WHERE e.event_date BETWEEN DATE_ADD(f.first_date, INTERVAL 7 DAY) AND DATE_ADD(f.first_date, INTERVAL 36 DAY)
|
|
87
|
+
)
|
|
88
|
+
SELECT
|
|
89
|
+
fw.user_pseudo_id,
|
|
90
|
+
ANY_VALUE(fw.first_date) AS first_date,
|
|
91
|
+
ANY_VALUE(fw.device_category) AS device_category,
|
|
92
|
+
ANY_VALUE(fw.country) AS country,
|
|
93
|
+
ANY_VALUE(fw.traffic_medium) AS traffic_medium,
|
|
94
|
+
COUNT(*) AS n_events,
|
|
95
|
+
COUNT(DISTINCT fw.event_date) AS n_active_days,
|
|
96
|
+
COUNTIF(fw.event_name = 'page_view') AS n_page_view,
|
|
97
|
+
COUNTIF(fw.event_name = 'view_item') AS n_view_item,
|
|
98
|
+
COUNTIF(fw.event_name = 'add_to_cart') AS n_add_to_cart,
|
|
99
|
+
COUNTIF(fw.event_name = 'begin_checkout') AS n_begin_checkout,
|
|
100
|
+
COUNTIF(fw.event_name = 'session_start') AS n_sessions,
|
|
101
|
+
COUNTIF(fw.event_name = 'purchase') > 0 AS did_purchase,
|
|
102
|
+
IFNULL(SUM(fw.engagement_time_msec), 0) AS total_engagement_time_msec,
|
|
103
|
+
lw.user_pseudo_id IS NULL AS churned
|
|
104
|
+
FROM feature_window fw
|
|
105
|
+
LEFT JOIN label_window lw USING (user_pseudo_id)
|
|
106
|
+
GROUP BY fw.user_pseudo_id, lw.user_pseudo_id
|
|
107
|
+
""".format(project=PROJECT_ID, dataset=DATASET_ID)
|
|
108
|
+
client.query(query).result()
|
|
109
|
+
print('Feature table ready')
|
|
110
|
+
|
|
111
|
+
query = """
|
|
112
|
+
CREATE OR REPLACE MODEL `{project}.{dataset}.ga4_churn_pipeline_model`
|
|
113
|
+
OPTIONS(
|
|
114
|
+
model_type = 'BOOSTED_TREE_CLASSIFIER',
|
|
115
|
+
input_label_cols = ['churned'],
|
|
116
|
+
auto_class_weights = TRUE,
|
|
117
|
+
data_split_method = 'AUTO_SPLIT',
|
|
118
|
+
enable_global_explain = TRUE
|
|
119
|
+
) AS
|
|
120
|
+
SELECT n_events, n_active_days, n_page_view, n_view_item, n_add_to_cart,
|
|
121
|
+
n_begin_checkout, n_sessions, did_purchase, device_category, country,
|
|
122
|
+
traffic_medium, total_engagement_time_msec, churned
|
|
123
|
+
FROM `{project}.{dataset}.ga4_churn_pipeline_features`
|
|
124
|
+
WHERE first_date <= '2020-11-20'
|
|
125
|
+
""".format(project=PROJECT_ID, dataset=DATASET_ID)
|
|
126
|
+
client.query(query).result()
|
|
127
|
+
print('Model ga4_churn_pipeline_model created (trained on TRAIN_INITIAL only)')
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
## Step 2 — The script being scheduled
|
|
132
|
+
|
|
133
|
+
The exact `pipeline_script` from `pipelines/sql_scripting/` — not modified in any way. A scheduled query is just this same text handed to a different execution mechanism.
|
|
134
|
+
|
|
135
|
+
**Design note:** the legacy `bqml-model-monitoring-tutorial.ipynb` this pipeline modernizes writes its script around the `@run_date` pseudo-parameter, so a recurring schedule can compute rolling date windows (e.g. "last week vs. the week before") against a live, continuously-growing serving table. This script instead uses fixed literal dates (`cutoff_date = DATE '2020-11-20'`) against a frozen historical GA4 export — every scheduled run would check the identical fixed window. That's an honest, disclosed difference driven by the dataset, not a gap in the scheduling mechanism itself: the same `@run_date` pattern would apply directly to a live production table.
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
pipeline_script = r"""
|
|
139
|
+
DECLARE cutoff_date DATE DEFAULT DATE '2020-11-20';
|
|
140
|
+
DECLARE drift_anomalies ARRAY<STRUCT<input STRING, metric STRING, value FLOAT64>>;
|
|
141
|
+
DECLARE drift_report STRING;
|
|
142
|
+
|
|
143
|
+
SET drift_anomalies = (
|
|
144
|
+
SELECT ARRAY_AGG(STRUCT(input, metric, ROUND(value, 4) AS value))
|
|
145
|
+
FROM ML.VALIDATE_DATA_DRIFT(
|
|
146
|
+
(SELECT n_events, n_active_days, n_page_view, n_view_item, n_add_to_cart, n_begin_checkout, n_sessions, did_purchase, device_category, country, traffic_medium, total_engagement_time_msec
|
|
147
|
+
FROM `{project}.{dataset}.ga4_churn_pipeline_features`
|
|
148
|
+
WHERE first_date <= cutoff_date),
|
|
149
|
+
(SELECT n_events, n_active_days, n_page_view, n_view_item, n_add_to_cart, n_begin_checkout, n_sessions, did_purchase, device_category, country, traffic_medium, total_engagement_time_msec
|
|
150
|
+
FROM `{project}.{dataset}.ga4_churn_pipeline_features`
|
|
151
|
+
WHERE first_date > cutoff_date),
|
|
152
|
+
STRUCT(0.1 AS numerical_default_threshold, 0.1 AS categorical_default_threshold)
|
|
153
|
+
)
|
|
154
|
+
WHERE is_anomaly = TRUE
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
IF ARRAY_LENGTH(drift_anomalies) > 0 THEN
|
|
158
|
+
SET drift_report = (
|
|
159
|
+
SELECT STRING_AGG(CONCAT('\n\t', da.input, ' (', da.metric, '): ', CAST(da.value AS STRING)) ORDER BY da.value DESC)
|
|
160
|
+
FROM UNNEST(drift_anomalies) AS da
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
BEGIN
|
|
164
|
+
DECLARE prior_roc_auc FLOAT64;
|
|
165
|
+
DECLARE retrained_roc_auc FLOAT64;
|
|
166
|
+
|
|
167
|
+
SET prior_roc_auc = (SELECT roc_auc FROM ML.EVALUATE(MODEL `{project}.{dataset}.ga4_churn_pipeline_model`));
|
|
168
|
+
|
|
169
|
+
CREATE OR REPLACE MODEL `{project}.{dataset}.ga4_churn_pipeline_model`
|
|
170
|
+
OPTIONS(
|
|
171
|
+
model_type = 'BOOSTED_TREE_CLASSIFIER',
|
|
172
|
+
input_label_cols = ['churned'],
|
|
173
|
+
auto_class_weights = TRUE,
|
|
174
|
+
data_split_method = 'AUTO_SPLIT',
|
|
175
|
+
enable_global_explain = TRUE
|
|
176
|
+
) AS
|
|
177
|
+
SELECT n_events, n_active_days, n_page_view, n_view_item, n_add_to_cart, n_begin_checkout, n_sessions, did_purchase, device_category, country, traffic_medium, total_engagement_time_msec, churned
|
|
178
|
+
FROM `{project}.{dataset}.ga4_churn_pipeline_features`;
|
|
179
|
+
|
|
180
|
+
SET retrained_roc_auc = (SELECT roc_auc FROM ML.EVALUATE(MODEL `{project}.{dataset}.ga4_churn_pipeline_model`));
|
|
181
|
+
|
|
182
|
+
SELECT ERROR(
|
|
183
|
+
CONCAT(
|
|
184
|
+
"\n\nGA4 Churn Pipeline Monitoring Report (cutoff ", CAST(cutoff_date AS STRING), "):",
|
|
185
|
+
"\n\tDrift detected in:", drift_report,
|
|
186
|
+
"\n\nModel retrained on full cohort.",
|
|
187
|
+
"\n\troc_auc before retrain (early-cohort-only model): ", CAST(prior_roc_auc AS STRING),
|
|
188
|
+
"\n\troc_auc after retrain (full cohort): ", CAST(retrained_roc_auc AS STRING),
|
|
189
|
+
"\n"
|
|
190
|
+
)
|
|
191
|
+
);
|
|
192
|
+
END;
|
|
193
|
+
ELSE
|
|
194
|
+
SELECT 'No drift detected -- no retrain triggered.' AS status;
|
|
195
|
+
END IF;
|
|
196
|
+
""".format(project=PROJECT_ID, dataset=DATASET_ID)
|
|
197
|
+
print('Pipeline script ready (same text as pipelines/sql_scripting/)')
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
## Step 3 — Create the scheduled query
|
|
202
|
+
|
|
203
|
+
`google.cloud.bigquery_datatransfer.DataTransferServiceClient` is the Python client for the same BigQuery Data Transfer Service that powers BigQuery Studio's "Scheduled queries" UI. `data_source_id='scheduled_query'` tells the Data Transfer Service that `params['query']` is arbitrary SQL to run on a schedule — the identical mechanism as any other transfer, just pointed at BigQuery itself instead of an external source.
|
|
204
|
+
|
|
205
|
+
**Verified live gotcha**: creating a transfer config directly through this API (rather than the Console's interactive flow) requires an explicit runtime identity — omitting `service_account_name` fails with `Failed to find a valid credential. The field 'version_info' or 'service_account_name' must be specified.` The Console handles this transparently via an OAuth consent step; the API needs a service account named explicitly.
|
|
206
|
+
|
|
207
|
+
**Verified live gotcha #2**: the schedule's own first automatic run and a manually-triggered demo run can race each other if both land close in time — both would try to `CREATE OR REPLACE` the same model concurrently, and BigQuery genuinely rejects that (`Model can not be updated by multiple create model query jobs at the same time`). Pushing `schedule_options.start_time` a couple of days out keeps this notebook's manual demo run isolated; a real production schedule wouldn't need this, since you wouldn't normally trigger a manual run at the exact moment the recurring schedule is also about to fire.
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from google.cloud import bigquery_datatransfer
|
|
211
|
+
from datetime import datetime, timezone, timedelta
|
|
212
|
+
import time
|
|
213
|
+
|
|
214
|
+
transfer_client = bigquery_datatransfer.DataTransferServiceClient()
|
|
215
|
+
parent = transfer_client.common_location_path(PROJECT_ID, 'us')
|
|
216
|
+
|
|
217
|
+
# Run the schedule as the project's default Compute Engine service account
|
|
218
|
+
import subprocess
|
|
219
|
+
project_number = subprocess.check_output(
|
|
220
|
+
['gcloud', 'projects', 'describe', PROJECT_ID, '--format=value(projectNumber)']
|
|
221
|
+
).decode().strip()
|
|
222
|
+
service_account_name = f'{project_number}-compute@developer.gserviceaccount.com'
|
|
223
|
+
print('Using service account:', service_account_name)
|
|
224
|
+
|
|
225
|
+
request = bigquery_datatransfer.CreateTransferConfigRequest(
|
|
226
|
+
parent=parent,
|
|
227
|
+
transfer_config=bigquery_datatransfer.TransferConfig(
|
|
228
|
+
display_name='GA4 Churn Pipeline Monitoring (bq-ml demo)',
|
|
229
|
+
data_source_id='scheduled_query',
|
|
230
|
+
params={'query': pipeline_script},
|
|
231
|
+
schedule='every 24 hours',
|
|
232
|
+
schedule_options=bigquery_datatransfer.ScheduleOptions(
|
|
233
|
+
start_time=datetime.now(timezone.utc) + timedelta(days=2)
|
|
234
|
+
),
|
|
235
|
+
email_preferences=bigquery_datatransfer.EmailPreferences(
|
|
236
|
+
enable_failure_email=True
|
|
237
|
+
),
|
|
238
|
+
),
|
|
239
|
+
service_account_name=service_account_name,
|
|
240
|
+
)
|
|
241
|
+
scheduled_query = transfer_client.create_transfer_config(request=request)
|
|
242
|
+
print('Created:', scheduled_query.name)
|
|
243
|
+
print('Next automatic run:', scheduled_query.next_run_time)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
## Step 4 — Trigger a manual run now (a real backfill, not waiting 24 hours)
|
|
248
|
+
|
|
249
|
+
`start_manual_transfer_runs` is exactly what a "Schedule backfill" click in the Console does — request that the transfer run immediately (or for a specific past date) rather than waiting for its next scheduled time.
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
backfill_job = transfer_client.start_manual_transfer_runs(
|
|
253
|
+
request=bigquery_datatransfer.StartManualTransferRunsRequest(
|
|
254
|
+
parent=scheduled_query.name,
|
|
255
|
+
requested_run_time=datetime.now(timezone.utc),
|
|
256
|
+
)
|
|
257
|
+
)
|
|
258
|
+
run_name = backfill_job.runs[0].name
|
|
259
|
+
print('Run:', run_name)
|
|
260
|
+
|
|
261
|
+
while True:
|
|
262
|
+
run = transfer_client.get_transfer_run(name=run_name)
|
|
263
|
+
state = run.state.name
|
|
264
|
+
if state in ['FAILED', 'SUCCEEDED', 'CANCELLED']:
|
|
265
|
+
break
|
|
266
|
+
time.sleep(15)
|
|
267
|
+
|
|
268
|
+
print('Final state:', state)
|
|
269
|
+
print()
|
|
270
|
+
print('Error status (the alert payload email_preferences would forward):')
|
|
271
|
+
print(run.error_status.message if run.error_status else '(none)')
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**`FAILED` is the correct, expected terminal state here** — not a real failure. This scheduled run used the exact same `SELECT ERROR()` idiom as `pipelines/sql_scripting/` to pass its report through as the job's (and therefore the transfer run's) error message. `email_preferences.enable_failure_email=True` means this exact message is what would land in an inbox as a real failure-alert email. A state of `SUCCEEDED` would mean the script's `ELSE` branch fired instead — no drift, no report, nothing to alert on. Same real, positive retrain outcome as `pipelines/sql_scripting/`: `roc_auc` improves from **0.737 to 0.766** by folding the newer, holiday-inclusive cohort back into training.
|
|
275
|
+
|
|
276
|
+
> `BOOSTED_TREE_CLASSIFIER` training carries a small amount of run-to-run variation — a rerun may show slightly different exact figures, but the direction (drift detected, retrain improves `roc_auc`) is the durable finding.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
## Related content
|
|
280
|
+
|
|
281
|
+
- `pipelines/sql_scripting` (`pipelines/sql_scripting/`) — the script this pipeline schedules, and where its drift-check/retrain design is explained in full.
|
|
282
|
+
- `functions/model_monitoring` (`functions/model_monitoring/`) — `ML.VALIDATE_DATA_DRIFT`'s full mechanics.
|
|
283
|
+
- [MLOps/Model Monitoring/bqml-model-monitoring-tutorial.ipynb](https://github.com/statmike/vertex-ai-mlops/blob/main/MLOps/Model%20Monitoring/bqml-model-monitoring-tutorial.ipynb) — the legacy tutorial this pipeline modernizes, including the `@run_date`-based rolling-window pattern for live serving tables.
|
|
284
|
+
- `workflows/ga4_churn_prediction` (`workflows/ga4_churn_prediction/`) — the workflow this pipeline operationalizes.
|