diff --git a/deployment/.dockerignore b/deployment/.dockerignore new file mode 100644 index 0000000..e01cbd5 --- /dev/null +++ b/deployment/.dockerignore @@ -0,0 +1,4 @@ +modules/ml-pipeline/src/pipeline/data/predictions* +modules/ml-pipeline/src/pipeline/data/prepared_data* +modules/ml-pipeline/src/pipeline/data/model/allmodels* +modules/ml-pipeline/src/pipeline/metrics* diff --git a/deployment/Dockerfile.prediction.lambda b/deployment/Dockerfile.prediction.lambda index a2520ba..f8000bf 100644 --- a/deployment/Dockerfile.prediction.lambda +++ b/deployment/Dockerfile.prediction.lambda @@ -9,7 +9,7 @@ ARG RUNTIME_ENVIRONMENT ENV RUNTIME_ENVIRONMENT=${RUNTIME_ENVIRONMENT} # Install necessary build tools - required to test locally -RUN yum install -y gcc python3-devel +RUN yum install -y gcc python3-devel gcc-c++ # Install python packages COPY modules/ml-pipeline/src/pipeline/requirements/predictions/requirements.txt ./requirements.txt diff --git a/modules/ml-pipeline/.dvc/.gitignore b/modules/ml-pipeline/.dvc/.gitignore deleted file mode 100644 index 528f30c..0000000 --- a/modules/ml-pipeline/.dvc/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/config.local -/tmp -/cache diff --git a/modules/ml-pipeline/.dvc/config b/modules/ml-pipeline/.dvc/config deleted file mode 100644 index 03ccfbc..0000000 --- a/modules/ml-pipeline/.dvc/config +++ /dev/null @@ -1,2 +0,0 @@ -['remote "myremote"'] - url = /tmp/dvcstore diff --git a/modules/ml-pipeline/.dvcignore b/modules/ml-pipeline/.dvcignore deleted file mode 100644 index 5197305..0000000 --- a/modules/ml-pipeline/.dvcignore +++ /dev/null @@ -1,3 +0,0 @@ -# Add patterns of files dvc should ignore, which could improve -# the performance. Learn more at -# https://dvc.org/doc/user-guide/dvcignore diff --git a/modules/ml-pipeline/.gto b/modules/ml-pipeline/.gto deleted file mode 100644 index c44c86e..0000000 --- a/modules/ml-pipeline/.gto +++ /dev/null @@ -1,2 +0,0 @@ -# .gto config file -stages: [dev, stage, prod] # list of allowed Stages diff --git a/modules/ml-pipeline/src/.dockerignore b/modules/ml-pipeline/src/.dockerignore new file mode 100644 index 0000000..14f71d7 --- /dev/null +++ b/modules/ml-pipeline/src/.dockerignore @@ -0,0 +1,4 @@ +pipeline/data/predictions* +pipeline/data/prepared_data/train.parquet* +pipeline/data/model/allmodels* +pipeline/metrics* diff --git a/modules/ml-pipeline/src/pipeline/.gitignore b/modules/ml-pipeline/src/pipeline/.gitignore index bf035d2..ce8309f 100644 --- a/modules/ml-pipeline/src/pipeline/.gitignore +++ b/modules/ml-pipeline/src/pipeline/.gitignore @@ -1,3 +1,4 @@ # Ignore dynaconf secret files .secrets.* +example.py diff --git a/modules/ml-pipeline/src/pipeline/4_generate_metrics.py b/modules/ml-pipeline/src/pipeline/4_generate_metrics.py index 937c5be..ddcd3cc 100644 --- a/modules/ml-pipeline/src/pipeline/4_generate_metrics.py +++ b/modules/ml-pipeline/src/pipeline/4_generate_metrics.py @@ -33,7 +33,6 @@ predictions_output_filepath = generate_predictions_params["predictions_output_fi predictions_column_name = generate_predictions_params["predictions_column_name"] metrics_output_filepath = generate_metrics_params["metrics_output_filepath"] - logger.info(f"--- Initiate MLModel ---") model = model_factory(build_model_params["model_type"]) diff --git a/modules/ml-pipeline/src/pipeline/configs/analysis.yaml b/modules/ml-pipeline/src/pipeline/configs/analysis.yaml index 5c6e749..725660b 100644 --- a/modules/ml-pipeline/src/pipeline/configs/analysis.yaml +++ b/modules/ml-pipeline/src/pipeline/configs/analysis.yaml @@ -13,4 +13,4 @@ default: dataclient_type: local nshap_samples: 100 # how many samples to use to approximate each Shapely value, larger values will be slower n_val: 30 # how many datapoints from validation data should we interpret predictions for, larger values will be slower - row_index: [0, 10, 20] # index of an example datapoint + row_index: [20695, 50243, 7653] # index of an example datapoint diff --git a/modules/ml-pipeline/src/pipeline/configs/build_model.yaml b/modules/ml-pipeline/src/pipeline/configs/build_model.yaml index fcec7f7..be5ec5c 100644 --- a/modules/ml-pipeline/src/pipeline/configs/build_model.yaml +++ b/modules/ml-pipeline/src/pipeline/configs/build_model.yaml @@ -19,3 +19,4 @@ default: excluded_model_types: ['RF', 'FASTAI', 'CAT', 'NN_TORCH', 'KNN', 'XT'] infer_limit: 0.05 infer_limit_batch_size: 10000 + ag_args_ensemble: {'num_folds_parallel': 2} diff --git a/modules/ml-pipeline/src/pipeline/configs/feature_processor_logic.py b/modules/ml-pipeline/src/pipeline/configs/feature_processor_logic.py index 94d3c6e..bcc53e5 100644 --- a/modules/ml-pipeline/src/pipeline/configs/feature_processor_logic.py +++ b/modules/ml-pipeline/src/pipeline/configs/feature_processor_logic.py @@ -73,7 +73,7 @@ business_logic = { "keep_negative_carbon_change": keep_negative_carbon_change, "remove_top_1_percent_heat_demand": remove_top_1_percent_heat_demand, "remove_top_1_percent_carbon": remove_top_1_percent_carbon, - "keep_non_negative_carbon_ending": keep_non_negative_carbon_ending + "keep_non_negative_carbon_ending": keep_non_negative_carbon_ending, # "remove_starting_columns": remove_starting_columns # "keep_ENDING_COLUMNS": keep_ending_columns } diff --git a/modules/ml-pipeline/src/pipeline/configs/post_prediction_logic.py b/modules/ml-pipeline/src/pipeline/configs/post_prediction_logic.py index dec7740..2ca8890 100644 --- a/modules/ml-pipeline/src/pipeline/configs/post_prediction_logic.py +++ b/modules/ml-pipeline/src/pipeline/configs/post_prediction_logic.py @@ -1,6 +1,7 @@ """ After predictions, we may want to apply some post processing to the predictions """ + import pandas as pd @@ -11,6 +12,7 @@ def clip_predictions_to_minimum_value( series_name = predictions.name predictions.name = "predictions" + predictions = predictions.astype(data["carbon_starting"].dtype) predictions_df = pd.concat([data, predictions], axis=1) # We expect all prediction to be atleast one point improvement replace_index = predictions_df["predictions"] > predictions_df["carbon_starting"] diff --git a/modules/ml-pipeline/src/pipeline/configs/settings.yaml b/modules/ml-pipeline/src/pipeline/configs/settings.yaml index 051e34e..66f7089 100644 --- a/modules/ml-pipeline/src/pipeline/configs/settings.yaml +++ b/modules/ml-pipeline/src/pipeline/configs/settings.yaml @@ -18,12 +18,8 @@ default: prepare_data: input_dataclient_type: aws-s3 output_dataclient_type: local - # data_filepath: s3://retrofit-data-dev/sap_change_model/dataset_with_differencing.parquet - # data_filepath: s3://retrofit-data-dev/sap_change_model/floor_area_clean_test.parquet - # data_filepath: s3://retrofit-data-dev/sap_change_model/dataset_without_differencing.parquet - # data_filepath: s3://retrofit-data-dev/sap_change_model/dataset.parquet - data_filepath: s3://retrofit-datalake-dev/dataset_with0perm_all.parquet - train_proportion: 1 + data_filepath: s3://retrofit-data-dev/sap_change_model/2024-03-22-18-56-53/dataset_rooms.parquet + train_proportion: 0.9 output_train_filepath: ./data/prepared_data/train.parquet output_test_filepath: ./data/prepared_data/test.parquet @@ -34,7 +30,11 @@ default: subsample_seed: 0 target: carbon_ending identifier_columns: ["uprn"] - drop_columns: ["heat_demand_change", "carbon_change", "rdsap_change", "heat_demand_ending", "sap_ending"] + # drop_columns: ["heat_demand_change", "carbon_change", "rdsap_change", "heat_demand_ending", "sap_ending"] + drop_columns: [ + "heat_demand_change", "carbon_change", "rdsap_change", "heat_demand_ending", "sap_ending", "days_to_starting", "days_to_ending", + 'number_habitable_rooms_starting', 'number_habitable_rooms_ending', 'number_heated_rooms_starting', 'number_heated_rooms_ending', + 'number_habitable_rooms', 'number_heated_rooms'] # retain_features: ["SAP_STARTING", "TOTAL_FLOOR_AREA_DIFF"] retain_features: null diff --git a/modules/ml-pipeline/src/pipeline/core/MLModels.py b/modules/ml-pipeline/src/pipeline/core/MLModels.py index 4fc572a..257261d 100644 --- a/modules/ml-pipeline/src/pipeline/core/MLModels.py +++ b/modules/ml-pipeline/src/pipeline/core/MLModels.py @@ -25,7 +25,7 @@ def model_factory(model_type: str) -> MLModel: models = { "SKLearnLinearRegression": SKLearnLinearRegression(), "SKLearnSVMRegression": SKLearnSVMRegression(), - "AutogluonAutoML": AutogluonAutoML() + "AutogluonAutoML": AutogluonAutoML(), # ADD OTHER MODELS HERE } @@ -151,6 +151,7 @@ class AutogluonAutoML: "excluded_model_types", "infer_limit", "infer_limit_batch_size", + "ag_args_ensemble", ] def load_model(self, path: Union[Path, str]) -> None: @@ -207,6 +208,7 @@ class AutogluonAutoML: excluded_model_types=model_hyperparameters["excluded_model_types"], infer_limit=model_hyperparameters["infer_limit"], infer_limit_batch_size=model_hyperparameters["infer_limit_batch_size"], + ag_args_ensemble=model_hyperparameters["ag_args_ensemble"], ) def predict( diff --git a/modules/ml-pipeline/src/pipeline/dvc.lock b/modules/ml-pipeline/src/pipeline/dvc.lock index dc996b7..ef40a2d 100644 --- a/modules/ml-pipeline/src/pipeline/dvc.lock +++ b/modules/ml-pipeline/src/pipeline/dvc.lock @@ -1,5 +1,16 @@ schema: '2.0' stages: + startup_cleanup: + cmd: python 0_startup_cleanup.py + deps: + - path: 0_startup_cleanup.py + hash: md5 + md5: b1b12f6b6393fbf8b83d23684df0a3d4 + size: 1220 + params: + configs/settings.yaml: + default.startup_cleanup.artefacts: ./data + default.startup_cleanup.metrics: ./metrics prepare_data: cmd: python 1_prepare_data.py deps: @@ -15,34 +26,43 @@ stages: - rdsap_change - heat_demand_ending - sap_ending + - days_to_starting + - days_to_ending + - number_habitable_rooms_starting + - number_habitable_rooms_ending + - number_heated_rooms_starting + - number_heated_rooms_ending + - number_habitable_rooms + - number_heated_rooms default.feature_processor.feature_processor_config.retain_features: default.feature_processor.feature_processor_config.subsample_amount: default.feature_processor.feature_processor_config.subsample_seed: 0 default.feature_processor.feature_processor_config.target: carbon_ending default.feature_processor.feature_processor_type: dataframe - default.prepare_data.data_filepath: s3://retrofit-datalake-dev/dataset_with0perm_all.parquet + default.prepare_data.data_filepath: + s3://retrofit-data-dev/sap_change_model/2024-03-22-18-56-53/dataset_rooms.parquet default.prepare_data.input_dataclient_type: aws-s3 default.prepare_data.output_dataclient_type: local default.prepare_data.output_test_filepath: ./data/prepared_data/test.parquet default.prepare_data.output_train_filepath: ./data/prepared_data/train.parquet - default.prepare_data.train_proportion: 1 + default.prepare_data.train_proportion: 0.9 outs: - path: data/prepared_data/ hash: md5 - md5: 44737880f5437e23143479a7818a3136.dir - size: 36064622 + md5: 824541f44e6538d2ef10e9d754c79743.dir + size: 36691842 nfiles: 2 build_model: cmd: python 2_build_model.py deps: - path: 2_build_model.py hash: md5 - md5: 090bfb7dbaff39f45784b7fe332a9b8e - size: 4819 + md5: 7231450b78920b0c5e7c6bada496b24a + size: 4820 - path: data/prepared_data hash: md5 - md5: 44737880f5437e23143479a7818a3136.dir - size: 36064622 + md5: 824541f44e6538d2ef10e9d754c79743.dir + size: 36691842 nfiles: 2 params: configs/build_model.yaml: @@ -70,21 +90,23 @@ stages: - XT infer_limit: 0.05 infer_limit_batch_size: 10000 + ag_args_ensemble: + num_folds_parallel: 2 outs: - path: data/fit_predictions/ hash: md5 - md5: 7b74ae1174ae2c7fab03ee0ce0a8ae71.dir - size: 3877514 + md5: 5a3091120d3497fa00b994d91bc7e5eb.dir + size: 3664806 nfiles: 1 - path: data/model/ hash: md5 - md5: d2ebaa73a894387f85083c49e58637bc.dir - size: 798349514 - nfiles: 32 + md5: 074da8dcfa515b9f3d082b21c7d76616.dir + size: 721558897 + nfiles: 31 - path: metrics/fit_metrics.json hash: md5 - md5: 51c9c678bbd19bc9f7e16f0bf5df3fef - size: 229 + md5: 728a49dcef5a98182325df455f929a33 + size: 225 generate_predictions: cmd: python 3_generate_predictions.py deps: @@ -94,13 +116,13 @@ stages: size: 2464 - path: data/model hash: md5 - md5: d2ebaa73a894387f85083c49e58637bc.dir - size: 798349514 - nfiles: 32 + md5: 074da8dcfa515b9f3d082b21c7d76616.dir + size: 721558897 + nfiles: 31 - path: data/prepared_data hash: md5 - md5: 44737880f5437e23143479a7818a3136.dir - size: 36064622 + md5: 824541f44e6538d2ef10e9d754c79743.dir + size: 36691842 nfiles: 2 params: configs/settings.yaml: @@ -112,25 +134,25 @@ stages: outs: - path: data/predictions/ hash: md5 - md5: ac0a698f14fb9002b337b1b163997333.dir - size: 638033 + md5: 680f51234d214d4cab9e6a064c75fc5d.dir + size: 499546 nfiles: 1 generate_metrics: cmd: python 4_generate_metrics.py deps: - path: 4_generate_metrics.py hash: md5 - md5: d09a80dd55f1f69e2a832b1991b3c406 - size: 3485 + md5: 4fedb86d89d528f0a6597934ba3890a0 + size: 3484 - path: data/predictions hash: md5 - md5: ac0a698f14fb9002b337b1b163997333.dir - size: 638033 + md5: 680f51234d214d4cab9e6a064c75fc5d.dir + size: 499546 nfiles: 1 - path: data/prepared_data hash: md5 - md5: 44737880f5437e23143479a7818a3136.dir - size: 36064622 + md5: 824541f44e6538d2ef10e9d754c79743.dir + size: 36691842 nfiles: 2 params: configs/settings.yaml: @@ -140,16 +162,5 @@ stages: outs: - path: metrics/metrics.json hash: md5 - md5: 47aa4601e71a93163d2cc1b85d0eda91 - size: 228 - startup_cleanup: - cmd: python 0_startup_cleanup.py - deps: - - path: 0_startup_cleanup.py - hash: md5 - md5: b1b12f6b6393fbf8b83d23684df0a3d4 - size: 1220 - params: - configs/settings.yaml: - default.startup_cleanup.artefacts: ./data - default.startup_cleanup.metrics: ./metrics + md5: 67b7ab30a4b0839d20bc6eb0c84e4dd1 + size: 226 diff --git a/modules/ml-pipeline/src/pipeline/eda.py b/modules/ml-pipeline/src/pipeline/eda.py index 2fdd8be..e1d33a6 100644 --- a/modules/ml-pipeline/src/pipeline/eda.py +++ b/modules/ml-pipeline/src/pipeline/eda.py @@ -190,28 +190,35 @@ prediction_analysis_params = settings.prediction_analysis model = model_factory(build_model_params["model_type"]) model.load_model(build_model_params["model_save_filepath"]) dataclient_type = prediction_analysis_params["dataclient_type"] -dataclient = dataclient_factory( - dataclient_type=dataclient_type, - dataclient_config=client_params[dataclient_type], -) +# dataclient_type = 'aws-s3' +# dataclient = dataclient_factory( +# dataclient_type=dataclient_type, +# dataclient_config=client_params[dataclient_type], +# ) +# data = dataclient.load_data("s3://retrofit-data-dev/sap_change_model/dataset.parquet") target = feature_process_params["feature_processor_config"]["target"] predictions_column_name = generate_predictions_params["predictions_column_name"] output_test_filepath = prepare_data_params["output_test_filepath"] predictions_output_filepath = generate_predictions_params["predictions_output_filepath"] -test_df = dataclient.load_data(output_test_filepath) -predictions = dataclient.load_data(predictions_output_filepath) +# score_data = dataclient.load_data("s3://retrofit-data-dev/carbon_change_predictions/51/2023-11-28T21:01:21.869339.parquet") + + +local_dataclient = dataclient_factory( + dataclient_type="local", + dataclient_config=client_params["local"], +) +test_df = local_dataclient.load_data(output_test_filepath) +predictions = local_dataclient.load_data(predictions_output_filepath) mix_df = pd.concat([test_df.copy(), predictions], axis=1) mix_df["residual"] = abs(mix_df[predictions_column_name] - mix_df[target]) mix_df = mix_df.sort_values("residual", ascending=False) -cosine_similarity_df = mix_df[ - mix_df.columns.difference(["predictions", "residual", "SAP_ENDING"]) -] +cosine_similarity_df = mix_df[mix_df.columns.difference(["predictions", "residual"])] from sklearn.metrics.pairwise import cosine_similarity -row_index = 58199 +row_index = 0 from sklearn.preprocessing import LabelEncoder @@ -225,7 +232,17 @@ feature_vector = cosine_similarity_df.loc[[row_index]] cosine_similarity_df["cosine"] = cosine_similarity(cosine_similarity_df, feature_vector) similar_index = ( - cosine_similarity_df.sort_values("cosine", ascending=False).head(5).index + cosine_similarity_df.sort_values("cosine", ascending=False).head(15).index ) check_df = mix_df.loc[similar_index] + +columns_to_check = [ + "LOW_ENERGY_LIGHTING_ENDING", + "walls_thermal_transmittance_ENDING", + "floor_thermal_transmittance_ENDING", + "roof_thermal_transmittance_ENDING", + "roof_insulation_thickness_ENDING", +] + +cosine_similarity_df = mix_df[columns_to_check] diff --git a/modules/ml-pipeline/src/pipeline/example.py b/modules/ml-pipeline/src/pipeline/example.py deleted file mode 100644 index e69de29..0000000 diff --git a/modules/ml-pipeline/src/pipeline/requirements/predictions/requirements-dev.txt b/modules/ml-pipeline/src/pipeline/requirements/predictions/requirements-dev.txt index 0d259fb..734419a 100644 --- a/modules/ml-pipeline/src/pipeline/requirements/predictions/requirements-dev.txt +++ b/modules/ml-pipeline/src/pipeline/requirements/predictions/requirements-dev.txt @@ -1,7 +1,7 @@ joblib==1.3.2 boto3==1.28.17 -pandas==1.5.3 -autogluon==0.8.2 -dynaconf==3.2.0 +pandas==2.1.4 +autogluon==1.0.0 +dynaconf==3.2.1 pyarrow==13.0.0 pre-commit==3.3.3 diff --git a/modules/ml-pipeline/src/pipeline/requirements/predictions/requirements.txt b/modules/ml-pipeline/src/pipeline/requirements/predictions/requirements.txt index afad9be..937b000 100644 --- a/modules/ml-pipeline/src/pipeline/requirements/predictions/requirements.txt +++ b/modules/ml-pipeline/src/pipeline/requirements/predictions/requirements.txt @@ -1,7 +1,7 @@ joblib==1.3.2 boto3==1.28.17 -pandas==1.5.3 -autogluon==0.8.2 -dynaconf==3.2.0 +pandas==2.1.4 +autogluon==1.0.0 +dynaconf==3.2.1 pyarrow==13.0.0 PyYAML==6.0.1 diff --git a/modules/ml-pipeline/src/pipeline/requirements/training/requirements-dev.txt b/modules/ml-pipeline/src/pipeline/requirements/training/requirements-dev.txt index d8c5907..fe06a4d 100644 --- a/modules/ml-pipeline/src/pipeline/requirements/training/requirements-dev.txt +++ b/modules/ml-pipeline/src/pipeline/requirements/training/requirements-dev.txt @@ -1,9 +1,10 @@ joblib==1.3.2 boto3==1.28.17 -pandas==1.5.3 -autogluon==0.8.2 -dynaconf==3.2.0 -alibi==0.9.4 +pandas==2.1.4 +autogluon==1.0.0 +ray==2.6.3 +dynaconf==3.2.1 +alibi==0.9.5 shap==0.42.1 pyarrow==13.0.0 pre-commit==3.3.3 diff --git a/modules/ml-pipeline/src/pipeline/requirements/training/requirements.txt b/modules/ml-pipeline/src/pipeline/requirements/training/requirements.txt index bbdc2fa..a5bccd3 100644 --- a/modules/ml-pipeline/src/pipeline/requirements/training/requirements.txt +++ b/modules/ml-pipeline/src/pipeline/requirements/training/requirements.txt @@ -1,4 +1,4 @@ boto3==1.28.41 -pandas==1.5.3 -autogluon==0.8.2 -dynaconf==3.2.0 +pandas==2.1.4 +autogluon==1.0.0 +dynaconf==3.2.1