Merge pull request #107 from Hestia-Homes/carbon-dev-model

Carbon dev model
This commit is contained in:
KhalimCK 2024-03-28 16:21:52 +00:00 committed by GitHub
commit c0c8d85cec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 119 additions and 87 deletions

4
deployment/.dockerignore Normal file
View file

@ -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*

View file

@ -9,7 +9,7 @@ ARG RUNTIME_ENVIRONMENT
ENV RUNTIME_ENVIRONMENT=${RUNTIME_ENVIRONMENT} ENV RUNTIME_ENVIRONMENT=${RUNTIME_ENVIRONMENT}
# Install necessary build tools - required to test locally # 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 # Install python packages
COPY modules/ml-pipeline/src/pipeline/requirements/predictions/requirements.txt ./requirements.txt COPY modules/ml-pipeline/src/pipeline/requirements/predictions/requirements.txt ./requirements.txt

View file

@ -1,3 +0,0 @@
/config.local
/tmp
/cache

View file

@ -1,2 +0,0 @@
['remote "myremote"']
url = /tmp/dvcstore

View file

@ -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

View file

@ -1,2 +0,0 @@
# .gto config file
stages: [dev, stage, prod] # list of allowed Stages

View file

@ -0,0 +1,4 @@
pipeline/data/predictions*
pipeline/data/prepared_data/train.parquet*
pipeline/data/model/allmodels*
pipeline/metrics*

View file

@ -1,3 +1,4 @@
# Ignore dynaconf secret files # Ignore dynaconf secret files
.secrets.* .secrets.*
example.py

View file

@ -33,7 +33,6 @@ predictions_output_filepath = generate_predictions_params["predictions_output_fi
predictions_column_name = generate_predictions_params["predictions_column_name"] predictions_column_name = generate_predictions_params["predictions_column_name"]
metrics_output_filepath = generate_metrics_params["metrics_output_filepath"] metrics_output_filepath = generate_metrics_params["metrics_output_filepath"]
logger.info(f"--- Initiate MLModel ---") logger.info(f"--- Initiate MLModel ---")
model = model_factory(build_model_params["model_type"]) model = model_factory(build_model_params["model_type"])

View file

@ -13,4 +13,4 @@ default:
dataclient_type: local dataclient_type: local
nshap_samples: 100 # how many samples to use to approximate each Shapely value, larger values will be slower 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 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

View file

@ -19,3 +19,4 @@ default:
excluded_model_types: ['RF', 'FASTAI', 'CAT', 'NN_TORCH', 'KNN', 'XT'] excluded_model_types: ['RF', 'FASTAI', 'CAT', 'NN_TORCH', 'KNN', 'XT']
infer_limit: 0.05 infer_limit: 0.05
infer_limit_batch_size: 10000 infer_limit_batch_size: 10000
ag_args_ensemble: {'num_folds_parallel': 2}

View file

@ -73,7 +73,7 @@ business_logic = {
"keep_negative_carbon_change": keep_negative_carbon_change, "keep_negative_carbon_change": keep_negative_carbon_change,
"remove_top_1_percent_heat_demand": remove_top_1_percent_heat_demand, "remove_top_1_percent_heat_demand": remove_top_1_percent_heat_demand,
"remove_top_1_percent_carbon": remove_top_1_percent_carbon, "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 # "remove_starting_columns": remove_starting_columns
# "keep_ENDING_COLUMNS": keep_ending_columns # "keep_ENDING_COLUMNS": keep_ending_columns
} }

View file

