From 02b074c035086f86af7fc1e3ae5b235d1dbd7639 Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 9 Feb 2024 16:41:23 +0000 Subject: [PATCH 01/13] feat(preprocessing): moved changes form Ethan's branch in old repo --- CHANGELOG.md | 5 + README.md | 2 +- main.tf | 21 +- .../models_template_notebook.ipynb | 1830 +++++------------ modules/s3/main.tf | 12 +- modules/s3/variables.tf | 7 +- modules/sagemaker/main.tf | 21 +- .../templates/startupscript.sh.tftpl | 6 + modules/sagemaker/variables.tf | 5 + variables.tf | 6 + 10 files changed, 621 insertions(+), 1294 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b366aa1..c4f1a00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ # AWS-MLOps-module +## [2.0.2] - 09/02/24 +* Added functionality for passing preprocessing script + +## [2.0.1] - 02/02/24 +* Updated retraining_schedule validation ## [2.0.0] - 21/12/23 **BREAKING CHANGES** diff --git a/README.md b/README.md index 252b5dc..fbc3683 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This repo contains a terraform module with corresponding AWS resources that enab ## Example Usage - +#TODO update ``` module "MLOps" { source = "github.com/crederauk/terraform-aws-mlops-module?ref=" diff --git a/main.tf b/main.tf index 685f88e..dcc025e 100644 --- a/main.tf +++ b/main.tf @@ -1,8 +1,9 @@ module "s3" { source = "./modules/s3" - resource_naming_prefix = var.resource_naming_prefix - tags = var.tags + resource_naming_prefix = var.resource_naming_prefix + tags = var.tags + preprocessing_script_path = var.preprocessing_script_path } module "sagemaker" { @@ -26,15 +27,15 @@ module "sagemaker" { ecr_repo_uri = "${module.ecr.repository.repository_url}:latest" # S3 - config_s3_bucket = module.s3.config_bucket.id - config_bucket_key_arn = module.s3.encryption_key.arn - data_s3_bucket = var.data_s3_bucket - data_bucket_key_arn = var.data_s3_bucket_encryption_key_arn - data_location_s3 = var.data_location_s3 - model_s3_bucket = module.s3.model_bucket.id - model_bucket_key_arn = module.s3.encryption_key.arn + config_s3_bucket = module.s3.config_bucket.id + config_bucket_key_arn = module.s3.encryption_key.arn + data_s3_bucket = var.data_s3_bucket + data_bucket_key_arn = var.data_s3_bucket_encryption_key_arn + data_location_s3 = var.data_location_s3 + model_s3_bucket = module.s3.model_bucket.id + model_bucket_key_arn = module.s3.encryption_key.arn + preprocessing_script_path = var.preprocessing_script_path } - module "retraining_job" { count = var.retrain_model_bool ? 1 : 0 source = "./modules/glue" diff --git a/mlops_ml_models/models_template_notebook.ipynb b/mlops_ml_models/models_template_notebook.ipynb index e9d7e71..e5690dc 100644 --- a/mlops_ml_models/models_template_notebook.ipynb +++ b/mlops_ml_models/models_template_notebook.ipynb @@ -2,181 +2,300 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Requirement already satisfied: pycaret in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (3.2.0)\n", - "Requirement already satisfied: category-encoders>=2.4.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (2.6.3)\n", - "Requirement already satisfied: cloudpickle in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (2.2.1)\n", - "Requirement already satisfied: deprecation>=2.1.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (2.1.0)\n", - "Requirement already satisfied: imbalanced-learn>=0.8.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (0.11.0)\n", - "Requirement already satisfied: importlib-metadata>=4.12.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (6.8.0)\n", - "Requirement already satisfied: ipython>=5.5.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (8.16.1)\n", - "Requirement already satisfied: ipywidgets>=7.6.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (8.1.1)\n", - "Requirement already satisfied: jinja2>=1.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (3.1.2)\n", - "Requirement already satisfied: joblib>=1.2.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (1.3.2)\n", - "Requirement already satisfied: kaleido>=0.2.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (0.2.1)\n", - "Requirement already satisfied: lightgbm>=3.0.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (4.1.0)\n", - "Requirement already satisfied: markupsafe>=2.0.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (2.1.3)\n", - "Requirement already satisfied: matplotlib<=3.6,>=3.3.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (3.6.0)\n", - "Requirement already satisfied: nbformat>=4.2.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (5.9.2)\n", - "Requirement already satisfied: numba>=0.55.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (0.57.1)\n", - "Requirement already satisfied: numpy<1.27,>=1.21 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (1.22.4)\n", - "Requirement already satisfied: pandas<2.0.0,>=1.3.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (1.5.3)\n", - "Requirement already satisfied: plotly-resampler>=0.8.3.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (0.9.1)\n", - "Requirement already satisfied: plotly>=5.0.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (5.18.0)\n", - "Requirement already satisfied: pmdarima!=1.8.1,<3.0.0,>=1.8.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (2.0.4)\n", - "Requirement already satisfied: psutil>=5.9.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (5.9.5)\n", - "Requirement already satisfied: pyod>=1.0.8 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (1.1.2)\n", - "Requirement already satisfied: requests>=2.27.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (2.31.0)\n", - "Requirement already satisfied: schemdraw==0.15 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (0.15)\n", - "Requirement already satisfied: scikit-learn<1.3.0,>=1.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (1.2.2)\n", - "Requirement already satisfied: scikit-plot>=0.3.7 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (0.3.7)\n", - "Requirement already satisfied: scipy~=1.10.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (1.10.1)\n", - "Requirement already satisfied: sktime!=0.17.1,!=0.17.2,!=0.18.0,<0.22.0,>=0.16.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (0.21.1)\n", - "Requirement already satisfied: statsmodels>=0.12.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (0.14.0)\n", - "Requirement already satisfied: tbats>=1.1.3 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (1.1.3)\n", - "Requirement already satisfied: tqdm>=4.62.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (4.66.1)\n", - "Requirement already satisfied: xxhash in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (3.4.1)\n", - "Requirement already satisfied: yellowbrick>=1.4 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (1.5)\n", - "Requirement already satisfied: wurlitzer in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pycaret) (3.0.3)\n", - "Requirement already satisfied: patsy>=0.5.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from category-encoders>=2.4.0->pycaret) (0.5.3)\n", - "Requirement already satisfied: packaging in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from deprecation>=2.1.0->pycaret) (21.3)\n", - "Requirement already satisfied: threadpoolctl>=2.0.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from imbalanced-learn>=0.8.1->pycaret) (3.2.0)\n", - "Requirement already satisfied: zipp>=0.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from importlib-metadata>=4.12.0->pycaret) (3.17.0)\n", - "Requirement already satisfied: backcall in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (0.2.0)\n", - "Requirement already satisfied: decorator in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (5.1.1)\n", - "Requirement already satisfied: jedi>=0.16 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (0.18.2)\n", - "Requirement already satisfied: matplotlib-inline in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (0.1.6)\n", - "Requirement already satisfied: pickleshare in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (0.7.5)\n", - "Requirement already satisfied: prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (3.0.39)\n", - "Requirement already satisfied: pygments>=2.4.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (2.16.1)\n", - "Requirement already satisfied: stack-data in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (0.6.2)\n", - "Requirement already satisfied: traitlets>=5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (5.12.0)\n", - "Requirement already satisfied: exceptiongroup in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (1.1.3)\n", - "Requirement already satisfied: pexpect>4.3 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipython>=5.5.0->pycaret) (4.8.0)\n", - "Requirement already satisfied: comm>=0.1.3 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipywidgets>=7.6.5->pycaret) (0.1.4)\n", - "Requirement already satisfied: widgetsnbextension~=4.0.9 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipywidgets>=7.6.5->pycaret) (4.0.9)\n", - "Requirement already satisfied: jupyterlab-widgets~=3.0.9 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ipywidgets>=7.6.5->pycaret) (3.0.9)\n", - "Requirement already satisfied: contourpy>=1.0.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (1.1.1)\n", - "Requirement already satisfied: cycler>=0.10 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (0.12.1)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (4.43.1)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (1.4.5)\n", - "Requirement already satisfied: pillow>=6.2.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (10.0.1)\n", - "Requirement already satisfied: pyparsing>=2.2.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (3.1.1)\n", - "Requirement already satisfied: python-dateutil>=2.7 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (2.8.2)\n", - "Requirement already satisfied: fastjsonschema in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from nbformat>=4.2.0->pycaret) (2.18.1)\n", - "Requirement already satisfied: jsonschema>=2.6 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from nbformat>=4.2.0->pycaret) (4.19.1)\n", - "Requirement already satisfied: jupyter-core in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from nbformat>=4.2.0->pycaret) (5.4.0)\n", - "Requirement already satisfied: llvmlite<0.41,>=0.40.0dev0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from numba>=0.55.0->pycaret) (0.40.1)\n", - "Requirement already satisfied: pytz>=2020.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pandas<2.0.0,>=1.3.0->pycaret) (2023.3.post1)\n", - "Requirement already satisfied: tenacity>=6.2.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from plotly>=5.0.0->pycaret) (8.2.3)\n", - "Requirement already satisfied: dash<3.0.0,>=2.11.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from plotly-resampler>=0.8.3.1->pycaret) (2.14.2)\n", - "Requirement already satisfied: orjson<4.0.0,>=3.8.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from plotly-resampler>=0.8.3.1->pycaret) (3.9.10)\n", - "Requirement already satisfied: trace-updater>=0.0.8 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from plotly-resampler>=0.8.3.1->pycaret) (0.0.9.1)\n", - "Requirement already satisfied: tsdownsample==0.1.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from plotly-resampler>=0.8.3.1->pycaret) (0.1.2)\n", - "Requirement already satisfied: Cython!=0.29.18,!=0.29.31,>=0.29 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pmdarima!=1.8.1,<3.0.0,>=1.8.0->pycaret) (3.0.4)\n", - "Requirement already satisfied: urllib3 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pmdarima!=1.8.1,<3.0.0,>=1.8.0->pycaret) (1.26.18)\n", - "Requirement already satisfied: setuptools!=50.0.0,>=38.6.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pmdarima!=1.8.1,<3.0.0,>=1.8.0->pycaret) (68.2.2)\n", - "Requirement already satisfied: six in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pyod>=1.0.8->pycaret) (1.16.0)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from requests>=2.27.1->pycaret) (3.3.1)\n", - "Requirement already satisfied: idna<4,>=2.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from requests>=2.27.1->pycaret) (3.4)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from requests>=2.27.1->pycaret) (2023.7.22)\n", - "Requirement already satisfied: deprecated>=1.2.13 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from sktime!=0.17.1,!=0.17.2,!=0.18.0,<0.22.0,>=0.16.1->pycaret) (1.2.14)\n", - "Requirement already satisfied: scikit-base<0.6.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from sktime!=0.17.1,!=0.17.2,!=0.18.0,<0.22.0,>=0.16.1->pycaret) (0.5.2)\n", - "Requirement already satisfied: Flask<3.1,>=1.0.4 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (3.0.0)\n", - "Requirement already satisfied: Werkzeug<3.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (3.0.1)\n", - "Requirement already satisfied: dash-html-components==2.0.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (2.0.0)\n", - "Requirement already satisfied: dash-core-components==2.0.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (2.0.0)\n", - "Requirement already satisfied: dash-table==5.0.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (5.0.0)\n", - "Requirement already satisfied: typing-extensions>=4.1.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (4.8.0)\n", - "Requirement already satisfied: retrying in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (1.3.4)\n", - "Requirement already satisfied: ansi2html in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (1.9.1)\n", - "Requirement already satisfied: nest-asyncio in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (1.5.8)\n", - "Requirement already satisfied: wrapt<2,>=1.10 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from deprecated>=1.2.13->sktime!=0.17.1,!=0.17.2,!=0.18.0,<0.22.0,>=0.16.1->pycaret) (1.15.0)\n", - "Requirement already satisfied: parso<0.9.0,>=0.8.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from jedi>=0.16->ipython>=5.5.0->pycaret) (0.8.3)\n", - "Requirement already satisfied: attrs>=22.2.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=4.2.0->pycaret) (23.1.0)\n", - "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=4.2.0->pycaret) (2023.7.1)\n", - "Requirement already satisfied: referencing>=0.28.4 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=4.2.0->pycaret) (0.30.2)\n", - "Requirement already satisfied: rpds-py>=0.7.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=4.2.0->pycaret) (0.10.6)\n", - "Requirement already satisfied: ptyprocess>=0.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pexpect>4.3->ipython>=5.5.0->pycaret) (0.7.0)\n", - "Requirement already satisfied: wcwidth in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30->ipython>=5.5.0->pycaret) (0.2.8)\n", - "Requirement already satisfied: platformdirs>=2.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from jupyter-core->nbformat>=4.2.0->pycaret) (3.11.0)\n", - "Requirement already satisfied: executing>=1.2.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from stack-data->ipython>=5.5.0->pycaret) (1.2.0)\n", - "Requirement already satisfied: asttokens>=2.1.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from stack-data->ipython>=5.5.0->pycaret) (2.4.1)\n", - "Requirement already satisfied: pure-eval in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from stack-data->ipython>=5.5.0->pycaret) (0.2.2)\n", - "Requirement already satisfied: itsdangerous>=2.1.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from Flask<3.1,>=1.0.4->dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (2.1.2)\n", - "Requirement already satisfied: click>=8.1.3 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from Flask<3.1,>=1.0.4->dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (8.1.7)\n", - "Requirement already satisfied: blinker>=1.6.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from Flask<3.1,>=1.0.4->dash<3.0.0,>=2.11.0->plotly-resampler>=0.8.3.1->pycaret) (1.6.3)\n", - "Requirement already satisfied: python-dotenv in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (1.0.0)\n", - "Requirement already satisfied: ydata-profiling in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (4.6.3)\n", - "Requirement already satisfied: scipy<1.12,>=1.4.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (1.10.1)\n", - "Requirement already satisfied: pandas!=1.4.0,<3,>1.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (1.5.3)\n", - "Requirement already satisfied: matplotlib<3.9,>=3.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (3.6.0)\n", - "Requirement already satisfied: pydantic>=2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (2.5.2)\n", - "Requirement already satisfied: PyYAML<6.1,>=5.0.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (6.0.1)\n", - "Requirement already satisfied: jinja2<3.2,>=2.11.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (3.1.2)\n", - "Requirement already satisfied: visions==0.7.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from visions[type_image_path]==0.7.5->ydata-profiling) (0.7.5)\n", - "Requirement already satisfied: numpy<1.26,>=1.16.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (1.22.4)\n", - "Requirement already satisfied: htmlmin==0.1.12 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (0.1.12)\n", - "Requirement already satisfied: phik<0.13,>=0.11.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (0.12.3)\n", - "Requirement already satisfied: requests<3,>=2.24.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (2.31.0)\n", - "Requirement already satisfied: tqdm<5,>=4.48.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (4.66.1)\n", - "Requirement already satisfied: seaborn<0.13,>=0.10.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (0.12.2)\n", - "Requirement already satisfied: multimethod<2,>=1.4 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (1.10)\n", - "Requirement already satisfied: statsmodels<1,>=0.13.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (0.14.0)\n", - "Requirement already satisfied: typeguard<5,>=4.1.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (4.1.5)\n", - "Requirement already satisfied: imagehash==4.3.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (4.3.1)\n", - "Requirement already satisfied: wordcloud>=1.9.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (1.9.3)\n", - "Requirement already satisfied: dacite>=1.8 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (1.8.1)\n", - "Requirement already satisfied: numba<0.59.0,>=0.56.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from ydata-profiling) (0.57.1)\n", - "Requirement already satisfied: PyWavelets in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from imagehash==4.3.1->ydata-profiling) (1.4.1)\n", - "Requirement already satisfied: pillow in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from imagehash==4.3.1->ydata-profiling) (10.0.1)\n", - "Requirement already satisfied: attrs>=19.3.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from visions==0.7.5->visions[type_image_path]==0.7.5->ydata-profiling) (23.1.0)\n", - "Requirement already satisfied: networkx>=2.4 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from visions==0.7.5->visions[type_image_path]==0.7.5->ydata-profiling) (3.2)\n", - "Requirement already satisfied: tangled-up-in-unicode>=0.0.4 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from visions==0.7.5->visions[type_image_path]==0.7.5->ydata-profiling) (0.2.0)\n", - "\u001b[33mWARNING: visions 0.7.5 does not provide the extra 'type-image-path'\u001b[0m\u001b[33m\n", - "\u001b[0mRequirement already satisfied: MarkupSafe>=2.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from jinja2<3.2,>=2.11.1->ydata-profiling) (2.1.3)\n", - "Requirement already satisfied: contourpy>=1.0.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (1.1.1)\n", - "Requirement already satisfied: cycler>=0.10 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (0.12.1)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (4.43.1)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (1.4.5)\n", - "Requirement already satisfied: packaging>=20.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (21.3)\n", - "Requirement already satisfied: pyparsing>=2.2.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (3.1.1)\n", - "Requirement already satisfied: python-dateutil>=2.7 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (2.8.2)\n", - "Requirement already satisfied: llvmlite<0.41,>=0.40.0dev0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from numba<0.59.0,>=0.56.0->ydata-profiling) (0.40.1)\n", - "Requirement already satisfied: pytz>=2020.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pandas!=1.4.0,<3,>1.1->ydata-profiling) (2023.3.post1)\n", - "Requirement already satisfied: joblib>=0.14.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from phik<0.13,>=0.11.1->ydata-profiling) (1.3.2)\n", - "Requirement already satisfied: annotated-types>=0.4.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pydantic>=2->ydata-profiling) (0.6.0)\n", - "Requirement already satisfied: pydantic-core==2.14.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pydantic>=2->ydata-profiling) (2.14.5)\n", - "Requirement already satisfied: typing-extensions>=4.6.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pydantic>=2->ydata-profiling) (4.8.0)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from requests<3,>=2.24.0->ydata-profiling) (3.3.1)\n", - "Requirement already satisfied: idna<4,>=2.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from requests<3,>=2.24.0->ydata-profiling) (3.4)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from requests<3,>=2.24.0->ydata-profiling) (1.26.18)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from requests<3,>=2.24.0->ydata-profiling) (2023.7.22)\n", - "Requirement already satisfied: patsy>=0.5.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from statsmodels<1,>=0.13.2->ydata-profiling) (0.5.3)\n", - "Requirement already satisfied: six in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from patsy>=0.5.2->statsmodels<1,>=0.13.2->ydata-profiling) (1.16.0)\n", - "Requirement already satisfied: shap in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (0.43.0)\n", - "Requirement already satisfied: numpy in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from shap) (1.22.4)\n", - "Requirement already satisfied: scipy in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from shap) (1.10.1)\n", - "Requirement already satisfied: scikit-learn in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from shap) (1.2.2)\n", - "Requirement already satisfied: pandas in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from shap) (1.5.3)\n", - "Requirement already satisfied: tqdm>=4.27.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from shap) (4.66.1)\n", - "Requirement already satisfied: packaging>20.9 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from shap) (21.3)\n", - "Requirement already satisfied: slicer==0.0.7 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from shap) (0.0.7)\n", - "Requirement already satisfied: numba in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from shap) (0.57.1)\n", - "Requirement already satisfied: cloudpickle in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from shap) (2.2.1)\n", - "Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from packaging>20.9->shap) (3.1.1)\n", - "Requirement already satisfied: llvmlite<0.41,>=0.40.0dev0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from numba->shap) (0.40.1)\n", - "Requirement already satisfied: python-dateutil>=2.8.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pandas->shap) (2.8.2)\n", - "Requirement already satisfied: pytz>=2020.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from pandas->shap) (2023.3.post1)\n", - "Requirement already satisfied: joblib>=1.1.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from scikit-learn->shap) (1.3.2)\n", - "Requirement already satisfied: threadpoolctl>=2.0.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from scikit-learn->shap) (3.2.0)\n", - "Requirement already satisfied: six>=1.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.10/site-packages (from python-dateutil>=2.8.1->pandas->shap) (1.16.0)\n" + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0mRequirement already satisfied: pycaret in /opt/homebrew/lib/python3.11/site-packages (3.2.0)\n", + "Requirement already satisfied: category-encoders>=2.4.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (2.6.3)\n", + "Requirement already satisfied: cloudpickle in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (3.0.0)\n", + "Requirement already satisfied: deprecation>=2.1.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (2.1.0)\n", + "Requirement already satisfied: imbalanced-learn>=0.8.1 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (0.11.0)\n", + "Requirement already satisfied: importlib-metadata>=4.12.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (6.8.0)\n", + "Requirement already satisfied: ipython>=5.5.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (8.20.0)\n", + "Requirement already satisfied: ipywidgets>=7.6.5 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (8.1.1)\n", + "Requirement already satisfied: jinja2>=1.2 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (3.1.2)\n", + "Requirement already satisfied: joblib>=1.2.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (1.3.2)\n", + "Requirement already satisfied: kaleido>=0.2.1 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (0.2.1)\n", + "Requirement already satisfied: lightgbm>=3.0.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (4.2.0)\n", + "Requirement already satisfied: markupsafe>=2.0.1 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (2.1.3)\n", + "Requirement already satisfied: matplotlib<=3.6,>=3.3.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (3.6.0)\n", + "Requirement already satisfied: nbformat>=4.2.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (5.9.2)\n", + "Requirement already satisfied: numba>=0.55.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (0.58.1)\n", + "Requirement already satisfied: numpy<1.27,>=1.21 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (1.25.2)\n", + "Requirement already satisfied: pandas<2.0.0,>=1.3.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (1.5.3)\n", + "Requirement already satisfied: plotly-resampler>=0.8.3.1 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (0.9.2)\n", + "Requirement already satisfied: plotly>=5.0.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (5.18.0)\n", + "Requirement already satisfied: pmdarima!=1.8.1,<3.0.0,>=1.8.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (2.0.4)\n", + "Requirement already satisfied: psutil>=5.9.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (5.9.6)\n", + "Requirement already satisfied: pyod>=1.0.8 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (1.1.2)\n", + "Requirement already satisfied: requests>=2.27.1 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (2.31.0)\n", + "Requirement already satisfied: schemdraw==0.15 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (0.15)\n", + "Requirement already satisfied: scikit-learn<1.3.0,>=1.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (1.2.2)\n", + "Requirement already satisfied: scikit-plot>=0.3.7 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (0.3.7)\n", + "Requirement already satisfied: scipy~=1.10.1 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (1.10.1)\n", + "Requirement already satisfied: sktime!=0.17.1,!=0.17.2,!=0.18.0,<0.22.0,>=0.16.1 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (0.21.1)\n", + "Requirement already satisfied: statsmodels>=0.12.1 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (0.14.1)\n", + "Requirement already satisfied: tbats>=1.1.3 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (1.1.3)\n", + "Requirement already satisfied: tqdm>=4.62.0 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (4.66.1)\n", + "Requirement already satisfied: xxhash in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (3.4.1)\n", + "Requirement already satisfied: yellowbrick>=1.4 in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (1.5)\n", + "Requirement already satisfied: wurlitzer in /opt/homebrew/lib/python3.11/site-packages (from pycaret) (3.0.3)\n", + "Requirement already satisfied: patsy>=0.5.1 in /opt/homebrew/lib/python3.11/site-packages (from category-encoders>=2.4.0->pycaret) (0.5.6)\n", + "Requirement already satisfied: packaging in /opt/homebrew/lib/python3.11/site-packages (from deprecation>=2.1.0->pycaret) (23.2)\n", + "Requirement already satisfied: threadpoolctl>=2.0.0 in /opt/homebrew/lib/python3.11/site-packages (from imbalanced-learn>=0.8.1->pycaret) (3.2.0)\n", + "Requirement already satisfied: zipp>=0.5 in /opt/homebrew/lib/python3.11/site-packages (from importlib-metadata>=4.12.0->pycaret) (3.17.0)\n", + "Requirement already satisfied: decorator in /opt/homebrew/lib/python3.11/site-packages (from ipython>=5.5.0->pycaret) (5.1.1)\n", + "Requirement already satisfied: jedi>=0.16 in /opt/homebrew/lib/python3.11/site-packages (from ipython>=5.5.0->pycaret) (0.19.1)\n", + "Requirement already satisfied: matplotlib-inline in /opt/homebrew/lib/python3.11/site-packages (from ipython>=5.5.0->pycaret) (0.1.6)\n", + "Requirement already satisfied: prompt-toolkit<3.1.0,>=3.0.41 in /opt/homebrew/lib/python3.11/site-packages (from ipython>=5.5.0->pycaret) (3.0.43)\n", + "Requirement already satisfied: pygments>=2.4.0 in /opt/homebrew/lib/python3.11/site-packages (from ipython>=5.5.0->pycaret) (2.17.2)\n", + "Requirement already satisfied: stack-data in /opt/homebrew/lib/python3.11/site-packages (from ipython>=5.5.0->pycaret) (0.6.3)\n", + "Requirement already satisfied: traitlets>=5 in /opt/homebrew/lib/python3.11/site-packages (from ipython>=5.5.0->pycaret) (5.14.1)\n", + "Requirement already satisfied: pexpect>4.3 in /opt/homebrew/lib/python3.11/site-packages (from ipython>=5.5.0->pycaret) (4.9.0)\n", + "Requirement already satisfied: comm>=0.1.3 in /opt/homebrew/lib/python3.11/site-packages (from ipywidgets>=7.6.5->pycaret) (0.2.1)\n", + "Requirement already satisfied: widgetsnbextension~=4.0.9 in /opt/homebrew/lib/python3.11/site-packages (from ipywidgets>=7.6.5->pycaret) (4.0.9)\n", + "Requirement already satisfied: jupyterlab-widgets~=3.0.9 in /opt/homebrew/lib/python3.11/site-packages (from ipywidgets>=7.6.5->pycaret) (3.0.9)\n", + "Requirement already satisfied: contourpy>=1.0.1 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (1.1.1)\n", + "Requirement already satisfied: cycler>=0.10 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (0.12.0)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (4.43.1)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (1.4.5)\n", + "Requirement already satisfied: pillow>=6.2.0 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (10.0.1)\n", + "Requirement already satisfied: pyparsing>=2.2.1 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (3.1.1)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<=3.6,>=3.3.0->pycaret) (2.8.2)\n", + "Requirement already satisfied: fastjsonschema in /opt/homebrew/lib/python3.11/site-packages (from nbformat>=4.2.0->pycaret) (2.19.1)\n", + "Requirement already satisfied: jsonschema>=2.6 in /opt/homebrew/lib/python3.11/site-packages (from nbformat>=4.2.0->pycaret) (4.19.1)\n", + "Requirement already satisfied: jupyter-core in /opt/homebrew/lib/python3.11/site-packages (from nbformat>=4.2.0->pycaret) (5.7.1)\n", + "Requirement already satisfied: llvmlite<0.42,>=0.41.0dev0 in /opt/homebrew/lib/python3.11/site-packages (from numba>=0.55.0->pycaret) (0.41.1)\n", + "Requirement already satisfied: pytz>=2020.1 in /opt/homebrew/lib/python3.11/site-packages (from pandas<2.0.0,>=1.3.0->pycaret) (2023.3.post1)\n", + "Requirement already satisfied: tenacity>=6.2.0 in /opt/homebrew/lib/python3.11/site-packages (from plotly>=5.0.0->pycaret) (8.2.3)\n", + "Requirement already satisfied: dash>=2.9.0 in /opt/homebrew/lib/python3.11/site-packages (from plotly-resampler>=0.8.3.1->pycaret) (2.14.2)\n", + "Requirement already satisfied: orjson<4.0.0,>=3.8.0 in /opt/homebrew/lib/python3.11/site-packages (from plotly-resampler>=0.8.3.1->pycaret) (3.9.10)\n", + "Requirement already satisfied: tsdownsample==0.1.2 in /opt/homebrew/lib/python3.11/site-packages (from plotly-resampler>=0.8.3.1->pycaret) (0.1.2)\n", + "Requirement already satisfied: Cython!=0.29.18,!=0.29.31,>=0.29 in /opt/homebrew/lib/python3.11/site-packages (from pmdarima!=1.8.1,<3.0.0,>=1.8.0->pycaret) (3.0.8)\n", + "Requirement already satisfied: urllib3 in /Users/ethan.charlton-harrow/Library/Python/3.11/lib/python/site-packages (from pmdarima!=1.8.1,<3.0.0,>=1.8.0->pycaret) (1.26.18)\n", + "Requirement already satisfied: setuptools!=50.0.0,>=38.6.0 in /opt/homebrew/lib/python3.11/site-packages (from pmdarima!=1.8.1,<3.0.0,>=1.8.0->pycaret) (68.2.2)\n", + "Requirement already satisfied: six in /opt/homebrew/lib/python3.11/site-packages (from pyod>=1.0.8->pycaret) (1.16.0)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.27.1->pycaret) (3.3.0)\n", + "Requirement already satisfied: idna<4,>=2.5 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.27.1->pycaret) (3.4)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.27.1->pycaret) (2023.11.17)\n", + "Requirement already satisfied: deprecated>=1.2.13 in /opt/homebrew/lib/python3.11/site-packages (from sktime!=0.17.1,!=0.17.2,!=0.18.0,<0.22.0,>=0.16.1->pycaret) (1.2.14)\n", + "Requirement already satisfied: scikit-base<0.6.0 in /opt/homebrew/lib/python3.11/site-packages (from sktime!=0.17.1,!=0.17.2,!=0.18.0,<0.22.0,>=0.16.1->pycaret) (0.5.2)\n", + "Requirement already satisfied: Flask<3.1,>=1.0.4 in /opt/homebrew/lib/python3.11/site-packages (from dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (3.0.0)\n", + "Requirement already satisfied: Werkzeug<3.1 in /opt/homebrew/lib/python3.11/site-packages (from dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (3.0.1)\n", + "Requirement already satisfied: dash-html-components==2.0.0 in /opt/homebrew/lib/python3.11/site-packages (from dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (2.0.0)\n", + "Requirement already satisfied: dash-core-components==2.0.0 in /opt/homebrew/lib/python3.11/site-packages (from dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (2.0.0)\n", + "Requirement already satisfied: dash-table==5.0.0 in /opt/homebrew/lib/python3.11/site-packages (from dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (5.0.0)\n", + "Requirement already satisfied: typing-extensions>=4.1.1 in /opt/homebrew/lib/python3.11/site-packages (from dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (4.8.0)\n", + "Requirement already satisfied: retrying in /opt/homebrew/lib/python3.11/site-packages (from dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (1.3.4)\n", + "Requirement already satisfied: ansi2html in /opt/homebrew/lib/python3.11/site-packages (from dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (1.9.1)\n", + "Requirement already satisfied: nest-asyncio in /opt/homebrew/lib/python3.11/site-packages (from dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (1.5.9)\n", + "Requirement already satisfied: wrapt<2,>=1.10 in /opt/homebrew/lib/python3.11/site-packages (from deprecated>=1.2.13->sktime!=0.17.1,!=0.17.2,!=0.18.0,<0.22.0,>=0.16.1->pycaret) (1.16.0)\n", + "Requirement already satisfied: parso<0.9.0,>=0.8.3 in /opt/homebrew/lib/python3.11/site-packages (from jedi>=0.16->ipython>=5.5.0->pycaret) (0.8.3)\n", + "Requirement already satisfied: attrs>=22.2.0 in /opt/homebrew/lib/python3.11/site-packages (from jsonschema>=2.6->nbformat>=4.2.0->pycaret) (23.1.0)\n", + "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /opt/homebrew/lib/python3.11/site-packages (from jsonschema>=2.6->nbformat>=4.2.0->pycaret) (2023.7.1)\n", + "Requirement already satisfied: referencing>=0.28.4 in /opt/homebrew/lib/python3.11/site-packages (from jsonschema>=2.6->nbformat>=4.2.0->pycaret) (0.30.2)\n", + "Requirement already satisfied: rpds-py>=0.7.1 in /opt/homebrew/lib/python3.11/site-packages (from jsonschema>=2.6->nbformat>=4.2.0->pycaret) (0.10.6)\n", + "Requirement already satisfied: ptyprocess>=0.5 in /opt/homebrew/lib/python3.11/site-packages (from pexpect>4.3->ipython>=5.5.0->pycaret) (0.7.0)\n", + "Requirement already satisfied: wcwidth in /Users/ethan.charlton-harrow/Library/Python/3.11/lib/python/site-packages (from prompt-toolkit<3.1.0,>=3.0.41->ipython>=5.5.0->pycaret) (0.1.9)\n", + "Requirement already satisfied: platformdirs>=2.5 in /opt/homebrew/lib/python3.11/site-packages (from jupyter-core->nbformat>=4.2.0->pycaret) (4.1.0)\n", + "Requirement already satisfied: executing>=1.2.0 in /opt/homebrew/lib/python3.11/site-packages (from stack-data->ipython>=5.5.0->pycaret) (2.0.1)\n", + "Requirement already satisfied: asttokens>=2.1.0 in /opt/homebrew/lib/python3.11/site-packages (from stack-data->ipython>=5.5.0->pycaret) (2.4.1)\n", + "Requirement already satisfied: pure-eval in /opt/homebrew/lib/python3.11/site-packages (from stack-data->ipython>=5.5.0->pycaret) (0.2.2)\n", + "Requirement already satisfied: itsdangerous>=2.1.2 in /opt/homebrew/lib/python3.11/site-packages (from Flask<3.1,>=1.0.4->dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (2.1.2)\n", + "Requirement already satisfied: click>=8.1.3 in /opt/homebrew/lib/python3.11/site-packages (from Flask<3.1,>=1.0.4->dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (8.1.7)\n", + "Requirement already satisfied: blinker>=1.6.2 in /opt/homebrew/lib/python3.11/site-packages (from Flask<3.1,>=1.0.4->dash>=2.9.0->plotly-resampler>=0.8.3.1->pycaret) (1.6.3)\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.3.2\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython3.11 -m pip install --upgrade pip\u001b[0m\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0mCollecting python-dotenv\n", + " Downloading python_dotenv-1.0.0-py3-none-any.whl (19 kB)\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0mInstalling collected packages: python-dotenv\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0mSuccessfully installed python-dotenv-1.0.0\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.3.2\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython3.11 -m pip install --upgrade pip\u001b[0m\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0mCollecting ydata-profiling\n", + " Downloading ydata_profiling-4.6.4-py2.py3-none-any.whl.metadata (20 kB)\n", + "Requirement already satisfied: scipy<1.12,>=1.4.1 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (1.10.1)\n", + "Requirement already satisfied: pandas!=1.4.0,<3,>1.1 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (1.5.3)\n", + "Requirement already satisfied: matplotlib<3.9,>=3.2 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (3.6.0)\n", + "Requirement already satisfied: pydantic>=2 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (2.4.2)\n", + "Requirement already satisfied: PyYAML<6.1,>=5.0.0 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (6.0.1)\n", + "Requirement already satisfied: jinja2<3.2,>=2.11.1 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (3.1.2)\n", + "Collecting visions==0.7.5 (from visions[type_image_path]==0.7.5->ydata-profiling)\n", + " Downloading visions-0.7.5-py3-none-any.whl (102 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m102.7/102.7 kB\u001b[0m \u001b[31m4.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: numpy<1.26,>=1.16.0 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (1.25.2)\n", + "Requirement already satisfied: htmlmin==0.1.12 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (0.1.12)\n", + "Requirement already satisfied: phik<0.13,>=0.11.1 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (0.12.3)\n", + "Requirement already satisfied: requests<3,>=2.24.0 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (2.31.0)\n", + "Requirement already satisfied: tqdm<5,>=4.48.2 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (4.66.1)\n", + "Collecting seaborn<0.13,>=0.10.1 (from ydata-profiling)\n", + " Downloading seaborn-0.12.2-py3-none-any.whl (293 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m293.3/293.3 kB\u001b[0m \u001b[31m6.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: multimethod<2,>=1.4 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (1.10)\n", + "Requirement already satisfied: statsmodels<1,>=0.13.2 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (0.14.1)\n", + "Collecting typeguard<5,>=4.1.2 (from ydata-profiling)\n", + " Downloading typeguard-4.1.5-py3-none-any.whl.metadata (3.7 kB)\n", + "Requirement already satisfied: imagehash==4.3.1 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (4.3.1)\n", + "Collecting wordcloud>=1.9.1 (from ydata-profiling)\n", + " Downloading wordcloud-1.9.3-cp311-cp311-macosx_11_0_arm64.whl.metadata (3.4 kB)\n", + "Collecting dacite>=1.8 (from ydata-profiling)\n", + " Downloading dacite-1.8.1-py3-none-any.whl.metadata (15 kB)\n", + "Requirement already satisfied: numba<0.59.0,>=0.56.0 in /opt/homebrew/lib/python3.11/site-packages (from ydata-profiling) (0.58.1)\n", + "Requirement already satisfied: PyWavelets in /opt/homebrew/lib/python3.11/site-packages (from imagehash==4.3.1->ydata-profiling) (1.4.1)\n", + "Requirement already satisfied: pillow in /opt/homebrew/lib/python3.11/site-packages (from imagehash==4.3.1->ydata-profiling) (10.0.1)\n", + "Requirement already satisfied: attrs>=19.3.0 in /opt/homebrew/lib/python3.11/site-packages (from visions==0.7.5->visions[type_image_path]==0.7.5->ydata-profiling) (23.1.0)\n", + "Requirement already satisfied: networkx>=2.4 in /opt/homebrew/lib/python3.11/site-packages (from visions==0.7.5->visions[type_image_path]==0.7.5->ydata-profiling) (3.1)\n", + "Requirement already satisfied: tangled-up-in-unicode>=0.0.4 in /opt/homebrew/lib/python3.11/site-packages (from visions==0.7.5->visions[type_image_path]==0.7.5->ydata-profiling) (0.2.0)\n", + "Requirement already satisfied: MarkupSafe>=2.0 in /opt/homebrew/lib/python3.11/site-packages (from jinja2<3.2,>=2.11.1->ydata-profiling) (2.1.3)\n", + "Requirement already satisfied: contourpy>=1.0.1 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (1.1.1)\n", + "Requirement already satisfied: cycler>=0.10 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (0.12.0)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (4.43.1)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (1.4.5)\n", + "Requirement already satisfied: packaging>=20.0 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (23.2)\n", + "Requirement already satisfied: pyparsing>=2.2.1 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (3.1.1)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /opt/homebrew/lib/python3.11/site-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (2.8.2)\n", + "Requirement already satisfied: llvmlite<0.42,>=0.41.0dev0 in /opt/homebrew/lib/python3.11/site-packages (from numba<0.59.0,>=0.56.0->ydata-profiling) (0.41.1)\n", + "Requirement already satisfied: pytz>=2020.1 in /opt/homebrew/lib/python3.11/site-packages (from pandas!=1.4.0,<3,>1.1->ydata-profiling) (2023.3.post1)\n", + "Requirement already satisfied: joblib>=0.14.1 in /opt/homebrew/lib/python3.11/site-packages (from phik<0.13,>=0.11.1->ydata-profiling) (1.3.2)\n", + "Requirement already satisfied: annotated-types>=0.4.0 in /opt/homebrew/lib/python3.11/site-packages (from pydantic>=2->ydata-profiling) (0.6.0)\n", + "Requirement already satisfied: pydantic-core==2.10.1 in /opt/homebrew/lib/python3.11/site-packages (from pydantic>=2->ydata-profiling) (2.10.1)\n", + "Requirement already satisfied: typing-extensions>=4.6.1 in /opt/homebrew/lib/python3.11/site-packages (from pydantic>=2->ydata-profiling) (4.8.0)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/homebrew/lib/python3.11/site-packages (from requests<3,>=2.24.0->ydata-profiling) (3.3.0)\n", + "Requirement already satisfied: idna<4,>=2.5 in /opt/homebrew/lib/python3.11/site-packages (from requests<3,>=2.24.0->ydata-profiling) (3.4)\n", + "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/ethan.charlton-harrow/Library/Python/3.11/lib/python/site-packages (from requests<3,>=2.24.0->ydata-profiling) (1.26.18)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /opt/homebrew/lib/python3.11/site-packages (from requests<3,>=2.24.0->ydata-profiling) (2023.11.17)\n", + "Requirement already satisfied: patsy>=0.5.4 in /opt/homebrew/lib/python3.11/site-packages (from statsmodels<1,>=0.13.2->ydata-profiling) (0.5.6)\n", + "Requirement already satisfied: six in /opt/homebrew/lib/python3.11/site-packages (from patsy>=0.5.4->statsmodels<1,>=0.13.2->ydata-profiling) (1.16.0)\n", + "Downloading ydata_profiling-4.6.4-py2.py3-none-any.whl (357 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m357.8/357.8 kB\u001b[0m \u001b[31m2.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[?25hDownloading dacite-1.8.1-py3-none-any.whl (14 kB)\n", + "Downloading typeguard-4.1.5-py3-none-any.whl (34 kB)\n", + "Downloading wordcloud-1.9.3-cp311-cp311-macosx_11_0_arm64.whl (168 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m168.3/168.3 kB\u001b[0m \u001b[31m2.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", + "\u001b[?25h\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0mInstalling collected packages: typeguard, dacite, wordcloud, visions, seaborn, ydata-profiling\n", + " Attempting uninstall: visions\n", + "\u001b[33m WARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33m WARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33m WARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m Found existing installation: visions 0.7.4\n", + " Uninstalling visions-0.7.4:\n", + " Successfully uninstalled visions-0.7.4\n", + " Attempting uninstall: seaborn\n", + "\u001b[33m WARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33m WARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33m WARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m Found existing installation: seaborn 0.13.0\n", + " Uninstalling seaborn-0.13.0:\n", + " Successfully uninstalled seaborn-0.13.0\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n", + "pandas-profiling 3.2.0 requires joblib~=1.1.0, but you have joblib 1.3.2 which is incompatible.\n", + "pandas-profiling 3.2.0 requires visions[type_image_path]==0.7.4, but you have visions 0.7.5 which is incompatible.\u001b[0m\u001b[31m\n", + "\u001b[0mSuccessfully installed dacite-1.8.1 seaborn-0.12.2 typeguard-4.1.5 visions-0.7.5 wordcloud-1.9.3 ydata-profiling-4.6.4\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.3.2\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython3.11 -m pip install --upgrade pip\u001b[0m\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0mCollecting shap\n", + " Downloading shap-0.44.0-cp311-cp311-macosx_11_0_arm64.whl.metadata (24 kB)\n", + "Requirement already satisfied: numpy in /opt/homebrew/lib/python3.11/site-packages (from shap) (1.25.2)\n", + "Requirement already satisfied: scipy in /opt/homebrew/lib/python3.11/site-packages (from shap) (1.10.1)\n", + "Requirement already satisfied: scikit-learn in /opt/homebrew/lib/python3.11/site-packages (from shap) (1.2.2)\n", + "Requirement already satisfied: pandas in /opt/homebrew/lib/python3.11/site-packages (from shap) (1.5.3)\n", + "Requirement already satisfied: tqdm>=4.27.0 in /opt/homebrew/lib/python3.11/site-packages (from shap) (4.66.1)\n", + "Requirement already satisfied: packaging>20.9 in /opt/homebrew/lib/python3.11/site-packages (from shap) (23.2)\n", + "Collecting slicer==0.0.7 (from shap)\n", + " Downloading slicer-0.0.7-py3-none-any.whl (14 kB)\n", + "Requirement already satisfied: numba in /opt/homebrew/lib/python3.11/site-packages (from shap) (0.58.1)\n", + "Requirement already satisfied: cloudpickle in /opt/homebrew/lib/python3.11/site-packages (from shap) (3.0.0)\n", + "Requirement already satisfied: llvmlite<0.42,>=0.41.0dev0 in /opt/homebrew/lib/python3.11/site-packages (from numba->shap) (0.41.1)\n", + "Requirement already satisfied: python-dateutil>=2.8.1 in /opt/homebrew/lib/python3.11/site-packages (from pandas->shap) (2.8.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /opt/homebrew/lib/python3.11/site-packages (from pandas->shap) (2023.3.post1)\n", + "Requirement already satisfied: joblib>=1.1.1 in /opt/homebrew/lib/python3.11/site-packages (from scikit-learn->shap) (1.3.2)\n", + "Requirement already satisfied: threadpoolctl>=2.0.0 in /opt/homebrew/lib/python3.11/site-packages (from scikit-learn->shap) (3.2.0)\n", + "Requirement already satisfied: six>=1.5 in /opt/homebrew/lib/python3.11/site-packages (from python-dateutil>=2.8.1->pandas->shap) (1.16.0)\n", + "Downloading shap-0.44.0-cp311-cp311-macosx_11_0_arm64.whl (445 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m446.0/446.0 kB\u001b[0m \u001b[31m6.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", + "\u001b[?25h\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0mInstalling collected packages: slicer, shap\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/idna-3.6.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0mSuccessfully installed shap-0.44.0 slicer-0.0.7\n", + "\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/charset_normalizer-3.3.2.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/urllib3-2.1.0.dist-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n", + "\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.3.2\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython3.11 -m pip install --upgrade pip\u001b[0m\n" ] } ], @@ -224,18 +343,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sagemaker.config INFO - Not applying SDK defaults from location: /etc/xdg/sagemaker/config.yaml\n", - "sagemaker.config INFO - Not applying SDK defaults from location: /home/ec2-user/.config/sagemaker/config.yaml\n" - ] - } - ], + "outputs": [], "source": [ "import os\n", "from sagemaker import get_execution_role\n", @@ -248,7 +358,8 @@ "from finalize_and_save_model import finalize_and_save_model\n", "from delete_sagemaker_endpoint import delete_sagemaker_endpoint\n", "from ydata_profiling import ProfileReport\n", - "import shap\n" + "import shap\n", + "import pandas as pd" ] }, { @@ -263,16 +374,14 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "sagemaker.config INFO - Not applying SDK defaults from location: /etc/xdg/sagemaker/config.yaml\n", - "sagemaker.config INFO - Not applying SDK defaults from location: /home/ec2-user/.config/sagemaker/config.yaml\n", - "streaming-data-platform-ml-data/ethan_data.csv classification y classification-proba-endpoint banking-classification s3://streaming-data-platform-ml-data/ethan_data.csv ml.m4.xlarge 135544376709.dkr.ecr.eu-west-1.amazonaws.com/mlops-classification-repo:latest AUC\n" + "None None None None None s3://None None None None\n" ] } ], @@ -293,8 +402,10 @@ "inference_instance_count = int(os.getenv(\"inference_instance_count\"))\n", "image_uri = os.getenv(\"ecr_repo_uri\")\n", "tuning_metric = os.getenv(\"tuning_metric\")\n", + "#TODO change \n", + "os.environ['preprocessing_script_path'] = 'filename_path'\n", "\n", - "print(data_location_s3, algorithm_choice, target, endpoint_name, model_name, data_location, instance_type, image_uri, tuning_metric)\n" + "print(data_location_s3, algorithm_choice, target, endpoint_name, model_name, data_location, instance_type, image_uri, tuning_metric)" ] }, { @@ -306,21 +417,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Your installed version of s3fs is very old and known to cause\n", - "severe performance issues, see also https://github.com/dask/dask/issues/10276\n", - "\n", - "To fix, you should specify a lower version bound on s3fs, or\n", - "update the current installation.\n", - "\n" - ] - }, { "data": { "text/html": [ @@ -342,86 +441,153 @@ " \n", " \n", " \n", + " Unnamed: 0\n", " age\n", " job\n", + " marital\n", " education\n", " default\n", " balance\n", " housing\n", " loan\n", + " contact\n", + " day\n", + " month\n", + " duration\n", + " campaign\n", + " pdays\n", + " previous\n", + " poutcome\n", " y\n", " \n", " \n", " \n", " \n", " 0\n", - " 32\n", - " 7\n", - " 2\n", - " 1\n", - " -238\n", - " 1\n", " 0\n", + " 58\n", + " management\n", + " married\n", + " tertiary\n", + " no\n", + " 2143\n", + " yes\n", + " no\n", + " unknown\n", + " 5\n", + " may\n", + " 261\n", + " 1\n", + " -1\n", " 0\n", + " unknown\n", + " no\n", " \n", " \n", " 1\n", - " 34\n", - " 4\n", - " 2\n", - " 0\n", - " -478\n", " 1\n", + " 44\n", + " technician\n", + " single\n", + " secondary\n", + " no\n", + " 29\n", + " yes\n", + " no\n", + " unknown\n", + " 5\n", + " may\n", + " 151\n", " 1\n", + " -1\n", " 0\n", + " unknown\n", + " no\n", " \n", " \n", " 2\n", - " 32\n", - " 3\n", " 2\n", - " 0\n", - " 266\n", + " 33\n", + " entrepreneur\n", + " married\n", + " secondary\n", + " no\n", + " 2\n", + " yes\n", + " yes\n", + " unknown\n", + " 5\n", + " may\n", + " 76\n", " 1\n", + " -1\n", " 0\n", - " 0\n", + " unknown\n", + " no\n", " \n", " \n", " 3\n", - " 36\n", - " 7\n", - " 2\n", - " 1\n", - " 13\n", - " 0\n", + " 3\n", + " 47\n", + " blue-collar\n", + " married\n", + " unknown\n", + " no\n", + " 1506\n", + " yes\n", + " no\n", + " unknown\n", + " 5\n", + " may\n", + " 92\n", " 1\n", + " -1\n", " 0\n", + " unknown\n", + " no\n", " \n", " \n", " 4\n", - " 23\n", - " 11\n", - " 2\n", - " 0\n", - " 486\n", - " 0\n", - " 0\n", + " 4\n", + " 33\n", + " unknown\n", + " single\n", + " unknown\n", + " no\n", + " 1\n", + " no\n", + " no\n", + " unknown\n", + " 5\n", + " may\n", + " 198\n", + " 1\n", + " -1\n", " 0\n", + " unknown\n", + " no\n", " \n", " \n", "\n", "" ], "text/plain": [ - " age job education default balance housing loan y\n", - "0 32 7 2 1 -238 1 0 0\n", - "1 34 4 2 0 -478 1 1 0\n", - "2 32 3 2 0 266 1 0 0\n", - "3 36 7 2 1 13 0 1 0\n", - "4 23 11 2 0 486 0 0 0" + " Unnamed: 0 age job marital education default balance housing \\\n", + "0 0 58 management married tertiary no 2143 yes \n", + "1 1 44 technician single secondary no 29 yes \n", + "2 2 33 entrepreneur married secondary no 2 yes \n", + "3 3 47 blue-collar married unknown no 1506 yes \n", + "4 4 33 unknown single unknown no 1 no \n", + "\n", + " loan contact day month duration campaign pdays previous poutcome y \n", + "0 no unknown 5 may 261 1 -1 0 unknown no \n", + "1 no unknown 5 may 151 1 -1 0 unknown no \n", + "2 yes unknown 5 may 76 1 -1 0 unknown no \n", + "3 no unknown 5 may 92 1 -1 0 unknown no \n", + "4 no unknown 5 may 198 1 -1 0 unknown no " ] }, - "execution_count": 4, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -441,64 +607,19 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 24, "metadata": {}, "outputs": [ { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "cd0eeb9e5943413eb2a07921ad25a2c2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Summarize dataset: 0%| | 0/5 [00:00 1\u001b[0m profile \u001b[38;5;241m=\u001b[39m \u001b[43mProfileReport\u001b[49m(\n\u001b[1;32m 2\u001b[0m df,\n\u001b[1;32m 3\u001b[0m sort\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 4\u001b[0m html\u001b[38;5;241m=\u001b[39m{\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstyle\u001b[39m\u001b[38;5;124m\"\u001b[39m: {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfull_width\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;28;01mTrue\u001b[39;00m}},\n\u001b[1;32m 5\u001b[0m title\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mData Exploration\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 6\u001b[0m explorative\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m 7\u001b[0m )\n\u001b[1;32m 8\u001b[0m profile\u001b[38;5;241m.\u001b[39mto_widgets()\n", + "\u001b[0;31mNameError\u001b[0m: name 'ProfileReport' is not defined" + ] } ], "source": [ @@ -512,68 +633,151 @@ "profile.to_widgets()\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