@ -1,6 +1,7 @@
""" """
After predictions, we may want to apply some post processing to the predictions After predictions, we may want to apply some post processing to the predictions
""" """
import pandas as pd import pandas as pd
@ -11,6 +12,7 @@ def clip_predictions_to_minimum_value(
series_name = predictions.name series_name = predictions.name
predictions.name = "predictions" predictions.name = "predictions"
predictions = predictions.astype(data["carbon_starting"].dtype)
predictions_df = pd.concat([data, predictions], axis=1) predictions_df = pd.concat([data, predictions], axis=1)
# We expect all prediction to be atleast one point improvement # We expect all prediction to be atleast one point improvement
replace_index = predictions_df["predictions"] > predictions_df["carbon_starting"] replace_index = predictions_df["predictions"] > predictions_df["carbon_starting"]

View file

@ -18,12 +18,8 @@ default:
prepare_data: prepare_data:
input_dataclient_type: aws-s3 input_dataclient_type: aws-s3
output_dataclient_type: local 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/2024-03-22-18-56-53/dataset_rooms.parquet
# data_filepath: s3://retrofit-data-dev/sap_change_model/floor_area_clean_test.parquet train_proportion: 0.9
# 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
output_train_filepath: ./data/prepared_data/train.parquet output_train_filepath: ./data/prepared_data/train.parquet
output_test_filepath: ./data/prepared_data/test.parquet output_test_filepath: ./data/prepared_data/test.parquet
@ -34,7 +30,11 @@ default:
subsample_seed: 0 subsample_seed: 0
target: carbon_ending target: carbon_ending
identifier_columns: ["uprn"] 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: ["SAP_STARTING", "TOTAL_FLOOR_AREA_DIFF"]
retain_features: null retain_features: null

View file

@ -25,7 +25,7 @@ def model_factory(model_type: str) -> MLModel:
models = { models = {
"SKLearnLinearRegression": SKLearnLinearRegression(), "SKLearnLinearRegression": SKLearnLinearRegression(),
"SKLearnSVMRegression": SKLearnSVMRegression(), "SKLearnSVMRegression": SKLearnSVMRegression(),
"AutogluonAutoML": AutogluonAutoML() "AutogluonAutoML": AutogluonAutoML(),
# ADD OTHER MODELS HERE # ADD OTHER MODELS HERE
} }
@ -151,6 +151,7 @@ class AutogluonAutoML:
"excluded_model_types", "excluded_model_types",
"infer_limit", "infer_limit",
"infer_limit_batch_size", "infer_limit_batch_size",
"ag_args_ensemble",
] ]
def load_model(self, path: Union[Path, str]) -> None: def load_model(self, path: Union[Path, str]) -> None:
@ -207,6 +208,7 @@ class AutogluonAutoML:
excluded_model_types=model_hyperparameters["excluded_model_types"], excluded_model_types=model_hyperparameters["excluded_model_types"],
infer_limit=model_hyperparameters["infer_limit"], infer_limit=model_hyperparameters["infer_limit"],
infer_limit_batch_size=model_hyperparameters["infer_limit_batch_size"], infer_limit_batch_size=model_hyperparameters["infer_limit_batch_size"],
ag_args_ensemble=model_hyperparameters["ag_args_ensemble"],
) )
def predict( def predict(

View file

@ -1,5 +1,16 @@
schema: '2.0' schema: '2.0'
stages: 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: prepare_data:
cmd: python 1_prepare_data.py cmd: python 1_prepare_data.py
deps: deps:
@ -15,34 +26,43 @@ stages:
- rdsap_change - rdsap_change
- heat_demand_ending - heat_demand_ending
- sap_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.retain_features:
default.feature_processor.feature_processor_config.subsample_amount: default.feature_processor.feature_processor_config.subsample_amount:
default.feature_processor.feature_processor_config.subsample_seed: 0 default.feature_processor.feature_processor_config.subsample_seed: 0
default.feature_processor.feature_processor_config.target: carbon_ending default.feature_processor.feature_processor_config.target: carbon_ending
default.feature_processor.feature_processor_type: dataframe 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.input_dataclient_type: aws-s3
default.prepare_data.output_dataclient_type: local default.prepare_data.output_dataclient_type: local
default.prepare_data.output_test_filepath: ./data/prepared_data/test.parquet 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.output_train_filepath: ./data/prepared_data/train.parquet
default.prepare_data.train_proportion: 1 default.prepare_data.train_proportion: 0.9
outs: outs:
- path: data/prepared_data/ - path: data/prepared_data/
hash: md5 hash: md5
md5: 44737880f5437e23143479a7818a3136.dir md5: 824541f44e6538d2ef10e9d754c79743.dir
size: 36064622 size: 36691842
nfiles: 2 nfiles: 2
build_model: build_model:
cmd: python 2_build_model.py cmd: python 2_build_model.py
deps: deps:
- path: 2_build_model.py - path: 2_build_model.py
hash: md5 hash: md5
md5: 090bfb7dbaff39f45784b7fe332a9b8e md5: 7231450b78920b0c5e7c6bada496b24a
size: 4819 size: 4820
- path: data/prepared_data - path: data/prepared_data
hash: md5 hash: md5
md5: 44737880f5437e23143479a7818a3136.dir md5: 824541f44e6538d2ef10e9d754c79743.dir
size: 36064622 size: 36691842
nfiles: 2 nfiles: 2
params: params:
configs/build_model.yaml: configs/build_model.yaml:
@ -70,21 +90,23 @@ stages:
- XT - XT
infer_limit: 0.05 infer_limit: 0.05
infer_limit_batch_size: 10000 infer_limit_batch_size: 10000
ag_args_ensemble:
num_folds_parallel: 2
outs: outs:
- path: data/fit_predictions/ - path: data/fit_predictions/
hash: md5 hash: md5
md5: 7b74ae1174ae2c7fab03ee0ce0a8ae71.dir md5: 5a3091120d3497fa00b994d91bc7e5eb.dir
size: 3877514 size: 3664806
nfiles: 1 nfiles: 1
- path: data/model/ - path: data/model/
hash: md5 hash: md5
md5: d2ebaa73a894387f85083c49e58637bc.dir md5: 074da8dcfa515b9f3d082b21c7d76616.dir
size: 798349514 size: 721558897
nfiles: 32 nfiles: 31
- path: metrics/fit_metrics.json - path: metrics/fit_metrics.json
hash: md5 hash: md5
md5: 51c9c678bbd19bc9f7e16f0bf5df3fef md5: 728a49dcef5a98182325df455f929a33
size: 229 size: 225
generate_predictions: generate_predictions:
cmd: python 3_generate_predictions.py cmd: python 3_generate_predictions.py
deps: deps:
@ -94,13 +116,13 @@ stages:
size: 2464 size: 2464
- path: data/model - path: data/model
hash: md5 hash: md5
md5: d2ebaa73a894387f85083c49e58637bc.dir md5: 074da8dcfa515b9f3d082b21c7d76616.dir
size: 798349514 size: 721558897
nfiles: 32 nfiles: 31
- path: data/prepared_data - path: data/prepared_data
hash: md5 hash: md5
md5: 44737880f5437e23143479a7818a3136.dir md5: 824541f44e6538d2ef10e9d754c79743.dir
size: 36064622 size: 36691842
nfiles: 2 nfiles: 2
params: params:
configs/settings.yaml: configs/settings.yaml:
@ -112,25 +134,25 @@ stages:
outs: outs:
- path: data/predictions/ - path: data/predictions/
hash: md5 hash: md5
md5: ac0a698f14fb9002b337b1b163997333.dir md5: 680f51234d214d4cab9e6a064c75fc5d.dir
size: 638033 size: 499546
nfiles: 1 nfiles: 1
generate_metrics: generate_metrics:
cmd: python 4_generate_metrics.py cmd: python 4_generate_metrics.py
deps: deps:
- path: 4_generate_metrics.py - path: 4_generate_metrics.py
hash: md5 hash: md5
md5: d09a80dd55f1f69e2a832b1991b3c406 md5: 4fedb86d89d528f0a6597934ba3890a0
size: 3485 size: 3484
- path: data/predictions - path: data/predictions
hash: md5 hash: md5
md5: ac0a698f14fb9002b337b1b163997333.dir md5: 680f51234d214d4cab9e6a064c75fc5d.dir
size: 638033 size: 499546
nfiles: 1 nfiles: 1
- path: data/prepared_data - path: data/prepared_data
hash: md5 hash: md5
md5: 44737880f5437e23143479a7818a3136.dir md5: 824541f44e6538d2ef10e9d754c79743.dir
size: 36064622 size: 36691842
nfiles: 2 nfiles: 2
params: params:
configs/settings.yaml: configs/settings.yaml:
@ -140,16 +162,5 @@ stages:
outs: outs:
- path: metrics/metrics.json - path: metrics/metrics.json
hash: md5 hash: md5
md5: 47aa4601e71a93163d2cc1b85d0eda91 md5: 67b7ab30a4b0839d20bc6eb0c84e4dd1
size: 228 size: 226
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

View file

@ -190,28 +190,35 @@ prediction_analysis_params = settings.prediction_analysis
model = model_factory(build_model_params["model_type"]) model = model_factory(build_model_params["model_type"])
model.load_model(build_model_params["model_save_filepath"]) model.load_model(build_model_params["model_save_filepath"])
dataclient_type = prediction_analysis_params["dataclient_type"] dataclient_type = prediction_analysis_params["dataclient_type"]
dataclient = dataclient_factory( # dataclient_type = 'aws-s3'
dataclient_type=dataclient_type, # dataclient = dataclient_factory(
dataclient_config=client_params[dataclient_type], # 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"] target = feature_process_params["feature_processor_config"]["target"]
predictions_column_name = generate_predictions_params["predictions_column_name"] predictions_column_name = generate_predictions_params["predictions_column_name"]
output_test_filepath = prepare_data_params["output_test_filepath"] output_test_filepath = prepare_data_params["output_test_filepath"]
predictions_output_filepath = generate_predictions_params["predictions_output_filepath"] predictions_output_filepath = generate_predictions_params["predictions_output_filepath"]
test_df = dataclient.load_data(output_test_filepath) # score_data = dataclient.load_data("s3://retrofit-data-dev/carbon_change_predictions/51/2023-11-28T21:01:21.869339.parquet")
predictions = dataclient.load_data(predictions_output_filepath)
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 = pd.concat([test_df.copy(), predictions], axis=1)
mix_df["residual"] = abs(mix_df[predictions_column_name] - mix_df[target]) mix_df["residual"] = abs(mix_df[predictions_column_name] - mix_df[target])
mix_df = mix_df.sort_values("residual", ascending=False) mix_df = mix_df.sort_values("residual", ascending=False)
cosine_similarity_df = mix_df[ cosine_similarity_df = mix_df[mix_df.columns.difference(["predictions", "residual"])]
mix_df.columns.difference(["predictions", "residual", "SAP_ENDING"])
]
from sklearn.metrics.pairwise import cosine_similarity from sklearn.metrics.pairwise import cosine_similarity
row_index = 58199 row_index = 0
from sklearn.preprocessing import LabelEncoder 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) cosine_similarity_df["cosine"] = cosine_similarity(cosine_similarity_df, feature_vector)
similar_index = ( 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] 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]

View file

@ -1,7 +1,7 @@
joblib==1.3.2 joblib==1.3.2
boto3==1.28.17 boto3==1.28.17
pandas==1.5.3 pandas==2.1.4
autogluon==0.8.2 autogluon==1.0.0
dynaconf==3.2.0 dynaconf==3.2.1
pyarrow==13.0.0 pyarrow==13.0.0
pre-commit==3.3.3 pre-commit==3.3.3

View file

@ -1,7 +1,7 @@
joblib==1.3.2 joblib==1.3.2
boto3==1.28.17 boto3==1.28.17
pandas==1.5.3 pandas==2.1.4
autogluon==0.8.2 autogluon==1.0.0
dynaconf==3.2.0 dynaconf==3.2.1
pyarrow==13.0.0 pyarrow==13.0.0
PyYAML==6.0.1 PyYAML==6.0.1

View file

@ -1,9 +1,10 @@
joblib==1.3.2 joblib==1.3.2
boto3==1.28.17 boto3==1.28.17
pandas==1.5.3 pandas==2.1.4
autogluon==0.8.2 autogluon==1.0.0
dynaconf==3.2.0 ray==2.6.3
alibi==0.9.4 dynaconf==3.2.1
alibi==0.9.5
shap==0.42.1 shap==0.42.1
pyarrow==13.0.0 pyarrow==13.0.0
pre-commit==3.3.3 pre-commit==3.3.3

View file

@ -1,4 +1,4 @@
boto3==1.28.41 boto3==1.28.41
pandas==1.5.3 pandas==2.1.4
autogluon==0.8.2 autogluon==1.0.0
dynaconf==3.2.0 dynaconf==3.2.1