6. Data Cleaning and Feature Engineering Placeholder

" + ] + }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - " age job education default balance housing loan y\n", - "0 46 7 1 0 1666 1 0 0\n", - "1 30 7 2 0 3532 1 0 0\n", - "2 37 2 3 0 2905 1 0 1\n", - "3 37 3 2 0 -797 1 0 1\n", - "4 92 8 4 0 775 0 0 1\n", - "... ... ... ... ... ... ... ... ..\n", - "44649 37 3 2 0 588 1 0 0\n", - "44650 41 4 2 0 239 1 0 0\n", - "44651 65 8 1 0 543 0 0 1\n", - "44652 50 2 2 0 1716 1 0 0\n", - "44653 40 2 3 0 0 0 0 1\n", + " Unnamed: 0 age education balance day month duration campaign \\\n", + "0 0 58 2 2143 5 8 261 1 \n", + "1 1 44 1 29 5 8 151 1 \n", + "2 2 33 1 2 5 8 76 1 \n", + "3 3 47 3 1506 5 8 92 1 \n", + "4 4 33 3 1 5 8 198 1 \n", + "... ... ... ... ... ... ... ... ... \n", + "79839 41749 33 1 1222 9 10 348 1 \n", + "79840 40301 30 1 444 16 6 195 2 \n", + "79841 41479 38 1 1844 7 11 245 1 \n", + "79842 31045 58 1 37 11 3 155 1 \n", + "79843 30566 58 2 3355 5 3 330 4 \n", "\n", - "[44654 rows x 8 columns] age job education default balance housing loan y\n", - "44654 35 7 4 0 2298 0 0 0\n", - "44655 31 5 2 0 132 0 0 0\n", - "44656 50 4 2 0 1375 0 0 1\n", - "44657 30 1 3 0 734 1 0 0\n", - "44658 36 4 2 0 1305 1 0 1\n", - "... ... ... ... ... ... ... ... ..\n", - "55813 42 2 3 0 -380 1 0 0\n", - "55814 18 11 1 0 608 0 0 1\n", - "55815 40 7 1 0 105 1 0 0\n", - "55816 31 2 2 0 4150 1 0 1\n", - "55817 35 2 2 0 910 0 0 0\n", + " pdays previous job_admin. job_blue-collar job_entrepreneur \\\n", + "0 -1 0 0 0 0 \n", + "1 -1 0 0 0 0 \n", + "2 -1 0 0 0 1 \n", + "3 -1 0 0 1 0 \n", + "4 -1 0 0 0 0 \n", + "... ... ... ... ... ... \n", + "79839 135 1 0 0 0 \n", + "79840 -1 0 0 0 0 \n", + "79841 62 0 0 0 0 \n", + "79842 -1 0 0 0 0 \n", + "79843 -1 0 0 0 0 \n", "\n", - "[11164 rows x 8 columns]\n" + " job_housemaid job_management job_retired job_self-employed \\\n", + "0 0 1 0 0 \n", + "1 0 0 0 0 \n", + "2 0 0 0 0 \n", + "3 0 0 0 0 \n", + "4 0 0 0 0 \n", + "... ... ... ... ... \n", + "79839 0 0 0 0 \n", + "79840 0 0 0 0 \n", + "79841 0 0 0 0 \n", + "79842 0 0 0 0 \n", + "79843 0 0 0 0 \n", + "\n", + " job_services job_student job_technician job_unemployed \\\n", + "0 0 0 0 0 \n", + "1 0 0 1 0 \n", + "2 0 0 0 0 \n", + "3 0 0 0 0 \n", + "4 0 0 0 0 \n", + "... ... ... ... ... \n", + "79839 0 0 0 0 \n", + "79840 0 0 0 0 \n", + "79841 0 0 0 0 \n", + "79842 0 0 0 0 \n", + "79843 0 0 0 0 \n", + "\n", + " marital_divorced marital_married marital_single contact_cellular \\\n", + "0 0 1 0 0 \n", + "1 0 0 1 0 \n", + "2 0 1 0 0 \n", + "3 0 1 0 0 \n", + "4 0 0 1 0 \n", + "... ... ... ... ... \n", + "79839 0 0 0 0 \n", + "79840 0 0 0 1 \n", + "79841 0 0 0 1 \n", + "79842 0 0 0 1 \n", + "79843 0 0 0 1 \n", + "\n", + " contact_telephone default_no default_yes housing_no housing_yes \\\n", + "0 0 1 0 0 1 \n", + "1 0 1 0 0 1 \n", + "2 0 1 0 0 1 \n", + "3 0 1 0 0 1 \n", + "4 0 1 0 1 0 \n", + "... ... ... ... ... ... \n", + "79839 0 1 0 1 0 \n", + "79840 0 1 0 0 0 \n", + "79841 0 1 0 1 0 \n", + "79842 0 1 0 1 0 \n", + "79843 0 1 0 1 0 \n", + "\n", + " loan_no loan_yes y \n", + "0 1 0 0 \n", + "1 1 0 0 \n", + "2 0 1 0 \n", + "3 1 0 0 \n", + "4 1 0 0 \n", + "... ... ... .. \n", + "79839 1 0 1 \n", + "79840 0 0 1 \n", + "79841 1 0 1 \n", + "79842 1 0 1 \n", + "79843 1 0 1 \n", + "\n", + "[79844 rows x 33 columns]\n" ] } ], "source": [ - "# Split and shuffle data\n", - "train_data, test_data = split_data(df, shuffle=True)\n", - "print(train_data, test_data)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "

6. Data Cleaning and Feature Engineering Placeholder

\n" + "#TODO tidy up\n", + "data_processing_path = os.getenv(\"data_processing\")\n", + "\n", + "if data_processing_path != \"None\":\n", + " try:\n", + " from preprocess_data import preprocess_data\n", + " df = preprocess_data(df)\n", + " if isinstance(df, pd.DataFrame):\n", + " print(\"The function returned a DataFrame.\")\n", + " else:\n", + " print(\"The function did not return a DataFrame.\")\n", + "\n", + " except ImportError:\n", + " print(\"file does not exist\")\n", + "\n", + "df.head()\n", + "\n" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "# Split and shuffle data\n", + "train_data, test_data = split_data(df, shuffle=True)\n", + "print(train_data, test_data)" + ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -583,142 +787,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 DescriptionValue
0Session id123
1Targety
2Target typeBinary
3Original data shape(44654, 8)
4Transformed data shape(44654, 8)
5Transformed train set shape(31257, 8)
6Transformed test set shape(13397, 8)
7Numeric features7
8PreprocessTrue
9Imputation typesimple
10Numeric imputationmean
11Categorical imputationmode
12Fold GeneratorStratifiedKFold
13Fold Number10
14CPU Jobs-1
15Use GPUFalse
16Log ExperimentFalse
17Experiment Nameclf-default-name
18USI5013
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# Initialize data in PyCaret with all the defined parameters\n", "pycaret.setup(data=train_data, target=target, session_id=123)\n" @@ -736,248 +807,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 ModelAccuracyAUCRecallPrec.F1KappaMCCTT (Sec)
rfRandom Forest Classifier0.79790.87680.82460.78280.80310.59580.59681.4370
dtDecision Tree Classifier0.78550.79040.81690.76850.79190.57090.57210.0650
etExtra Trees Classifier0.77290.86110.79770.76000.77830.54580.54651.1060
lightgbmLight Gradient Boosting Machine0.76320.84010.77910.75510.76680.52630.52670.7680
knnK Neighbors Classifier0.75640.84020.86390.71100.78000.51290.52530.1020
gbcGradient Boosting Classifier0.73920.81250.76010.72970.74450.47850.47901.0040
adaAda Boost Classifier0.72520.79540.75740.71160.73380.45040.45140.3740
ridgeRidge Classifier0.71740.00000.77200.69610.73200.43490.43760.0250
ldaLinear Discriminant Analysis0.71740.75770.77200.69610.73200.43490.43760.0390
lrLogistic Regression0.71340.74860.77500.69000.73000.42680.43020.8080
nbNaive Bayes0.69810.76040.80490.66330.72720.39630.40570.0250
qdaQuadratic Discriminant Analysis0.58740.77060.96720.54960.70090.17490.26870.0260
svmSVM - Linear Kernel0.53730.00000.55610.49820.45220.07460.08870.0920
dummyDummy Classifier0.50010.50000.00000.00000.00000.00000.00000.0200
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# Train and evaluate the performance of all estimators available in the model library using cross-validation.\n", "bestModel = pycaret.compare_models()\n" @@ -1003,223 +835,18 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 AccuracyAUCRecallPrec.F1KappaMCC
Fold       
00.73060.80030.76630.71510.73980.46130.4625
10.71910.78660.76180.70170.73050.43830.4399
20.72710.80300.78060.70520.74100.45430.4569
30.71690.78870.76260.69870.72930.43380.4356
40.72780.80100.77670.70750.74050.45550.4577
50.72840.80760.78570.70490.74310.45680.4598
60.71940.79140.77740.69670.73480.43890.4419
70.71140.78190.77980.68580.72980.42270.4268
80.71970.79830.78040.69580.73570.43940.4427
90.70910.78080.76630.68750.72480.41830.4210
Mean0.72100.79400.77380.69990.73490.44190.4445
Std0.00700.00890.00820.00850.00580.01400.0136
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Fitting 10 folds for each of 10 candidates, totalling 100 fits\n", - "Original model was better than the tuned model, hence it will be returned. NOTE: The display metrics are for the tuned model (not the original one).\n" - ] - } - ], + "outputs": [], "source": [ "bestModel = pycaret.tune_model(bestModel, n_iter = 10, optimize = tuning_metric)\n" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,\n", - " criterion='gini', max_depth=None, max_features='sqrt',\n", - " max_leaf_nodes=None, max_samples=None,\n", - " min_impurity_decrease=0.0, min_samples_leaf=1,\n", - " min_samples_split=2, min_weight_fraction_leaf=0.0,\n", - " n_estimators=100, n_jobs=-1, oob_score=False,\n", - " random_state=123, verbose=0, warm_start=False)\n" - ] - } - ], + "outputs": [], "source": [ "# View the model's hyperparameter\n", "print(bestModel)\n" @@ -1236,27 +863,12 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a80ac25ea3bb4a059f8d9e065ed7b973", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(ToggleButtons(description='Plot Type:', icons=('',), options=(('Pipeline Plot', 'pipelin…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# Evaluate model: Display UI analyzing Hyperparameters, Confusion Matrix, Class Report, etc.\n", - "pycaret.evaluate_model(bestModel)\n" + "pycaret.evaluate_model(bestModel)" ] }, { @@ -1270,19 +882,11 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "scrolled": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Transformation Pipeline and Model Successfully Saved\n" - ] - } - ], + "outputs": [], "source": [ "# Finalising model and save the model to current directory\n", "final_model = finalize_and_save_model(algorithm_choice, bestModel, model_name)\n" @@ -1290,174 +894,9 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 ModelAccuracyAUCRecallPrec.F1KappaMCC
0Random Forest Classifier0.81520.89590.83960.80080.81970.63040.6311
\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
agejobeducationdefaultbalancehousingloanyprediction_labelprediction_score
4465435740229800010.590
446553152013200010.960
4465650420137500100.610
446573013073410001.000
4465836420130510110.531
\n", - "
" - ], - "text/plain": [ - " age job education default balance housing loan y \\\n", - "44654 35 7 4 0 2298 0 0 0 \n", - "44655 31 5 2 0 132 0 0 0 \n", - "44656 50 4 2 0 1375 0 0 1 \n", - "44657 30 1 3 0 734 1 0 0 \n", - "44658 36 4 2 0 1305 1 0 1 \n", - "\n", - " prediction_label prediction_score \n", - "44654 1 0.590 \n", - "44655 1 0.960 \n", - "44656 0 0.610 \n", - "44657 0 1.000 \n", - "44658 1 0.531 " - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "final_prediction = pycaret.predict_model(final_model, data=test_data)\n", "final_prediction.head()\n" @@ -1505,104 +944,9 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "ExactExplainer explainer: 11165it [21:57, 8.43it/s] \n" - ] - }, - { - "data": { - "text/html": [ - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n", - "findfont: Generic family 'sans-serif' not found because none of the following families were found: Arial, Liberation Sans, Bitstream Vera Sans, sans-serif\n" - ] - }, - { - "data": { - "image/png": "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29ub/fv385///AdQx9c0a9aMHTt20K9fv2Lbl4KQYF4IIYQQQjw0UlNTefnll23Sv/zyS3799Ve+/PJLXn/9dbRaLe3atWPSpEm4uLhY5Q0JCWHDhg1WA11btGjBjh07StXgVwCNkjnfkRBCCCGEEKJMkT7zQgghhBBClFESzAshhBBCCFFGSTAvyr0dO3bw5JNP0rZtWwYNGsTq1asL/Nrjx48zfvx4OnbsSKdOnfjXv/7FmTNnHmBpy4Z7qdNMEydOJCQkhF9//fUBlLBsKUp9njx5kg8//JABAwbQrl07Bg4cyPfff09ycnIxlLj0CAsLY/z48bRv356ePXsybdo00tPT7/o6RVGYN28effr0oV27djzzzDMcP368GEpcuhWlPm/fvs20adN46qmn6NixI7179+add97h+vXrxVTq0q2ox2h2ixYtIiQkhFdeeeXBFFKUajIAVpRrR48e5Y033qB///5MnDiRAwcO8PHHH+Pk5MQjjzyS72sPHDjAyy+/zGOPPcbIkSMxGo2cPHmSlJSUYip96XQvdZpp165dnDhx4gGXtGwoan1u3LiRq1evMnLkSKpXr87FixeZOXMmJ06c4McffyzGPSg5cXFxjB07lurVq/PVV19x8+ZNvvnmG1JSUnjzzTfzfe38+fOZOXMmL774InXr1mXJkiW8+OKLLFy4sFRNSVecilqfoaGhbN26lccee4yGDRsSExPDTz/9xKhRo/j999/x9PQsxr0oXe7lGM10+/ZtZs+ejZeX1wMurSi1FCHKsQkTJijPPPOMVdrbb7+tDBkyJN/XpaenK/369VOmTZv2IItXJhW1TjOlpqYqAwYMUFatWqU0b95c+eWXXx5EMcuMotZnVFSUTdq6deuU5s2bK6dOnbqvZSyt5syZo7Rv316JiYmxpC1btkxp2bKlcvPmzTxfl5KSonTs2FH5/vvvLWlpaWlK3759lcmTJz/QMpdmRa3PuLg4JT093SotMjJSCQkJUX799dcHVt6yoKh1mt27776rvPfee8rzzz+vvPzyyw+opKI0k242otxKS0vj4MGDNq2bPXr04NKlS0REROT52v379xMREcETTzzxoItZptxLnWb69ddfcXV1LXXz+JaEe6nP3Fo7AwMDAbh169b9LWgptXv3blq2bGl1Z8fu3btjNpvZu3dvnq87duwYiYmJVvVu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uijF4tq1a0yfPp3Q0NCSLoooJnFxcUyfPr3IJyRFld+xFhQUxCOPPMLnn3+O3LxeiCz6ki6AEOXV8ePHGTFiBHq9ngEDBlCnTh1SUlK4fPkyu3btwtnZmdatW9+37S1duhRnZ2ccHBxYtmwZISEheeYNCgrimWeeASA2Npbt27czb948du/ezbJlyzAYDPetXGXNkSNH2LVrFzNmzLBKb9GiBceOHUOvf/i+VsPDw/n+++/x8/MjKCiopIsjikFcXBzff/89L774Iq1atSq27d7tWBs1ahRPP/0027dvp3PnzsVWLiFKs4fvV0eIMmLGjBkkJyezatUq6tWrZ7P81q1b921b6enprFq1ikcffRRXV1cWL17MO++8g4uLS675K1asSP/+/S3PR44cydixY9m6dSubN2+mV69e961sZc2iRYvw9PSkU6dOVularRZ7e/sSKpUQ5UNISAh+fn789ttvEswLkUG62QhRQsLCwvDw8Mg1kAfw9fW9b9vaunUrd+7cYeDAgQwcOJCkpCTWrVtXqHW0b98egCtXruSZZ9GiRQQGBrJ582abZWazmY4dO1qdJOzcuZNXXnmFbt260ahRI0JCQhg9enSB+8SOGDGCrl272qRfu3aNwMBApk+fbpWuKAqLFi1i0KBBNG7cmKZNmzJixAibLk15MRqNbNq0ibZt22JnZ2e1LLd+ztnTFi5cSM+ePWnYsCH9+vVj69atAJw5c4Znn32WZs2a0apVKz755BPS09Nz3c+rV68ybtw4mjdvTrNmzZgwYQJXr161yms2m/nhhx8YPnw47dq1o0GDBnTu3Jn333+f6OjoXPdrw4YNjBgxgpCQEBo3bkzPnj355JNPSEtLY/ny5YwcORKAt956y9L9asSIEXetr2vXrvHGG2/Qtm1bGjRowCOPPMLUqVNJTk62yjd9+nQCAwO5ePEiU6dOpWPHjjRo0IDHHnuM7du333U7kNVPfc+ePXz//fd06dKFRo0aMXToUI4ePQrA/v37efLJJ2nSpAnt27e3ubqSadOmTTzxxBM0adKEpk2b8sQTT7Bp06Zc8y5evJhHH32UBg0a0L17d+bNm5dnF5D4+Hi++uorunfvToMGDWjdujWvvfaazXtYWAWt5/zGnQQGBjJp0iRAPW67desGwPfff295zzM/a9k/X2vWrKFfv340bNiQzp07M336dIxGo9W6C/o5LcixptFoaN++PX///TeJiYlFqS4hHjrSMi9ECalevTqXLl3ir7/+okePHgV6jclkyrNPfFpaWp6vW7p0KVWrViUkJASNRkNwcDDLli1j6NChBS5vWFgYAJ6ennnm6dOnD5MnT2bVqlWWYCDTnj17uHHjBqNHj7akrVixgtjYWAYMGEClSpW4ceMGS5Ys4V//+he//PJLvl2BiuKNN95g7dq19OzZk0GDBpGWlsYff/zB6NGjmT59uk2Zczp58iRJSUk0atSoUNtduHAhcXFxDB06FIPBwK+//sqLL77ItGnT+M9//kPfvn155JFH2LVrF7/++iteXl6MHz/eah1JSUmMGDGCRo0a8dprr3H58mUWLVrEP//8w4oVKywnf+np6fz888/06NGDbt264ejoyPHjx1m2bBmHDx+26Sb1zTff8OOPP1KnTh3+9a9/4evry5UrV/jrr7/497//TYsWLRg7diw//vgjjz/+OM2bNwfAx8cn330ODw9n6NChxMfH89RTT1GjRg3279/PzJkzOXz4MPPmzbPpkjRp0iT0ej2jR48mPT2d+fPnM2HCBNavX0/VqlULVNdTpkzBbDYzcuRI0tPTmTNnDqNHj+bLL7/knXfeYdiwYfTr149169bx3XffUbVqVasTzIULF/LRRx9Rq1Yty3uwYsUKJkyYwEcffcTjjz9uyTtv3jwmT55MvXr1eO2110hOTmbOnDl4e3vblCs+Pp4nnniCiIgIBg8eTN26dbl16xaLFi1i6NChLFu2DD8/vwLt473W893Url2bt956i8mTJ9O9e3e6d+8OgLOzs1W+LVu2cPXqVYYPH46Pjw9btmzh+++/JyIigsmTJxd6Xwp6rDVt2pTff/+dQ4cO0bFjx0JvR4iHjiKEKBGHDx9W6tevrwQEBCg9evRQJk2apCxcuFA5f/58rvm7dOmiBAQE3PVx584dq9dFRkYqQUFBynfffWdJmzdvnhIQEJDrtgICApTRo0crd+7cUe7cuaNcunRJmTt3rlK/fn2lefPmyu3bt/Pdr5deeklp0KCBEhMTY5X++uuvK8HBwVavT0xMtHn9rVu3lJYtWyrPPfecVfqbb76pBAQEWKU9/fTTSpcuXWzWcfXqVSUgIMBqn//66y8lICBA+e2336zypqenKwMHDlS6dOmimM3mfPdt6dKlSkBA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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "test_features = test_data.copy().drop(target, axis=1)\n", "\n", @@ -1623,37 +967,9 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "
\n", - "
\n", - " Visualization omitted, Javascript library not loaded!
\n", - " Have you run `initjs()` in this notebook? If this notebook was from another\n", - " user you must also trust this notebook (File -> Trust notebook). If you are viewing\n", - " this notebook on github the Javascript has been stripped for security. If you are using\n", - " JupyterLab this error is because a JupyterLab extension has not yet been written.\n", - "
\n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "shap_values_array = shap_values.values[0]\n", "\n", @@ -1671,21 +987,9 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sagemaker.config INFO - Not applying SDK defaults from location: /etc/xdg/sagemaker/config.yaml\n", - "sagemaker.config INFO - Not applying SDK defaults from location: /home/ec2-user/.config/sagemaker/config.yaml\n", - "sagemaker.config INFO - Not applying SDK defaults from location: /etc/xdg/sagemaker/config.yaml\n", - "sagemaker.config INFO - Not applying SDK defaults from location: /home/ec2-user/.config/sagemaker/config.yaml\n", - "-------!" - ] - } - ], + "outputs": [], "source": [ "# deploy model to sagemaker endpoint\n", "deploy_model(model_name, algorithm_choice, model_s3_bucket, instance_type, endpoint_name, role, inference_instance_count, image_uri)\n" @@ -1701,33 +1005,17 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Are you sure you want to delete the endpoint 'classification-proba-endpoint'? Type 'Yes' to confirm: Yes\n", - "Endpoint 'classification-proba-endpoint' and its configuration have been deleted.\n" - ] - } - ], + "outputs": [], "source": [ "delete_sagemaker_endpoint(endpoint_name)\n" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -1741,9 +1029,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.11.6" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/modules/s3/main.tf b/modules/s3/main.tf index a4400b6..eb7a057 100644 --- a/modules/s3/main.tf +++ b/modules/s3/main.tf @@ -3,7 +3,8 @@ # The model bucket will contain the model artifact # The config-bucket is used to store ipynb files, python files and other configuration files locals { - file_path = "${path.module}/../../mlops_ml_models" + preprocessing_script_path = var.preprocessing_script_path + file_path = "${path.module}/../../mlops_ml_models" files_to_upload = concat( tolist(fileset(local.file_path, "*.ipynb")), tolist(fileset(local.file_path, "*.py")), @@ -63,3 +64,12 @@ resource "random_string" "s3_suffix" { special = false upper = false } + +resource "aws_s3_object" "preprocessing_script_path" { + count = var.preprocessing_script_path != "None" ? 1 : 0 + bucket = aws_s3_bucket.model_buckets[1].id + key = "preprocess_data.py" + source = var.preprocessing_script_path + etag = filemd5(local.preprocessing_script_path) + tags = var.tags +} \ No newline at end of file diff --git a/modules/s3/variables.tf b/modules/s3/variables.tf index 3e5998a..c3d4caa 100644 --- a/modules/s3/variables.tf +++ b/modules/s3/variables.tf @@ -12,4 +12,9 @@ variable "tags" { type = map(string) } - +variable "preprocessing_script_path" { + description = "The path the user provides if they want to include their own data cleaning logic" + type = string + default = "None" +} +#TODO replace "None" with None \ No newline at end of file diff --git a/modules/sagemaker/main.tf b/modules/sagemaker/main.tf index cfd98e9..c965645 100644 --- a/modules/sagemaker/main.tf +++ b/modules/sagemaker/main.tf @@ -13,16 +13,17 @@ resource "aws_sagemaker_notebook_instance_lifecycle_configuration" "training_not { config_s3_bucket = var.config_s3_bucket env = { - data_location_s3 = "${var.data_s3_bucket}${var.data_location_s3}" - target = var.model_target_variable - algorithm_choice = var.algorithm_choice - endpoint_name = local.endpoint_name - model_name = local.model_name - model_s3_bucket = var.model_s3_bucket - inference_instance_type = var.inference_instance_type - inference_instance_count = var.inference_instance_count - ecr_repo_uri = var.ecr_repo_uri - tuning_metric = var.tuning_metric + data_location_s3 = "${var.data_s3_bucket}${var.data_location_s3}" + target = var.model_target_variable + algorithm_choice = var.algorithm_choice + endpoint_name = local.endpoint_name + model_name = local.model_name + model_s3_bucket = var.model_s3_bucket + inference_instance_type = var.inference_instance_type + inference_instance_count = var.inference_instance_count + ecr_repo_uri = var.ecr_repo_uri + tuning_metric = var.tuning_metric + preprocessing_script_path = var.preprocessing_script_path } } )) diff --git a/modules/sagemaker/templates/startupscript.sh.tftpl b/modules/sagemaker/templates/startupscript.sh.tftpl index 6be12e0..18ada0a 100644 --- a/modules/sagemaker/templates/startupscript.sh.tftpl +++ b/modules/sagemaker/templates/startupscript.sh.tftpl @@ -13,6 +13,12 @@ cat << EOF > /home/ec2-user/SageMaker/.env %{ for key, value in env ~} ${key}=${value} %{ endfor ~} +#TODO remplace "None" with None +if [ ${var.preprocessing_script_path} == "None" ]; then + echo "preprocessing_script_path" = "None" >> /home/ec2-user/SageMaker/.env +else + echo "preprocessing_script_path" = preprocess_data.py >> /home/ec2-user/SageMaker/.env +fi EOF exit 0 diff --git a/modules/sagemaker/variables.tf b/modules/sagemaker/variables.tf index f8b676a..e9a1452 100644 --- a/modules/sagemaker/variables.tf +++ b/modules/sagemaker/variables.tf @@ -88,3 +88,8 @@ variable "config_bucket_key_arn" { description = "The ARN of the KMS key using which notebook scripts are encrypted in S3." type = string } + +variable "preprocessing_script_path" { + description = "The path the user provides if they want to include their own data cleaning logic" + type = string +} \ No newline at end of file diff --git a/variables.tf b/variables.tf index 56f6e31..469e51c 100644 --- a/variables.tf +++ b/variables.tf @@ -97,3 +97,9 @@ variable "tuning_metric" { description = "The metric user want to focus when tuning hyperparameter" type = string } + +variable "preprocessing_script_path" { + description = "The path the user provides if they want to include their own data cleaning logic" + type = string + default = "None" +} \ No newline at end of file From 4e5723d9605e4010d6b1b0048ce9c71ad5395052 Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 23 Feb 2024 16:32:36 +0000 Subject: [PATCH 02/13] fix(preprocessing_script_path): variable formatting fixes --- .../models_template_notebook.ipynb | 136 ++++-------------- modules/s3/main.tf | 2 +- modules/s3/variables.tf | 5 +- .../templates/startupscript.sh.tftpl | 8 +- variables.tf | 2 +- 5 files changed, 30 insertions(+), 123 deletions(-) diff --git a/mlops_ml_models/models_template_notebook.ipynb b/mlops_ml_models/models_template_notebook.ipynb index e5690dc..2b54e6a 100644 --- a/mlops_ml_models/models_template_notebook.ipynb +++ b/mlops_ml_models/models_template_notebook.ipynb @@ -359,7 +359,8 @@ "from delete_sagemaker_endpoint import delete_sagemaker_endpoint\n", "from ydata_profiling import ProfileReport\n", "import shap\n", - "import pandas as pd" + "import pandas as pd\n", + "import unittest" ] }, { @@ -402,8 +403,7 @@ "inference_instance_count = int(os.getenv(\"inference_instance_count\"))\n", "image_uri = os.getenv(\"ecr_repo_uri\")\n", "tuning_metric = os.getenv(\"tuning_metric\")\n", - "#TODO change \n", - "os.environ['preprocessing_script_path'] = 'filename_path'\n", + "preprocessing_script_path = os.getenv(\"preprocessing_script_path\")\n", "\n", "print(data_location_s3, algorithm_choice, target, endpoint_name, model_name, data_location, instance_type, image_uri, tuning_metric)" ] @@ -642,123 +642,37 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 5, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - " Unnamed: 0 age education balance day month duration campaign \\\n", - "0 0 58 2 2143 5 8 261 1 \n", - "1 1 44 1 29 5 8 151 1 \n", - "2 2 33 1 2 5 8 76 1 \n", - "3 3 47 3 1506 5 8 92 1 \n", - "4 4 33 3 1 5 8 198 1 \n", - "... ... ... ... ... ... ... ... ... \n", - "79839 41749 33 1 1222 9 10 348 1 \n", - "79840 40301 30 1 444 16 6 195 2 \n", - "79841 41479 38 1 1844 7 11 245 1 \n", - "79842 31045 58 1 37 11 3 155 1 \n", - "79843 30566 58 2 3355 5 3 330 4 \n", - "\n", - " pdays previous job_admin. job_blue-collar job_entrepreneur \\\n", - "0 -1 0 0 0 0 \n", - "1 -1 0 0 0 0 \n", - "2 -1 0 0 0 1 \n", - "3 -1 0 0 1 0 \n", - "4 -1 0 0 0 0 \n", - "... ... ... ... ... ... \n", - "79839 135 1 0 0 0 \n", - "79840 -1 0 0 0 0 \n", - "79841 62 0 0 0 0 \n", - "79842 -1 0 0 0 0 \n", - "79843 -1 0 0 0 0 \n", - "\n", - " job_housemaid job_management job_retired job_self-employed \\\n", - "0 0 1 0 0 \n", - "1 0 0 0 0 \n", - "2 0 0 0 0 \n", - "3 0 0 0 0 \n", - "4 0 0 0 0 \n", - "... ... ... ... ... \n", - "79839 0 0 0 0 \n", - "79840 0 0 0 0 \n", - "79841 0 0 0 0 \n", - "79842 0 0 0 0 \n", - "79843 0 0 0 0 \n", - "\n", - " job_services job_student job_technician job_unemployed \\\n", - "0 0 0 0 0 \n", - "1 0 0 1 0 \n", - "2 0 0 0 0 \n", - "3 0 0 0 0 \n", - "4 0 0 0 0 \n", - "... ... ... ... ... \n", - "79839 0 0 0 0 \n", - "79840 0 0 0 0 \n", - "79841 0 0 0 0 \n", - "79842 0 0 0 0 \n", - "79843 0 0 0 0 \n", - "\n", - " marital_divorced marital_married marital_single contact_cellular \\\n", - "0 0 1 0 0 \n", - "1 0 0 1 0 \n", - "2 0 1 0 0 \n", - "3 0 1 0 0 \n", - "4 0 0 1 0 \n", - "... ... ... ... ... \n", - "79839 0 0 0 0 \n", - "79840 0 0 0 1 \n", - "79841 0 0 0 1 \n", - "79842 0 0 0 1 \n", - "79843 0 0 0 1 \n", - "\n", - " contact_telephone default_no default_yes housing_no housing_yes \\\n", - "0 0 1 0 0 1 \n", - "1 0 1 0 0 1 \n", - "2 0 1 0 0 1 \n", - "3 0 1 0 0 1 \n", - "4 0 1 0 1 0 \n", - "... ... ... ... ... ... \n", - "79839 0 1 0 1 0 \n", - "79840 0 1 0 0 0 \n", - "79841 0 1 0 1 0 \n", - "79842 0 1 0 1 0 \n", - "79843 0 1 0 1 0 \n", - "\n", - " loan_no loan_yes y \n", - "0 1 0 0 \n", - "1 1 0 0 \n", - "2 0 1 0 \n", - "3 1 0 0 \n", - "4 1 0 0 \n", - "... ... ... .. \n", - "79839 1 0 1 \n", - "79840 0 0 1 \n", - "79841 1 0 1 \n", - "79842 1 0 1 \n", - "79843 1 0 1 \n", - "\n", - "[79844 rows x 33 columns]\n" + "ename": "NameError", + "evalue": "name 'df' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32mc:\\Users\\KonradBachusz(Creder\\OneDrive - OneWorkplace\\Documents\\Projects\\internal\\terraform-aws-mlops-module\\mlops_ml_models\\models_template_notebook.ipynb Cell 12\u001b[0m line \u001b[0;36m1\n\u001b[0;32m 14\u001b[0m \u001b[39mprint\u001b[39m(\u001b[39m\"\u001b[39m\u001b[39mFile does not exist\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[0;32m 15\u001b[0m \u001b[39mreturn\u001b[39;00m df\n\u001b[1;32m---> 17\u001b[0m df\u001b[39m.\u001b[39mhead()\n", + "\u001b[1;31mNameError\u001b[0m: name 'df' is not defined" ] } ], "source": [ "#TODO tidy up\n", - "data_processing_path = os.getenv(\"data_processing\")\n", "\n", - "if data_processing_path != \"None\":\n", - " try:\n", - " from preprocess_data import preprocess_data\n", - " df = preprocess_data(df)\n", - " if isinstance(df, pd.DataFrame):\n", - " print(\"The function returned a DataFrame.\")\n", - " else:\n", - " print(\"The function did not return a DataFrame.\")\n", + "def preprocess_df(df):\n", + " \"\"\"\"\"\"\n", + " \n", "\n", - " except ImportError:\n", - " print(\"file does not exist\")\n", + " if preprocessing_script_path:\n", + " try:\n", + " from preprocess_data import preprocess_data\n", + " df = preprocess_data(df)\n", + " message = \"preprocess_data function didn't return a dataframe\"\n", + " assertIsInstance(df, pd.DataFrame, message)\n", + " except ImportError:\n", + " print(\"File does not exist\")\n", + " return df\n", "\n", "df.head()\n", "\n" @@ -1029,7 +943,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.10.11" } }, "nbformat": 4, diff --git a/modules/s3/main.tf b/modules/s3/main.tf index eb7a057..5cc30cf 100644 --- a/modules/s3/main.tf +++ b/modules/s3/main.tf @@ -66,7 +66,7 @@ resource "random_string" "s3_suffix" { } resource "aws_s3_object" "preprocessing_script_path" { - count = var.preprocessing_script_path != "None" ? 1 : 0 + count = var.preprocessing_script_path != null ? 1 : 0 bucket = aws_s3_bucket.model_buckets[1].id key = "preprocess_data.py" source = var.preprocessing_script_path diff --git a/modules/s3/variables.tf b/modules/s3/variables.tf index c3d4caa..02b8e34 100644 --- a/modules/s3/variables.tf +++ b/modules/s3/variables.tf @@ -15,6 +15,5 @@ variable "tags" { variable "preprocessing_script_path" { description = "The path the user provides if they want to include their own data cleaning logic" type = string - default = "None" -} -#TODO replace "None" with None \ No newline at end of file + default = null +} \ No newline at end of file diff --git a/modules/sagemaker/templates/startupscript.sh.tftpl b/modules/sagemaker/templates/startupscript.sh.tftpl index 18ada0a..28a3865 100644 --- a/modules/sagemaker/templates/startupscript.sh.tftpl +++ b/modules/sagemaker/templates/startupscript.sh.tftpl @@ -13,12 +13,6 @@ cat << EOF > /home/ec2-user/SageMaker/.env %{ for key, value in env ~} ${key}=${value} %{ endfor ~} -#TODO remplace "None" with None -if [ ${var.preprocessing_script_path} == "None" ]; then - echo "preprocessing_script_path" = "None" >> /home/ec2-user/SageMaker/.env -else - echo "preprocessing_script_path" = preprocess_data.py >> /home/ec2-user/SageMaker/.env -fi EOF -exit 0 +exit 0 \ No newline at end of file diff --git a/variables.tf b/variables.tf index 469e51c..9e44d68 100644 --- a/variables.tf +++ b/variables.tf @@ -101,5 +101,5 @@ variable "tuning_metric" { variable "preprocessing_script_path" { description = "The path the user provides if they want to include their own data cleaning logic" type = string - default = "None" + default = null } \ No newline at end of file From 2beda1f2f997678ceecc0c11d60f567239e6f2c4 Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 23 Feb 2024 17:03:38 +0000 Subject: [PATCH 03/13] fix(unit test): unit test for split_data --- mlops_ml_models/delete_sagemaker_endpoint.py | 7 ++-- mlops_ml_models/deploy_model_endpoint.py | 16 +++++---- mlops_ml_models/finalize_and_save_model.py | 3 +- mlops_ml_models/load_data.py | 2 +- .../models_template_notebook.ipynb | 2 +- mlops_ml_models/save_model_to_s3.py | 8 ++--- .../{split_data.py => transfom_data.py} | 2 +- pycaret_image_files/prediction_script.py | 9 +++-- tests/test_load_data.py | 10 +++--- tests/test_transform_data.py | 35 +++++++++++++++++++ 10 files changed, 61 insertions(+), 33 deletions(-) rename mlops_ml_models/{split_data.py => transfom_data.py} (96%) create mode 100644 tests/test_transform_data.py diff --git a/mlops_ml_models/delete_sagemaker_endpoint.py b/mlops_ml_models/delete_sagemaker_endpoint.py index 7741287..fe118d7 100644 --- a/mlops_ml_models/delete_sagemaker_endpoint.py +++ b/mlops_ml_models/delete_sagemaker_endpoint.py @@ -32,11 +32,8 @@ def delete_sagemaker_endpoint(endpoint_name: str) -> None: sagemaker_client.delete_endpoint(EndpointName=endpoint_name) # Delete endpoint configuration - sagemaker_client.delete_endpoint_config( - EndpointConfigName=endpoint_name - ) + sagemaker_client.delete_endpoint_config(EndpointConfigName=endpoint_name) - print(f"Endpoint '{endpoint_name}' and its configuration have " - "been deleted.") + print(f"Endpoint '{endpoint_name}' and its configuration have " "been deleted.") else: print("Endpoint deletion cancelled.") diff --git a/mlops_ml_models/deploy_model_endpoint.py b/mlops_ml_models/deploy_model_endpoint.py index ce4052e..ce3b391 100644 --- a/mlops_ml_models/deploy_model_endpoint.py +++ b/mlops_ml_models/deploy_model_endpoint.py @@ -2,10 +2,15 @@ def deploy_model( - model_name: str, model_type: str, model_s3_bucket: str, instance_type: str, endpoint_name, - role: str, inference_instance_count: int, image_uri: str + model_name: str, + model_type: str, + model_s3_bucket: str, + instance_type: str, + endpoint_name, + role: str, + inference_instance_count: int, + image_uri: str, ) -> None: - """This script deploys the sagemaker endpoint using the tar.gz file saved in s3. @@ -23,10 +28,7 @@ def deploy_model( image_uri=(image_uri), # The ECR image you pushed model_data=model_file, # Location of your serialized model role=role, - env={ - "MODEL_NAME": model_name, - "MODEL_TYPE": model_type - } + env={"MODEL_NAME": model_name, "MODEL_TYPE": model_type}, ) model.deploy( initial_instance_count=inference_instance_count, diff --git a/mlops_ml_models/finalize_and_save_model.py b/mlops_ml_models/finalize_and_save_model.py index acbcadc..eb67b79 100644 --- a/mlops_ml_models/finalize_and_save_model.py +++ b/mlops_ml_models/finalize_and_save_model.py @@ -1,8 +1,7 @@ import importlib -def finalize_and_save_model(algorithm_choice: str, bestModel: str, - model_name: str): +def finalize_and_save_model(algorithm_choice: str, bestModel: str, model_name: str): """ Finalizes the best model obtained from PyCaret and saves it locally. diff --git a/mlops_ml_models/load_data.py b/mlops_ml_models/load_data.py index 421ed06..c3bef86 100644 --- a/mlops_ml_models/load_data.py +++ b/mlops_ml_models/load_data.py @@ -18,7 +18,7 @@ def load_data(data_location: str) -> pd.DataFrame: df = pd.read_csv(data_location, low_memory=False) # Dropped unnamed columns. You should comment this portion out before # using the script if you dont have unamed columns - df = df.loc[:, ~df.columns.str.contains('^Unnamed')] + df = df.loc[:, ~df.columns.str.contains("^Unnamed")] return df except Exception as e: print(f"Error loading data: {e}") diff --git a/mlops_ml_models/models_template_notebook.ipynb b/mlops_ml_models/models_template_notebook.ipynb index 2b54e6a..7ba5362 100644 --- a/mlops_ml_models/models_template_notebook.ipynb +++ b/mlops_ml_models/models_template_notebook.ipynb @@ -351,7 +351,7 @@ "from sagemaker import get_execution_role\n", "from dotenv import load_dotenv\n", "from load_data import load_data\n", - "from split_data import split_data\n", + "from transfom_data import split_data\n", "import importlib\n", "from save_model_to_s3 import save_model_to_s3\n", "from deploy_model_endpoint import deploy_model\n", diff --git a/mlops_ml_models/save_model_to_s3.py b/mlops_ml_models/save_model_to_s3.py index 1895541..d6e4432 100644 --- a/mlops_ml_models/save_model_to_s3.py +++ b/mlops_ml_models/save_model_to_s3.py @@ -2,9 +2,7 @@ import boto3 -def save_model_to_s3( - trained_model_name: str, bucket_name: str -) -> None: +def save_model_to_s3(trained_model_name: str, bucket_name: str) -> None: """This saves the tar.gz model in an s3 bucket Args: @@ -16,5 +14,5 @@ def save_model_to_s3( s3 = boto3.client("s3") s3.upload_file( - f"{trained_model_name}.tar.gz", bucket_name, - f"{trained_model_name}.tar.gz") + f"{trained_model_name}.tar.gz", bucket_name, f"{trained_model_name}.tar.gz" + ) diff --git a/mlops_ml_models/split_data.py b/mlops_ml_models/transfom_data.py similarity index 96% rename from mlops_ml_models/split_data.py rename to mlops_ml_models/transfom_data.py index b7b8738..965e120 100644 --- a/mlops_ml_models/split_data.py +++ b/mlops_ml_models/transfom_data.py @@ -3,7 +3,7 @@ def split_data(df: pd.DataFrame, shuffle: bool) -> pd.DataFrame: """This script split the data into test_data and train_data, - with optinal shuffle function + with optional shuffle function Note: Remember that this function returns 2 values, therefore using, diff --git a/pycaret_image_files/prediction_script.py b/pycaret_image_files/prediction_script.py index d24b336..8ec20d5 100644 --- a/pycaret_image_files/prediction_script.py +++ b/pycaret_image_files/prediction_script.py @@ -14,8 +14,8 @@ # Instantiate Flask app app = Flask(__name__) -MODEL_NAME = os.getenv('MODEL_NAME') -MODEL_TYPE = os.getenv('MODEL_TYPE') +MODEL_NAME = os.getenv("MODEL_NAME") +MODEL_TYPE = os.getenv("MODEL_TYPE") # Define the model path # When you configure the model, you will need to specify the S3 location of @@ -32,8 +32,7 @@ @app.route("/ping", methods=["GET"]) def ping(): - return flask.Response(response="\n", status=200, - mimetype="application/json") + return flask.Response(response="\n", status=200, mimetype="application/json") # Define an endpoint for making predictions @@ -47,7 +46,7 @@ def predict(): logging.info(df) # Make predictions using the loaded model - if (MODEL_TYPE == "classification"): + if MODEL_TYPE == "classification": prediction = model.predict_proba(df) else: prediction = model.predict(df) diff --git a/tests/test_load_data.py b/tests/test_load_data.py index 2438faf..58fae9e 100644 --- a/tests/test_load_data.py +++ b/tests/test_load_data.py @@ -16,11 +16,9 @@ def mock_df() -> pd.DataFrame: pd.DataFrame: dataframe created from the script. Should be the same as in the resources. """ - return pd.DataFrame({ - 'col1': [1, 2, 3], - 'col2': ['A', 'B', 'C'], - 'col3': [4.5, 5.5, 6.5] - }) + return pd.DataFrame( + {"col1": [1, 2, 3], "col2": ["A", "B", "C"], "col3": [4.5, 5.5, 6.5]} + ) def test_load_data(mock_df: pd.DataFrame) -> None: @@ -30,6 +28,6 @@ def test_load_data(mock_df: pd.DataFrame) -> None: Args: mock_df (pd.DataFrame): Mock data generated from mock_df function """ - with patch('pandas.read_csv', return_value=mock_df): + with patch("pandas.read_csv", return_value=mock_df): result = load_data("mlops_ml_models/tests/resources/sample.csv") pd.testing.assert_frame_equal(result, mock_df) diff --git a/tests/test_transform_data.py b/tests/test_transform_data.py new file mode 100644 index 0000000..ee22716 --- /dev/null +++ b/tests/test_transform_data.py @@ -0,0 +1,35 @@ +from mlops_ml_models.transfom_data import split_data +import pandas as pd +import pytest +from unittest.mock import patch + + +@pytest.fixture +def mock_df() -> pd.DataFrame: + """This creates a mock dataframe based on the data + entered in the columns below. The data in the mock + dataframe is the same data that we have in the csv file in the + resources section The aim of this is to be able to test if the + load_data.py file returns a the same dataframe as what we have here. + + Returns: + pd.DataFrame: dataframe created from the script. Should be the same as + in the resources. + """ + return pd.DataFrame( + { + "col1": [1, 2, 3, 1, 2, 3, 1, 2, 3, 1], + "col2": ["A", "B", "C", "A", "B", "C", "A", "B", "C", "A"], + "col3": [4.5, 5.5, 6.5, 4.5, 5.5, 6.5, 4.5, 5.5, 6.5, 6.5], + } + ) + + +def test_split_data(mock_df: pd.DataFrame, shuffle=False) -> None: + """This Test compares if the split_data correctly splits a dataframe into 80% and 20% of rows + + Args: + mock_df (pd.DataFrame): Mock data generated from mock_df function + """ + train_data, test_data = split_data(mock_df, shuffle=False) + assert len(train_data) == 8 and len(test_data) == 2 From c8c237c0003518aae8c913b28b3dd828088b659d Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 23 Feb 2024 17:17:25 +0000 Subject: [PATCH 04/13] feat(unit tests): test_split_data_shuffle --- tests/test_transform_data.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/test_transform_data.py b/tests/test_transform_data.py index ee22716..c961234 100644 --- a/tests/test_transform_data.py +++ b/tests/test_transform_data.py @@ -25,11 +25,21 @@ def mock_df() -> pd.DataFrame: ) -def test_split_data(mock_df: pd.DataFrame, shuffle=False) -> None: - """This Test compares if the split_data correctly splits a dataframe into 80% and 20% of rows +def test_split_data_shuffle(mock_df: pd.DataFrame) -> None: + """This Test compares if the split_data correctly splits a dataframe into 80% and 20% of rows with shuffling. Args: mock_df (pd.DataFrame): Mock data generated from mock_df function """ - train_data, test_data = split_data(mock_df, shuffle=False) + train_data, test_data = split_data(mock_df, shuffle=True) assert len(train_data) == 8 and len(test_data) == 2 + + +def test_split_data(mock_df: pd.DataFrame) -> None: + """This Test compares if the split_data correctly splits a dataframe into 80% and 20% of rows with no shuffling. + + Args: + mock_df (pd.DataFrame): Mock data generated from mock_df function + """ + train_data, test_data = split_data(mock_df, shuffle=False) + assert list(train_data['col1']) == [1, 2, 3, 1, 2, 3, 1, 2] and list(test_data['col1']) == [3, 1] From e362b09cfaa696475e53430914fc48a318c00d31 Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 23 Feb 2024 17:18:40 +0000 Subject: [PATCH 05/13] fix(flake8): flake8 format --- tests/test_transform_data.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_transform_data.py b/tests/test_transform_data.py index c961234..1df7626 100644 --- a/tests/test_transform_data.py +++ b/tests/test_transform_data.py @@ -1,7 +1,6 @@ from mlops_ml_models.transfom_data import split_data import pandas as pd import pytest -from unittest.mock import patch @pytest.fixture @@ -42,4 +41,6 @@ def test_split_data(mock_df: pd.DataFrame) -> None: mock_df (pd.DataFrame): Mock data generated from mock_df function """ train_data, test_data = split_data(mock_df, shuffle=False) - assert list(train_data['col1']) == [1, 2, 3, 1, 2, 3, 1, 2] and list(test_data['col1']) == [3, 1] + assert list(train_data["col1"]) == [1, 2, 3, 1, 2, 3, 1, 2] and list( + test_data["col1"] + ) == [3, 1] From 5a954fc5da1873897e289d2d290f2fda80b4760a Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 23 Feb 2024 17:28:41 +0000 Subject: [PATCH 06/13] unit test commit --- mlops_ml_models/transfom_data.py | 14 ++++++++++++++ tests/test_transform_data.py | 9 ++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mlops_ml_models/transfom_data.py b/mlops_ml_models/transfom_data.py index 965e120..1eada30 100644 --- a/mlops_ml_models/transfom_data.py +++ b/mlops_ml_models/transfom_data.py @@ -30,3 +30,17 @@ def split_data(df: pd.DataFrame, shuffle: bool) -> pd.DataFrame: return train_data, test_data except Exception as e: print(f"Error loading data: {e}") + +#TODO finish +def preprocess_df(df,preprocessing_script_path): + """""" + if preprocessing_script_path: + try: + print("Loading file") + from preprocess_data import preprocess_data + df = preprocess_data(df) + message = "preprocess_data function didn't return a dataframe" + assertIsInstance(df, pd.DataFrame, message) + except ImportError: + print("File does not exist") + return df \ No newline at end of file diff --git a/tests/test_transform_data.py b/tests/test_transform_data.py index 1df7626..4a5d2b2 100644 --- a/tests/test_transform_data.py +++ b/tests/test_transform_data.py @@ -1,4 +1,4 @@ -from mlops_ml_models.transfom_data import split_data +from mlops_ml_models.transfom_data import split_data, preprocess_df import pandas as pd import pytest @@ -44,3 +44,10 @@ def test_split_data(mock_df: pd.DataFrame) -> None: assert list(train_data["col1"]) == [1, 2, 3, 1, 2, 3, 1, 2] and list( test_data["col1"] ) == [3, 1] + +def test_preprocess_df(mock_df: pd.DataFrame) -> None: + """TODO""" + preprocessing_script_path="test" + df=preprocess_df(mock_df, preprocessing_script_path) + print(df) + assert 2==2 \ No newline at end of file From b31e7fbb9cbb4573dc2cd9053f724664f70f6f42 Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 1 Mar 2024 13:41:47 +0000 Subject: [PATCH 07/13] fix(formatting): black formatting --- mlops_ml_models/transfom_data.py | 10 ++++++---- tests/test_transform_data.py | 7 ++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/mlops_ml_models/transfom_data.py b/mlops_ml_models/transfom_data.py index 1eada30..5f870fe 100644 --- a/mlops_ml_models/transfom_data.py +++ b/mlops_ml_models/transfom_data.py @@ -31,16 +31,18 @@ def split_data(df: pd.DataFrame, shuffle: bool) -> pd.DataFrame: except Exception as e: print(f"Error loading data: {e}") -#TODO finish -def preprocess_df(df,preprocessing_script_path): + +# TODO finish +def preprocess_df(df, preprocessing_script_path): """""" if preprocessing_script_path: try: print("Loading file") from preprocess_data import preprocess_data - df = preprocess_data(df) + + df = preprocess_data(df) message = "preprocess_data function didn't return a dataframe" assertIsInstance(df, pd.DataFrame, message) except ImportError: print("File does not exist") - return df \ No newline at end of file + return df diff --git a/tests/test_transform_data.py b/tests/test_transform_data.py index 4a5d2b2..04013bc 100644 --- a/tests/test_transform_data.py +++ b/tests/test_transform_data.py @@ -45,9 +45,10 @@ def test_split_data(mock_df: pd.DataFrame) -> None: test_data["col1"] ) == [3, 1] + def test_preprocess_df(mock_df: pd.DataFrame) -> None: """TODO""" - preprocessing_script_path="test" - df=preprocess_df(mock_df, preprocessing_script_path) + preprocessing_script_path = "test" + df = preprocess_df(mock_df, preprocessing_script_path) print(df) - assert 2==2 \ No newline at end of file + assert 2 == 2 From 9cf9594d86e7936aff9a65208a8b95e5bb665bdc Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 1 Mar 2024 14:40:42 +0000 Subject: [PATCH 08/13] feat(preprocess_data): added a function for unit testing --- tests/preprocess_data.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/preprocess_data.py diff --git a/tests/preprocess_data.py b/tests/preprocess_data.py new file mode 100644 index 0000000..cf807ef --- /dev/null +++ b/tests/preprocess_data.py @@ -0,0 +1,18 @@ +import pandas as pd + + +def preprocess_data(df): + """This placeholder function is supposed to mock some dataframe pre-processing to b used in unit testing + Args: + df: input dataframe + Returns: + df: processed dataframe""" + + # One-hot-encode categorical columns + df = pd.get_dummies(data=df, columns=["col1", "col2"]) + + # Create some dummy columns + df["col4"] = df["col3"] + 23 + df["col5"] = (df["col3"] + 100) / df["col4"] + + return df From 6f01cf069e174cff2efb362c9da770b328d13fe1 Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 1 Mar 2024 15:06:50 +0000 Subject: [PATCH 09/13] feat(preprocessing): added unit tests to preprocessing function --- mlops_ml_models/transfom_data.py | 3 +-- .../preprocess_data.py => preprocess_data.py | 0 tests/test_transform_data.py | 22 +++++++++++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) rename tests/preprocess_data.py => preprocess_data.py (100%) diff --git a/mlops_ml_models/transfom_data.py b/mlops_ml_models/transfom_data.py index 5f870fe..d67a15e 100644 --- a/mlops_ml_models/transfom_data.py +++ b/mlops_ml_models/transfom_data.py @@ -41,8 +41,7 @@ def preprocess_df(df, preprocessing_script_path): from preprocess_data import preprocess_data df = preprocess_data(df) - message = "preprocess_data function didn't return a dataframe" - assertIsInstance(df, pd.DataFrame, message) + assert isinstance(df, pd.DataFrame) except ImportError: print("File does not exist") return df diff --git a/tests/preprocess_data.py b/preprocess_data.py similarity index 100% rename from tests/preprocess_data.py rename to preprocess_data.py diff --git a/tests/test_transform_data.py b/tests/test_transform_data.py index 04013bc..3b87ffd 100644 --- a/tests/test_transform_data.py +++ b/tests/test_transform_data.py @@ -47,8 +47,22 @@ def test_split_data(mock_df: pd.DataFrame) -> None: def test_preprocess_df(mock_df: pd.DataFrame) -> None: - """TODO""" - preprocessing_script_path = "test" + """This test checks if the pre-processing function can be imported and execute a custom script to update the dataframe. + + Args: + mock_df: mock dataframe""" + preprocessing_script_path = "tests\\preprocess_data.py" df = preprocess_df(mock_df, preprocessing_script_path) - print(df) - assert 2 == 2 + + assert len(df.columns) == 9 + + +def test_preprocess_df_no_path(mock_df: pd.DataFrame) -> None: + """This test checks if the pre-processing function doesn't change the data if the preprocessing_script_path is not present. + + Args: + mock_df: mock dataframe""" + preprocessing_script_path = None + df = preprocess_df(mock_df, preprocessing_script_path) + + assert df.equals(mock_df) From b0fcd8a5b2bc8be81721f1858f97d1cb3a3568e0 Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 1 Mar 2024 15:20:17 +0000 Subject: [PATCH 10/13] fix(formatting): flake8 fixes --- .../models_template_notebook.ipynb | 24 +++---------------- mlops_ml_models/transfom_data.py | 12 ++++++++-- setup.cfg | 2 ++ 3 files changed, 15 insertions(+), 23 deletions(-) create mode 100644 setup.cfg diff --git a/mlops_ml_models/models_template_notebook.ipynb b/mlops_ml_models/models_template_notebook.ipynb index 7ba5362..b0ff651 100644 --- a/mlops_ml_models/models_template_notebook.ipynb +++ b/mlops_ml_models/models_template_notebook.ipynb @@ -351,7 +351,7 @@ "from sagemaker import get_execution_role\n", "from dotenv import load_dotenv\n", "from load_data import load_data\n", - "from transfom_data import split_data\n", + "from transfom_data import split_data, preprocess_df\n", "import importlib\n", "from save_model_to_s3 import save_model_to_s3\n", "from deploy_model_endpoint import deploy_model\n", @@ -359,8 +359,7 @@ "from delete_sagemaker_endpoint import delete_sagemaker_endpoint\n", "from ydata_profiling import ProfileReport\n", "import shap\n", - "import pandas as pd\n", - "import unittest" + "import pandas as pd" ] }, { @@ -658,24 +657,7 @@ } ], "source": [ - "#TODO tidy up\n", - "\n", - "def preprocess_df(df):\n", - " \"\"\"\"\"\"\n", - " \n", - "\n", - " if preprocessing_script_path:\n", - " try:\n", - " from preprocess_data import preprocess_data\n", - " df = preprocess_data(df)\n", - " message = \"preprocess_data function didn't return a dataframe\"\n", - " assertIsInstance(df, pd.DataFrame, message)\n", - " except ImportError:\n", - " print(\"File does not exist\")\n", - " return df\n", - "\n", - "df.head()\n", - "\n" + "df=preprocess_df(df)" ] }, { diff --git a/mlops_ml_models/transfom_data.py b/mlops_ml_models/transfom_data.py index d67a15e..48776ef 100644 --- a/mlops_ml_models/transfom_data.py +++ b/mlops_ml_models/transfom_data.py @@ -32,9 +32,17 @@ def split_data(df: pd.DataFrame, shuffle: bool) -> pd.DataFrame: print(f"Error loading data: {e}") -# TODO finish def preprocess_df(df, preprocessing_script_path): - """""" + """This is a placeholder function to import the preprocess_data function + if it has been uploaded into s3 when the preprocessing_script_path is provided by the user. + Args: + df: + preprocessing_script_path: Path to the data preprocessing script declared in user's repo + + Returns: + df: dataframe that has been processed or unchanged depending + if the preprocessing_script_path has been provided + """ if preprocessing_script_path: try: print("Loading file") diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..905c8bb --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 160 \ No newline at end of file From 17c36a303a322025444ac36b515e5e704f62a65f Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 1 Mar 2024 15:27:10 +0000 Subject: [PATCH 11/13] chore(readme and changelog): updated files --- CHANGELOG.md | 3 ++- README.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4f1a00..e53c6b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # AWS-MLOps-module -## [2.0.2] - 09/02/24 + +## [2.0.2] - 01/03/24 * Added functionality for passing preprocessing script ## [2.0.1] - 02/02/24 diff --git a/README.md b/README.md index fbc3683..9beb203 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ This repo contains a terraform module with corresponding AWS resources that enab ## Example Usage -#TODO update ``` module "MLOps" { source = "github.com/crederauk/terraform-aws-mlops-module?ref=" @@ -22,6 +21,7 @@ module "MLOps" { algorithm_choice = "classification" sagemaker_training_notebook_instance_type = "ml.m4.xlarge" inference_instance_count = 1 + preprocessing_script_path = "terraform\preprocess_data.py" tags = { my-tag-key = "my-tag-value" } @@ -67,6 +67,7 @@ No resources. | [inference\_instance\_count](#input\_inference\_instance\_count) | The initial number of instances to serve the model endpoint | `number` | `1` | no | | [inference\_instance\_type](#input\_inference\_instance\_type) | The instance type to be created for serving the model. Must be a valid EC2 instance type | `string` | `"ml.t2.medium"` | no | | [model\_target\_variable](#input\_model\_target\_variable) | The dependent variable (or 'label') that the model aims to predict. This should be a column name in the dataset. | `string` | n/a | yes | +| [preprocessing\_script\_path](#input\_preprocessing\_script\_path) | The path the user provides if they want to include their own data cleaning logic | `string` | `null` | no | | [resource\_naming\_prefix](#input\_resource\_naming\_prefix) | Naming prefix to be applied to all resources created by this module | `string` | n/a | yes | | [retrain\_model\_bool](#input\_retrain\_model\_bool) | Boolean to indicate if the retraining pipeline shoud be added | `bool` | `false` | no | | [retraining\_schedule](#input\_retraining\_schedule) | Cron expression for the model retraining frequency in the AWS format. See https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents-expressions.html for details | `string` | `""` | no | From 39b8047a4e3885a782da32732c55cb93d7a392f0 Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 8 Mar 2024 16:39:35 +0000 Subject: [PATCH 12/13] fix(preprocessing_script_path): default as null --- modules/sagemaker/variables.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/sagemaker/variables.tf b/modules/sagemaker/variables.tf index e9a1452..b75e56f 100644 --- a/modules/sagemaker/variables.tf +++ b/modules/sagemaker/variables.tf @@ -92,4 +92,5 @@ variable "config_bucket_key_arn" { variable "preprocessing_script_path" { description = "The path the user provides if they want to include their own data cleaning logic" type = string + default = null } \ No newline at end of file From c3fb46c58e84e3960a9681d37a0fc723add0da53 Mon Sep 17 00:00:00 2001 From: Konrad Bachusz Date: Fri, 8 Mar 2024 16:40:52 +0000 Subject: [PATCH 13/13] fix(forward slash): formatting fixed --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9beb203..cd3fa7f 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ module "MLOps" { algorithm_choice = "classification" sagemaker_training_notebook_instance_type = "ml.m4.xlarge" inference_instance_count = 1 - preprocessing_script_path = "terraform\preprocess_data.py" + preprocessing_script_path = "terraform/preprocess_data.py" tags = { my-tag-key = "my-tag-value" }