diff --git a/src/models/solarradiation/solarradiation_model.ipynb b/src/models/solarradiation/solarradiation_model.ipynb index bbf91d7..2ba696f 100755 --- a/src/models/solarradiation/solarradiation_model.ipynb +++ b/src/models/solarradiation/solarradiation_model.ipynb @@ -2,8 +2,189 @@ "cells": [ { "cell_type": "code", + "execution_count": 1, "id": "8adcbe0819b88578", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease\n", + "Hit:2 http://security.ubuntu.com/ubuntu jammy-security InRelease\n", + "Hit:3 http://archive.ubuntu.com/ubuntu jammy-updates InRelease\n", + "Hit:4 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64 InRelease\n", + "Hit:5 http://archive.ubuntu.com/ubuntu jammy-backports InRelease\n", + "Reading package lists... Done\n", + "Reading package lists... Done\n", + "Building dependency tree... Done\n", + "Reading state information... Done\n", + "graphviz is already the newest version (2.42.2-6ubuntu0.1).\n", + "0 upgraded, 0 newly installed, 0 to remove and 121 not upgraded.\n", + "Requirement already satisfied: tensorflow in /usr/local/lib/python3.11/dist-packages (2.13.0)\n", + "Requirement already satisfied: absl-py>=1.0.0 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (2.0.0)\n", + "Requirement already satisfied: astunparse>=1.6.0 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (1.6.3)\n", + "Requirement already satisfied: flatbuffers>=23.1.21 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (23.5.26)\n", + "Requirement already satisfied: gast<=0.4.0,>=0.2.1 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (0.4.0)\n", + "Requirement already satisfied: google-pasta>=0.1.1 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (0.2.0)\n", + "Requirement already satisfied: grpcio<2.0,>=1.24.3 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (1.58.0)\n", + "Requirement already satisfied: h5py>=2.9.0 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (3.9.0)\n", + "Requirement already satisfied: keras<2.14,>=2.13.1 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (2.13.1)\n", + "Requirement already satisfied: libclang>=13.0.0 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (16.0.6)\n", + "Requirement already satisfied: numpy<=1.24.3,>=1.22 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (1.24.3)\n", + "Requirement already satisfied: opt-einsum>=2.3.2 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (3.3.0)\n", + "Requirement already satisfied: packaging in /usr/local/lib/python3.11/dist-packages (from tensorflow) (23.1)\n", + "Requirement already satisfied: protobuf!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev,>=3.20.3 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (4.24.3)\n", + "Requirement already satisfied: setuptools in /usr/local/lib/python3.11/dist-packages (from tensorflow) (68.2.2)\n", + "Requirement already satisfied: six>=1.12.0 in /usr/lib/python3/dist-packages (from tensorflow) (1.16.0)\n", + "Requirement already satisfied: tensorboard<2.14,>=2.13 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (2.13.0)\n", + "Requirement already satisfied: tensorflow-estimator<2.14,>=2.13.0 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (2.13.0)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (2.3.0)\n", + "Requirement already satisfied: typing-extensions<4.6.0,>=3.6.6 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (4.5.0)\n", + "Requirement already satisfied: wrapt>=1.11.0 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (1.14.1)\n", + "Requirement already satisfied: tensorflow-io-gcs-filesystem>=0.23.1 in /usr/local/lib/python3.11/dist-packages (from tensorflow) (0.37.1)\n", + "Requirement already satisfied: wheel<1.0,>=0.23.0 in /usr/local/lib/python3.11/dist-packages (from astunparse>=1.6.0->tensorflow) (0.41.2)\n", + "Requirement already satisfied: google-auth<3,>=1.6.3 in /usr/local/lib/python3.11/dist-packages (from tensorboard<2.14,>=2.13->tensorflow) (2.23.1)\n", + "Requirement already satisfied: google-auth-oauthlib<1.1,>=0.5 in /usr/local/lib/python3.11/dist-packages (from tensorboard<2.14,>=2.13->tensorflow) (1.0.0)\n", + "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.11/dist-packages (from tensorboard<2.14,>=2.13->tensorflow) (3.4.4)\n", + "Requirement already satisfied: requests<3,>=2.21.0 in /usr/local/lib/python3.11/dist-packages (from tensorboard<2.14,>=2.13->tensorflow) (2.31.0)\n", + "Requirement already satisfied: tensorboard-data-server<0.8.0,>=0.7.0 in /usr/local/lib/python3.11/dist-packages (from tensorboard<2.14,>=2.13->tensorflow) (0.7.1)\n", + "Requirement already satisfied: werkzeug>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from tensorboard<2.14,>=2.13->tensorflow) (2.3.7)\n", + "Requirement already satisfied: cachetools<6.0,>=2.0.0 in /usr/local/lib/python3.11/dist-packages (from google-auth<3,>=1.6.3->tensorboard<2.14,>=2.13->tensorflow) (5.3.1)\n", + "Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.11/dist-packages (from google-auth<3,>=1.6.3->tensorboard<2.14,>=2.13->tensorflow) (0.3.0)\n", + "Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/lib/python3.11/dist-packages (from google-auth<3,>=1.6.3->tensorboard<2.14,>=2.13->tensorflow) (4.9)\n", + "Requirement already satisfied: urllib3>=2.0.5 in /usr/local/lib/python3.11/dist-packages (from google-auth<3,>=1.6.3->tensorboard<2.14,>=2.13->tensorflow) (2.0.5)\n", + "Requirement already satisfied: requests-oauthlib>=0.7.0 in /usr/local/lib/python3.11/dist-packages (from google-auth-oauthlib<1.1,>=0.5->tensorboard<2.14,>=2.13->tensorflow) (1.3.1)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.11/dist-packages (from requests<3,>=2.21.0->tensorboard<2.14,>=2.13->tensorflow) (3.2.0)\n", + "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.11/dist-packages (from requests<3,>=2.21.0->tensorboard<2.14,>=2.13->tensorflow) (3.4)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.11/dist-packages (from requests<3,>=2.21.0->tensorboard<2.14,>=2.13->tensorflow) (2023.7.22)\n", + "Requirement already satisfied: MarkupSafe>=2.1.1 in /usr/local/lib/python3.11/dist-packages (from werkzeug>=1.0.1->tensorboard<2.14,>=2.13->tensorflow) (2.1.3)\n", + "Requirement already satisfied: pyasn1<0.6.0,>=0.4.6 in /usr/local/lib/python3.11/dist-packages (from pyasn1-modules>=0.2.1->google-auth<3,>=1.6.3->tensorboard<2.14,>=2.13->tensorflow) (0.5.0)\n", + "Requirement already satisfied: oauthlib>=3.0.0 in /usr/lib/python3/dist-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<1.1,>=0.5->tensorboard<2.14,>=2.13->tensorflow) (3.2.0)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: numpy in /usr/local/lib/python3.11/dist-packages (1.24.3)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: pandas in /usr/local/lib/python3.11/dist-packages (2.2.3)\n", + "Requirement already satisfied: numpy>=1.23.2 in /usr/local/lib/python3.11/dist-packages (from pandas) (1.24.3)\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.11/dist-packages (from pandas) (2.8.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.11/dist-packages (from pandas) (2024.2)\n", + "Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.11/dist-packages (from pandas) (2024.2)\n", + "Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: keras in /usr/local/lib/python3.11/dist-packages (2.13.1)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: scikit-learn in /usr/local/lib/python3.11/dist-packages (1.5.2)\n", + "Requirement already satisfied: numpy>=1.19.5 in /usr/local/lib/python3.11/dist-packages (from scikit-learn) (1.24.3)\n", + "Requirement already satisfied: scipy>=1.6.0 in /usr/local/lib/python3.11/dist-packages (from scikit-learn) (1.14.1)\n", + "Requirement already satisfied: joblib>=1.2.0 in /usr/local/lib/python3.11/dist-packages (from scikit-learn) (1.4.2)\n", + "Requirement already satisfied: threadpoolctl>=3.1.0 in /usr/local/lib/python3.11/dist-packages (from scikit-learn) (3.5.0)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: matplotlib in /usr/local/lib/python3.11/dist-packages (3.8.0)\n", + "Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (1.1.1)\n", + "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (0.11.0)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (4.42.1)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (1.4.5)\n", + "Requirement already satisfied: numpy<2,>=1.21 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (1.24.3)\n", + "Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (23.1)\n", + "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (10.0.1)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (3.2.0)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (2.8.2)\n", + "Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: joblib in /usr/local/lib/python3.11/dist-packages (1.4.2)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: pyarrow in /usr/local/lib/python3.11/dist-packages (18.0.0)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: fastparquet in /usr/local/lib/python3.11/dist-packages (2024.11.0)\n", + "Requirement already satisfied: pandas>=1.5.0 in /usr/local/lib/python3.11/dist-packages (from fastparquet) (2.2.3)\n", + "Requirement already satisfied: numpy in /usr/local/lib/python3.11/dist-packages (from fastparquet) (1.24.3)\n", + "Requirement already satisfied: cramjam>=2.3 in /usr/local/lib/python3.11/dist-packages (from fastparquet) (2.9.0)\n", + "Requirement already satisfied: fsspec in /usr/local/lib/python3.11/dist-packages (from fastparquet) (2024.10.0)\n", + "Requirement already satisfied: packaging in /usr/local/lib/python3.11/dist-packages (from fastparquet) (23.1)\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.5.0->fastparquet) (2.8.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.5.0->fastparquet) (2024.2)\n", + "Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.5.0->fastparquet) (2024.2)\n", + "Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.8.2->pandas>=1.5.0->fastparquet) (1.16.0)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: scipy in /usr/local/lib/python3.11/dist-packages (1.14.1)\n", + "Requirement already satisfied: numpy<2.3,>=1.23.5 in /usr/local/lib/python3.11/dist-packages (from scipy) (1.24.3)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: seaborn in /usr/local/lib/python3.11/dist-packages (0.13.2)\n", + "Requirement already satisfied: numpy!=1.24.0,>=1.20 in /usr/local/lib/python3.11/dist-packages (from seaborn) (1.24.3)\n", + "Requirement already satisfied: pandas>=1.2 in /usr/local/lib/python3.11/dist-packages (from seaborn) (2.2.3)\n", + "Requirement already satisfied: matplotlib!=3.6.1,>=3.4 in /usr/local/lib/python3.11/dist-packages (from seaborn) (3.8.0)\n", + "Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (1.1.1)\n", + "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.11/dist-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (0.11.0)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (4.42.1)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (1.4.5)\n", + "Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (23.1)\n", + "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (10.0.1)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (3.2.0)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.11/dist-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (2.8.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.2->seaborn) (2024.2)\n", + "Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.2->seaborn) (2024.2)\n", + "Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.7->matplotlib!=3.6.1,>=3.4->seaborn) (1.16.0)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: tqdm in /usr/local/lib/python3.11/dist-packages (4.67.0)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: pydot in /usr/local/lib/python3.11/dist-packages (3.0.2)\n", + "Requirement already satisfied: pyparsing>=3.0.9 in /usr/local/lib/python3.11/dist-packages (from pydot) (3.2.0)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: tensorflow-io in /usr/local/lib/python3.11/dist-packages (0.37.1)\n", + "Requirement already satisfied: tensorflow-io-gcs-filesystem==0.37.1 in /usr/local/lib/python3.11/dist-packages (from tensorflow-io) (0.37.1)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "Requirement already satisfied: tensorflow-addons in /usr/local/lib/python3.11/dist-packages (0.23.0)\n", + "Requirement already satisfied: packaging in /usr/local/lib/python3.11/dist-packages (from tensorflow-addons) (23.1)\n", + "Requirement already satisfied: typeguard<3.0.0,>=2.7 in /usr/local/lib/python3.11/dist-packages (from tensorflow-addons) (2.13.3)\n", + "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n" + ] + } + ], "source": [ "from opt_einsum.paths import branch_1\n", "!apt-get update\n", @@ -25,17 +206,36 @@ "!pip install pydot\n", "!pip install tensorflow-io\n", "!pip install tensorflow-addons" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "code", + "execution_count": 2, "id": "7a813e3cbca057b7", "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2024-11-20 18:26:10.290667: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n", + "To enable the following instructions: AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", + "/usr/local/lib/python3.11/dist-packages/tensorflow_addons/utils/tfa_eol_msg.py:23: UserWarning: \n", + "\n", + "TensorFlow Addons (TFA) has ended development and introduction of new features.\n", + "TFA has entered a minimal maintenance and release mode until a planned end of life in May 2024.\n", + "Please modify downstream libraries to take dependencies from other repositories in our TensorFlow community (e.g. Keras, Keras-CV, and Keras-NLP). \n", + "\n", + "For more information see: https://github.com/tensorflow/addons/issues/2807 \n", + "\n", + " warnings.warn(\n" + ] + } + ], "source": [ "import tensorflow as tf\n", - "from tensorflow.keras.layers import Dense, LSTM, MultiHeadAttention, Dropout, BatchNormalization, LayerNormalization, Input, Activation, Lambda, Bidirectional, Add, MaxPooling1D\n", + "from tensorflow.keras.layers import Dense, LSTM, MultiHeadAttention, Dropout, BatchNormalization, LayerNormalization, Input, Activation, Lambda, Bidirectional, Add, MaxPooling1D, SpatialDropout1D, GlobalAveragePooling1D, \\\n", + " GlobalMaxPooling1D, Concatenate\n", "from tensorflow.keras import regularizers\n", "from tensorflow.keras.models import Model\n", "import pandas as pd\n", @@ -49,18 +249,22 @@ "import matplotlib.pyplot as plt\n", "from tensorflow.keras.utils import plot_model\n", "import tensorflow_addons as tfa\n", + "import os\n", + "import joblib\n", + "import seaborn as sns\n", + "from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score, confusion_matrix\n", "\n", "folder_name = datetime.now().strftime(\"%Y-%m-%d_%H-%M\")\n", "\n", "random_state_value = None" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "code", + "execution_count": 3, "id": "b3f525e19f78a1da", "metadata": {}, + "outputs": [], "source": [ "def get_season(date):\n", " month = date.month\n", @@ -89,28 +293,43 @@ "\n", "\n", "def add_time_features(df):\n", - " df['datetime'] = pd.to_datetime(df['datetime'])\n", - " df['timestamp'] = df['datetime'].astype(np.int64) // 10 ** 9\n", - " df['year'] = df['datetime'].dt.year\n", - " df['month'] = df['datetime'].dt.month\n", - " df['day'] = df['datetime'].dt.day\n", - " df['hour'] = df['datetime'].dt.hour\n", - " df['minute'] = df['datetime'].dt.minute\n", - " df['hour_sin'] = np.sin(df['hour'] * (2 * np.pi / 24))\n", - " df['hour_cos'] = np.cos(df['hour'] * (2 * np.pi / 24))\n", - " df['day_of_week'] = df['datetime'].dt.dayofweek\n", - " df['day_of_year'] = df['datetime'].dt.dayofyear\n", - " df['week_of_year'] = df['datetime'].dt.isocalendar().week.astype(int)\n", - " df['quarter'] = df['datetime'].dt.quarter\n", - " df['is_month_end'] = df['datetime'].dt.is_month_end.astype(int)\n", - " df['is_quarter_end'] = df['datetime'].dt.is_quarter_end.astype(int)\n", - " df['is_year_end'] = df['datetime'].dt.is_year_end.astype(int)\n", - " df['month_sin'] = np.sin(df['month'] * (2 * np.pi / 12))\n", - " df['month_cos'] = np.cos(df['month'] * (2 * np.pi / 12))\n", - " df['day_of_year_sin'] = np.sin(df['day_of_year'] * (2 * np.pi / 365.25))\n", - " df['day_of_year_cos'] = np.cos(df['day_of_year'] * (2 * np.pi / 365.25))\n", - " df['season'] = df['datetime'].apply(get_season)\n", - " df['time_period'] = df['hour'].apply(get_time_period)\n", + " \"\"\"\n", + " Add time-based features to the DataFrame.\n", + " Works with both 'datetime' as column or index.\n", + " \"\"\"\n", + " # Se datetime è l'indice, lo usiamo direttamente\n", + " if isinstance(df.index, pd.DatetimeIndex):\n", + " datetime_col = df.index\n", + " else:\n", + " # Se datetime è una colonna, la convertiamo\n", + " if 'datetime' in df.columns:\n", + " datetime_col = pd.to_datetime(df['datetime'])\n", + " else:\n", + " raise ValueError(\"No datetime column or index found in DataFrame\")\n", + "\n", + " # Creazione delle feature temporali\n", + " df['timestamp'] = datetime_col.astype(np.int64) // 10 ** 9\n", + " df['year'] = datetime_col.year\n", + " df['month'] = datetime_col.month\n", + " df['day'] = datetime_col.day\n", + " df['hour'] = datetime_col.hour\n", + " df['minute'] = datetime_col.minute\n", + " df['hour_sin'] = np.sin(datetime_col.hour * (2 * np.pi / 24))\n", + " df['hour_cos'] = np.cos(datetime_col.hour * (2 * np.pi / 24))\n", + " df['day_of_week'] = datetime_col.dayofweek\n", + " df['day_of_year'] = datetime_col.dayofyear\n", + " df['week_of_year'] = datetime_col.isocalendar().week.astype(int)\n", + " df['quarter'] = datetime_col.quarter\n", + " df['is_month_end'] = datetime_col.is_month_end.astype(int)\n", + " df['is_quarter_end'] = datetime_col.is_quarter_end.astype(int)\n", + " df['is_year_end'] = datetime_col.is_year_end.astype(int)\n", + " df['month_sin'] = np.sin(datetime_col.month * (2 * np.pi / 12))\n", + " df['month_cos'] = np.cos(datetime_col.month * (2 * np.pi / 12))\n", + " df['day_of_year_sin'] = np.sin(datetime_col.dayofyear * (2 * np.pi / 365.25))\n", + " df['day_of_year_cos'] = np.cos(datetime_col.dayofyear * (2 * np.pi / 365.25))\n", + " df['season'] = datetime_col.map(get_season)\n", + " df['time_period'] = datetime_col.hour.map(get_time_period)\n", + "\n", " return df\n", "\n", "\n", @@ -130,18 +349,38 @@ "\n", "\n", "def add_solar_specific_features(df):\n", - " # Solar angle and day length\n", + " \"\"\"\n", + " Aggiunge feature specifiche per la predizione della radiazione solare\n", + " combinando caratteristiche astronomiche e meteorologiche\n", + " \"\"\"\n", + " # Caratteristiche astronomiche\n", " df['day_length'] = 12 + 3 * np.sin(2 * np.pi * (df['day_of_year'] - 81) / 365.25)\n", " df['solar_noon'] = 12 - df['hour']\n", " df['solar_elevation'] = np.sin(2 * np.pi * df['day_of_year'] / 365.25) * np.cos(2 * np.pi * df['solar_noon'] / 24)\n", "\n", - " # Interactions\n", + " # Angolo solare teorico\n", + " df['solar_angle'] = np.sin(df['hour_sin']) * np.sin(df['day_of_year_sin'])\n", + "\n", + " # Interazioni con condizioni atmosferiche\n", " df['cloud_elevation'] = df['cloudcover'] * df['solar_elevation']\n", " df['visibility_elevation'] = df['visibility'] * df['solar_elevation']\n", + " df['uv_cloud_interaction'] = df['uvindex'] * (100 - df['cloudcover']) / 100\n", "\n", - " # Rolling features with wider windows\n", + " # Indici di chiarezza e trasmissione\n", + " df['clearness_index'] = (100 - df['cloudcover']) * df['visibility'] / 10000\n", + " df['atmospheric_attenuation'] = (df['pressure'] / 1013.25) * (1 - (df['humidity'] / 100) * 0.6)\n", + "\n", + " # Radiazione teorica e attenuazione\n", + " df['theoretical_radiation'] = df['solar_angle'].clip(0, 1) * 1000\n", + " df['expected_radiation'] = df['theoretical_radiation'] * df['clearness_index']\n", + "\n", + " # Rolling features\n", " df['cloud_rolling_12h'] = df['cloudcover'].rolling(window=12).mean()\n", " df['temp_rolling_12h'] = df['temp'].rolling(window=12).mean()\n", + " df['uv_rolling_12h'] = df['uvindex'].rolling(window=12).mean()\n", + "\n", + " # Interazioni temperatura-radiazione\n", + " df['temp_radiation_potential'] = df['temp'] * df['solar_elevation']\n", "\n", " return df\n", "\n", @@ -149,6 +388,10 @@ "def add_radiation_energy_features(df):\n", " \"\"\"Adds specific features based on solarenergy and uvindex\"\"\"\n", "\n", + " # Assicuriamoci che l'indice sia di tipo datetime\n", + " if not isinstance(df.index, pd.DatetimeIndex):\n", + " df.index = pd.to_datetime(df['datetime'])\n", + "\n", " # Solar energy to UV ratio (independent from solarradiation)\n", " df['energy_uv_ratio'] = df['solarenergy'] / (df['uvindex'] + 1e-6)\n", "\n", @@ -159,7 +402,7 @@ " df[f'energy_rolling_mean_{w}h'] = df['solarenergy'].rolling(window=w).mean()\n", " df[f'uv_rolling_mean_{w}h'] = df['uvindex'].rolling(window=w).mean()\n", "\n", - " # Daily aggregations\n", + " # Daily aggregations utilizzando datetime\n", " df['energy_daily_sum'] = df.groupby(df.index.date)['solarenergy'].transform('sum')\n", " df['uv_daily_max'] = df.groupby(df.index.date)['uvindex'].transform('max')\n", "\n", @@ -177,123 +420,161 @@ " df['is_energy_peak'] = (df['solarenergy'] > df['energy_rolling_mean_6h'] * 1.2).astype(int)\n", " df['is_uv_peak'] = (df['uvindex'] > df['uv_rolling_mean_6h'] * 1.2).astype(int)\n", "\n", + " # Aggiungiamo alcune metriche di volatilità\n", + " df['energy_volatility'] = df['energy_change'].rolling(window=24).std()\n", + " df['uv_volatility'] = df['uv_change'].rolling(window=24).std()\n", + "\n", + " # Indice di intensità solare composito\n", + " df['solar_intensity_index'] = (df['solarenergy'] * df['uvindex']) / (df['cloudcover'] + 1e-6)\n", + "\n", + " # Interazioni\n", + " df['uv_cloud_interaction'] = df['uvindex'] * (100 - df['cloudcover']) / 100\n", + " df['energy_temp_interaction'] = df['solarenergy'] * df['temp']\n", + "\n", " return df\n", "\n", "\n", "def add_advanced_features(df):\n", + " \"\"\"\n", + " Add all advanced features to the DataFrame\n", + " Assumes df has a DatetimeIndex\n", + " \"\"\"\n", + " # Verifichiamo che abbiamo un DatetimeIndex\n", + " if not isinstance(df.index, pd.DatetimeIndex):\n", + " raise ValueError(\"DataFrame must have a DatetimeIndex\")\n", + "\n", " # Existing features\n", " df = add_time_features(df)\n", " df = add_solar_features(df)\n", " df = add_solar_specific_features(df)\n", " df = add_radiation_energy_features(df)\n", "\n", - " if not isinstance(df.index, pd.DatetimeIndex):\n", - " df.index = pd.to_datetime(df.index)\n", - "\n", - " # One-hot encoding for categorical features\n", - " df = pd.get_dummies(df, columns=['season', 'time_period'])\n", - "\n", " # Weather variable interactions\n", " df['temp_humidity'] = df['temp'] * df['humidity']\n", " df['temp_cloudcover'] = df['temp'] * df['cloudcover']\n", " df['visibility_cloudcover'] = df['visibility'] * df['cloudcover']\n", "\n", - " # Derived features for solar radiation\n", + " # Derived features\n", " df['clear_sky_factor'] = (100 - df['cloudcover']) / 100\n", - " df['day_length'] = np.sin(df['day_of_year_sin']) * 12 + 12 # day length approximation\n", + " df['temp_humidity_interaction'] = df['temp'] * df['humidity'] / 100\n", + " df['atmospheric_transparency'] = (100 - df['cloudcover']) * (df['visibility'] / 10)\n", + "\n", + " # Rolling means\n", + " df['temp_rolling_mean_6h'] = df['temp'].rolling(window=6).mean()\n", + " df['cloudcover_rolling_mean_6h'] = df['cloudcover'].rolling(window=6).mean()\n", "\n", " # Lag features\n", " df['temp_1h_lag'] = df['temp'].shift(1)\n", " df['cloudcover_1h_lag'] = df['cloudcover'].shift(1)\n", " df['humidity_1h_lag'] = df['humidity'].shift(1)\n", "\n", - " # Rolling means\n", - " df['temp_rolling_mean_6h'] = df['temp'].rolling(window=6).mean()\n", - " df['cloudcover_rolling_mean_6h'] = df['cloudcover'].rolling(window=6).mean()\n", - "\n", - " df['temp_humidity_interaction'] = df['temp'] * df['humidity'] / 100\n", - "\n", " # Extreme conditions indicator\n", - " df['extreme_conditions'] = ((df['temp'] > df['temp'].quantile(0.75)) & (df['humidity'] < df['humidity'].quantile(0.25))).astype(int)\n", + " df['extreme_conditions'] = ((df['temp'] > df['temp'].quantile(0.75)) &\n", + " (df['humidity'] < df['humidity'].quantile(0.25))).astype(int)\n", "\n", - " # Composite feature for atmospheric transparency\n", - " df['atmospheric_transparency'] = (100 - df['cloudcover']) * (df['visibility'] / 10)\n", - "\n", - " # More granular temporal indicators for mid-seasons\n", - " df['is_transition_season'] = ((df['season_Spring'] | df['season_Autumn'])).astype(int)\n", - "\n", - " # Interaction between solar angle and normalized cloud cover\n", - " df['solar_cloud_effect'] = df['solar_elevation'] * (100 - df['cloudcover']) / 100\n", - "\n", - " # Atmospheric stability indicator\n", - " df['pressure_stability'] = df.groupby(df.index.date if isinstance(df.index, pd.DatetimeIndex)\n", - " else df.index.to_series().dt.date)['pressure'].transform(\n", - " lambda x: x.std()\n", - " ).fillna(0)\n", + " # One-hot encoding for categorical features\n", + " df = pd.get_dummies(df, columns=['season', 'time_period'])\n", "\n", " return df\n", "\n", "\n", "def prepare_advanced_data(df):\n", + " \"\"\"\n", + " Prepare data for advanced modeling with proper datetime handling\n", + " \"\"\"\n", + " # Assicuriamoci che abbiamo una copia del DataFrame\n", + " df = df.copy()\n", + "\n", + " # Verifichiamo se datetime è già l'indice\n", + " if not isinstance(df.index, pd.DatetimeIndex):\n", + " if 'datetime' in df.columns:\n", + " df['datetime'] = pd.to_datetime(df['datetime'])\n", + " df.set_index('datetime', inplace=True)\n", + " else:\n", + " raise ValueError(\"No datetime column or index found in DataFrame\")\n", + "\n", + " # Ordiniamo il DataFrame per datetime\n", + " df = df.sort_index()\n", + "\n", " # Apply feature engineering functions\n", " df = add_advanced_features(df)\n", "\n", - " target_variables = ['solarradiation', 'solarenergy', 'uvindex']\n", + " #all_columns = list(df.columns)\n", + " #print(all_columns)\n", "\n", - " # Updated feature selection (without solarradiation dependencies)\n", - " selected_features = [\n", - " # Base meteorological features\n", - " 'temp', 'humidity', 'cloudcover', 'visibility', 'pressure',\n", + " features = {\n", + " # Primary Features (strong direct correlation)\n", + " 'primary_features': [\n", + " 'uvindex', # Direct radiation indicator\n", + " 'cloudcover', # Cloud coverage\n", + " 'visibility', # Atmospheric transparency\n", + " 'temp', # Temperature\n", + " 'pressure', # Atmospheric pressure\n", + " 'humidity', # Humidity\n", + " ],\n", "\n", - " # Solar features\n", - " 'zenith_angle', 'air_mass', 'atmospheric_transmission',\n", - " 'cloud_transmission', 'theoretical_radiation',\n", + " # Astronomical and Temporal Features\n", + " 'astronomical_features': [\n", + " 'solar_elevation', # Solar elevation\n", + " 'solar_angle', # Solar angle\n", + " 'day_length', # Day length\n", + " 'hour_sin', # Daily cycle\n", + " 'hour_cos',\n", + " 'day_of_year_sin', # Annual cycle\n", + " 'day_of_year_cos',\n", + " 'month_sin', # Monthly cycle\n", + " 'month_cos',\n", + " ],\n", "\n", - " # Time features\n", - " 'hour_sin', 'hour_cos', 'month_sin', 'month_cos',\n", - " 'day_of_year_sin', 'day_of_year_cos',\n", + " # Key Indices and Interactions\n", + " 'key_interactions': [\n", + " 'clear_sky_index', # Clear sky index\n", + " 'atmospheric_attenuation', # Atmospheric attenuation\n", + " 'theoretical_radiation', # Theoretical radiation\n", + " 'expected_radiation', # Expected radiation\n", + " 'cloud_elevation', # Cloud-elevation interaction\n", + " 'visibility_elevation', # Visibility-elevation interaction\n", + " 'uv_cloud_interaction', # UV-cloud interaction\n", + " 'temp_radiation_potential', # Temperature-radiation potential\n", + " ],\n", "\n", - " # Atmospheric features\n", - " 'clear_sky_index', 'humidity_factor', 'atmospheric_clarity',\n", - " 'vapor_pressure',\n", + " # Rolling Features (temporal trends)\n", + " 'rolling_features': [\n", + " 'cloud_rolling_12h', # Cloud coverage moving average\n", + " 'temp_rolling_12h', # Temperature moving average\n", + " 'uv_rolling_12h', # UV moving average\n", + " 'cloudcover_rolling_mean_6h',\n", + " 'temp_rolling_mean_6h',\n", + " ],\n", "\n", - " # Solar energy and UV features\n", - " 'energy_uv_ratio',\n", + " # Lag Features (most recent)\n", + " 'lag_features': [\n", + " 'temp_1h_lag', # 1-hour temperature lag\n", + " 'cloudcover_1h_lag', # 1-hour cloud coverage lag\n", + " 'humidity_1h_lag', # 1-hour humidity lag\n", + " 'uv_lag_1h', # 1-hour UV lag\n", + " ],\n", "\n", - " # Moving averages\n", - " 'energy_rolling_mean_3h', 'energy_rolling_mean_6h',\n", - " 'uv_rolling_mean_3h', 'uv_rolling_mean_6h',\n", + " # Categorical Features\n", + " 'categorical_features': [\n", + " 'season_Spring', # Seasons\n", + " 'season_Summer',\n", + " 'season_Autumn',\n", + " 'season_Winter',\n", + " 'time_period_Morning', # Time periods\n", + " 'time_period_Afternoon',\n", + " 'time_period_Evening',\n", + " 'time_period_Night',\n", + " ]\n", + " }\n", "\n", - " # Daily aggregations\n", - " 'energy_daily_sum', 'uv_daily_max',\n", - "\n", - " # Main lag features\n", - " 'energy_lag_1h', 'energy_lag_3h', 'energy_lag_6h',\n", - " 'uv_lag_1h', 'uv_lag_3h',\n", - "\n", - " # Peak and volatility indicators\n", - " 'is_energy_peak', 'is_uv_peak',\n", - " 'energy_volatility', 'uv_volatility',\n", - "\n", - " # Composite indices\n", - " 'solar_intensity_index',\n", - "\n", - " # Interactions\n", - " 'uv_cloud_interaction',\n", - " 'energy_temp_interaction'\n", - " ]\n", - "\n", - " # Add one-hot columns\n", - " categorical_columns = [col for col in df.columns if col.startswith(('season_', 'time_period_'))]\n", - " final_features = selected_features + categorical_columns\n", - "\n", - " # Dataset preparation\n", - " df = df.sort_values('datetime')\n", - " df.set_index('datetime', inplace=True)\n", + " final_features = [feature for group in features.values() for feature in group]\n", "\n", " # Handle missing values\n", + " target_variables = ['solarradiation', 'solarenergy', 'uvindex']\n", " for column in final_features + target_variables:\n", - " df[column] = df[column].interpolate(method='time')\n", + " if column in df.columns:\n", + " df[column] = df[column].interpolate(method='time')\n", " df.fillna(0, inplace=True)\n", "\n", " # Temporal split\n", @@ -305,15 +586,26 @@ " X_to_predict = data_before_2010[final_features]\n", "\n", " # Train-test split\n", - " X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=random_state_value)\n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.2, random_state=42, shuffle=False\n", + " )\n", "\n", " # Scaling\n", - " scaler = RobustScaler()\n", - " X_train_scaled = scaler.fit_transform(X_train)\n", - " X_test_scaled = scaler.transform(X_test)\n", - " X_to_predict_scaled = scaler.transform(X_to_predict)\n", + " feature_scaler = RobustScaler()\n", + " X_train_scaled = feature_scaler.fit_transform(X_train)\n", + " X_test_scaled = feature_scaler.transform(X_test)\n", + " X_to_predict_scaled = feature_scaler.transform(X_to_predict)\n", "\n", - " return X_train_scaled, X_test_scaled, y_train, y_test, scaler, final_features, X_to_predict_scaled\n", + " target_scaler = RobustScaler()\n", + " y_train_scaled = target_scaler.fit_transform(y_train.values.reshape(-1, 1))\n", + " y_test_scaled = target_scaler.transform(y_test.values.reshape(-1, 1))\n", + "\n", + " # Print info about selected features\n", + " print(\"\\nSelected features:\")\n", + " print(f\"Number of features: {len(final_features)}\")\n", + " print(\"Features list:\", final_features)\n", + "\n", + " return X_train_scaled, X_test_scaled, y_train_scaled, y_test_scaled, feature_scaler, target_scaler, final_features, X_to_predict_scaled\n", "\n", "\n", "def create_sequence_data(X, sequence_length=24):\n", @@ -328,7 +620,7 @@ "\n", "\n", "def prepare_hybrid_data(df):\n", - " X_train_scaled, X_test_scaled, y_train, y_test, scaler, features, X_to_predict_scaled = prepare_advanced_data(df)\n", + " X_train_scaled, X_test_scaled, y_train_scaled, y_test_scaled, feature_scaler, target_scaler, features, X_to_predict_scaled = prepare_advanced_data(df)\n", "\n", " # Convert data into sequences\n", " sequence_length = 24 # 24 hours of historical data\n", @@ -337,20 +629,22 @@ " X_test_seq = create_sequence_data(X_test_scaled, sequence_length)\n", "\n", " # Adjust y by removing the first (sequence_length-1) elements\n", - " y_train = y_train[sequence_length - 1:]\n", - " y_test = y_test[sequence_length - 1:]\n", + " y_train = y_train_scaled[sequence_length - 1:]\n", + " y_test = y_test_scaled[sequence_length - 1:]\n", "\n", " X_to_predict_seq = create_sequence_data(X_to_predict_scaled, sequence_length)\n", "\n", - " return X_train_seq, X_test_seq, y_train, y_test, scaler, features, X_to_predict_seq" - ], - "outputs": [], - "execution_count": null + " return X_train_seq, X_test_seq, y_train, y_test, feature_scaler, target_scaler, features, X_to_predict_seq" + ] }, { "cell_type": "code", "id": "9dff3259-b376-4cfc-89d8-ab2ea18aaa5e", - "metadata": {}, + "metadata": { + "jupyter": { + "is_executing": true + } + }, "source": [ "def create_residual_lstm_layer(x, units, dropout_rate, l2_reg=0.01, return_sequences=True, survival_probability=0.8):\n", " \"\"\"\n", @@ -375,6 +669,7 @@ " x = tfa.layers.StochasticDepth(survival_probability)([x, residual])\n", " return x\n", "\n", + "\n", "def attention_block(x, units, num_heads=8, survival_probability=0.8):\n", " \"\"\"\n", " Creates a multi-head attention block with residual connections.\n", @@ -390,7 +685,8 @@ " x = LayerNormalization()(x)\n", " return x\n", "\n", - "def create_solarradiation_model(input_shape, folder_name, l2_lambda=0.005):\n", + "\n", + "def create_solarradiation_model(input_shape, folder_name, l2_lambda=0.005, min_output=0, max_output=1):\n", " \"\"\"\n", " Creates a deep learning model for solar radiation prediction using LSTM and attention mechanisms.\n", "\n", @@ -402,15 +698,16 @@ " inputs = Input(shape=input_shape)\n", "\n", " # Progressive hyperparameters for model architecture\n", - " survival_probs = [0.9, 0.8, 0.7] # Decreasing survival probabilities for deeper layers\n", - " attention_survival_probs = [0.85, 0.75, 0.65] # Survival probabilities for attention blocks\n", - " lstm_units = [256, 128, 64] # Decreasing number of units for LSTM layers\n", - " dropout_rates = [0.4, 0.3, 0.2] # Decreasing dropout rates\n", - " attention_heads = [32, 24, 16] # Decreasing number of attention heads\n", + " survival_probs = [0.9, 0.8, 0.7, 0.6] # Decreasing survival probabilities for deeper layers\n", + " attention_survival_probs = [0.85, 0.75, 0.65, 0.55] # Survival probabilities for attention blocks\n", + " lstm_units = [256, 128, 64, 32] # Decreasing number of units for LSTM layers\n", + " dropout_rates = [0.4, 0.3, 0.2, 0.2] # Decreasing dropout rates\n", + " attention_heads = [32, 24, 16, 8] # Decreasing number of attention heads\n", "\n", + " lstm_blocks = 4\n", " # Main network architecture\n", " x = inputs\n", - " for i in range(3):\n", + " for i in range(lstm_blocks):\n", " # LSTM layer with residual connections\n", " x = create_residual_lstm_layer(\n", " x,\n", @@ -427,7 +724,7 @@ " num_heads=attention_heads[i],\n", " survival_probability=attention_survival_probs[i]\n", " )\n", - " if i < 2: # No pooling after last LSTM layer\n", + " if i < lstm_blocks - 1: # No pooling after last LSTM layer\n", " x = MaxPooling1D()(x)\n", "\n", " # Final LSTM layer for sequence aggregation\n", @@ -441,8 +738,8 @@ " )\n", "\n", " # Dense layers for final prediction\n", - " dense_units = [64, 32]\n", - " dense_dropout = [0.2, 0.1]\n", + " dense_units = [128, 64, 32]\n", + " dense_dropout = [0.2, 0.1, 0.05]\n", "\n", " for units, dropout in zip(dense_units, dense_dropout):\n", " x = Dense(units, kernel_regularizer=regularizers.l2(l2_lambda))(x)\n", @@ -452,49 +749,61 @@ "\n", " # Output layer with value clipping\n", " outputs = Dense(1)(x)\n", - " outputs = Lambda(lambda x: tf.clip_by_value(x, 0, 1500))(outputs)\n", + " outputs = Lambda(lambda x: tf.clip_by_value(x, min_output, max_output))(outputs)\n", "\n", " # Model compilation\n", " model = Model(inputs=inputs, outputs=outputs, name=\"SolarRadiationModel\")\n", "\n", - " # Optimizer configuration\n", - " optimizer = AdamW(\n", - " learning_rate=0.0003,\n", - " beta_1=0.9,\n", - " beta_2=0.999,\n", - " epsilon=1e-07,\n", - " weight_decay=0.001\n", - " )\n", + " # Improved loss function\n", + " def hybrid_focal_loss(y_true, y_pred):\n", + " # MSE with focal weighting\n", + " mse = tf.square(y_true - y_pred)\n", + " error_ratio = tf.abs(y_true - y_pred) / (tf.abs(y_true) + 1.0)\n", + " focal_weight = tf.pow(error_ratio, 2)\n", + " weighted_mse = focal_weight * mse\n", "\n", - " # Custom evaluation metrics\n", + " # MAE component\n", + " mae = tf.abs(y_true - y_pred)\n", + "\n", + " return tf.reduce_mean(0.7 * weighted_mse + 0.3 * mae)\n", + "\n", + " # Custom metrics\n", " def rmse(y_true, y_pred):\n", - " \"\"\"Root Mean Squared Error\"\"\"\n", " return tf.sqrt(tf.reduce_mean(tf.square(y_true - y_pred)))\n", "\n", - " def mape(y_true, y_pred):\n", - " \"\"\"Mean Absolute Percentage Error\"\"\"\n", + " def custom_mape(y_true, y_pred):\n", " epsilon = 1e-7\n", - " return tf.reduce_mean(tf.abs((y_true - y_pred) / (y_true + epsilon))) * 100\n", + " diff = tf.abs((y_true - y_pred) / (y_true + epsilon))\n", + " diff = tf.clip_by_value(diff, 0, 1)\n", + " return tf.reduce_mean(diff) * 100\n", "\n", - " def hybrid_loss(y_true, y_pred):\n", - " \"\"\"Combined loss function: 70% MSE + 30% MAE\"\"\"\n", - " mse = tf.reduce_mean(tf.square(y_true - y_pred))\n", - " mae = tf.reduce_mean(tf.abs(y_true - y_pred))\n", - " return 0.7 * mse + 0.3 * mae\n", + " # Learning rate schedule\n", + " lr_schedule = tf.keras.optimizers.schedules.CosineDecayRestarts(\n", + " initial_learning_rate=0.0003,\n", + " first_decay_steps=1000,\n", + " t_mul=2.0,\n", + " m_mul=0.9,\n", + " alpha=1e-5\n", + " )\n", + "\n", + " # Optimizer\n", + " optimizer = AdamW(\n", + " learning_rate=lr_schedule,\n", + " beta_1=0.9,\n", + " beta_2=0.999,\n", + " epsilon=1e-7,\n", + " weight_decay=0.001,\n", + " amsgrad=True\n", + " )\n", "\n", - " # Model compilation with custom metrics\n", " model.compile(\n", " optimizer=optimizer,\n", - " loss=hybrid_loss,\n", - " metrics=[\n", - " 'mae',\n", - " rmse,\n", - " mape\n", - " ]\n", + " loss=hybrid_focal_loss,\n", + " metrics=['mse', 'mae', rmse, custom_mape]\n", " )\n", + "\n", " model.summary()\n", "\n", - " # Save model architecture visualization\n", " plot_model(model,\n", " to_file=f'{folder_name}_model_architecture.png',\n", " show_shapes=True,\n", @@ -525,13 +834,6 @@ " dict\n", " Dictionary containing all calculated metrics\n", " \"\"\"\n", - " import os\n", - " from datetime import datetime\n", - " import numpy as np\n", - " import pandas as pd\n", - " import matplotlib.pyplot as plt\n", - " import seaborn as sns\n", - " from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score, confusion_matrix\n", "\n", " # Data preparation\n", " y_true = np.array(y_true).ravel()\n", @@ -578,12 +880,12 @@ " print(f\"MAPE: {mape:.2f}%\")\n", "\n", " print(\"\\nPercentage Accuracy:\")\n", - " print(f\"Within ±5%: {within_5_percent*100:.1f}%\")\n", - " print(f\"Within ±10%: {within_10_percent*100:.1f}%\")\n", - " print(f\"Within ±20%: {within_20_percent*100:.1f}%\")\n", + " print(f\"Within ±5%: {within_5_percent * 100:.1f}%\")\n", + " print(f\"Within ±10%: {within_10_percent * 100:.1f}%\")\n", + " print(f\"Within ±20%: {within_20_percent * 100:.1f}%\")\n", "\n", " print(\"\\nLevel Accuracy:\")\n", - " print(f\"Level Accuracy: {level_accuracy*100:.1f}%\")\n", + " print(f\"Level Accuracy: {level_accuracy * 100:.1f}%\")\n", "\n", " # Confusion matrix for radiation levels\n", " cm = confusion_matrix(y_true_levels, y_pred_levels)\n", @@ -622,8 +924,6 @@ " # Visualizations\n", " if folder_name is not None:\n", " try:\n", - " os.makedirs(folder_name, exist_ok=True)\n", - " timestamp = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n", "\n", " # Figure 1: Main analysis plots\n", " plt.figure(figsize=(20, 15))\n", @@ -679,7 +979,7 @@ " plt.yticks(rotation=45)\n", "\n", " plt.tight_layout()\n", - " filename = os.path.join(folder_name, f'radiation_analysis_{timestamp}.png')\n", + " filename = f'{folder_name}_radiation_analysis.png'\n", " plt.savefig(filename, dpi=300, bbox_inches='tight')\n", " print(f\"\\nPlot saved as: {filename}\")\n", " plt.close()\n", @@ -732,7 +1032,6 @@ " folder_name : str\n", " Directory to save the plots and metrics\n", " \"\"\"\n", - " import os\n", "\n", " try:\n", " # Create figure\n", @@ -761,9 +1060,8 @@ " plt.tight_layout()\n", "\n", " if folder_name is not None:\n", - " os.makedirs(folder_name, exist_ok=True)\n", " # Generate filename with timestamp\n", - " filename = os.path.join(folder_name, 'training_history.png')\n", + " filename = f'{folder_name}_training_history.png' # Rimossa parentesi extra\n", "\n", " # Save figure\n", " plt.savefig(filename, dpi=300, bbox_inches='tight')\n", @@ -775,11 +1073,10 @@ " 'training_loss': history.history['loss'],\n", " 'validation_loss': history.history['val_loss'],\n", " 'training_mae': history.history['mae'],\n", - " 'validation_mae': history.history['val_mae']\n", - " })\n", + " 'validation_mae': history.history['val_mae']})\n", "\n", " if folder_name is not None:\n", - " csv_filename = os.path.join(folder_name, 'training_history.csv')\n", + " csv_filename = f'{folder_name}_training_history.csv' # Rimossa parentesi extra\n", " history_df.to_csv(csv_filename, index=False)\n", " print(f\"Training history data saved as: {csv_filename}\")\n", "\n", @@ -796,7 +1093,7 @@ "\n", " if folder_name is not None:\n", " # Save statistics in JSON format\n", - " stats_filename = os.path.join(folder_name, 'training_stats.json')\n", + " stats_filename = f'{folder_name}_training_stats.json' # Rimossa parentesi extra\n", " with open(stats_filename, 'w') as f:\n", " json.dump(final_stats, f, indent=4)\n", " print(f\"Final statistics saved as: {stats_filename}\")\n", @@ -816,37 +1113,32 @@ "\n", "def train_hybrid_model(model, X_train, y_train, X_test, y_test, epochs=100, batch_size=32, folder_name='solarradiation'):\n", " \"\"\"\n", - " Advanced training function for the hybrid solar radiation model with detailed monitoring\n", - " and training management.\n", - "\n", - " Parameters:\n", - " -----------\n", - " model : keras.Model\n", - " Compiled hybrid model\n", - " X_train : numpy.ndarray\n", - " Training data\n", - " y_train : numpy.ndarray\n", - " Training targets\n", - " X_test : numpy.ndarray\n", - " Validation data\n", - " y_test : numpy.ndarray\n", - " Validation targets\n", - " epochs : int, optional\n", - " Maximum number of training epochs\n", - " batch_size : int, optional\n", - " Batch size\n", - " folder_name : str, optional\n", - " Directory for saving model artifacts\n", - "\n", - " Returns:\n", - " --------\n", - " history : keras.callbacks.History\n", - " Training history with all metrics\n", + " Advanced training function for the hybrid solar radiation model\n", " \"\"\"\n", "\n", - " # Advanced training callbacks\n", + " def calculate_metrics(y_true, y_pred):\n", + " \"\"\"Helper function to calculate metrics safely\"\"\"\n", + " y_true = np.array(y_true).flatten()\n", + " y_pred = np.array(y_pred).flatten()\n", + "\n", + " # Count out of range predictions\n", + " out_of_range = np.sum((y_pred < 0) | (y_pred > 1500))\n", + "\n", + " # Calculate MAPE with clipping to avoid extreme values\n", + " diff = np.abs((y_true - y_pred) / (y_true + 1e-7))\n", + " diff = np.clip(diff, 0, 1) # Clip to maximum 100% error\n", + " mape = np.mean(diff) * 100\n", + "\n", + " # Calculate accuracy within 10%\n", + " within_10_percent = np.mean(diff <= 0.10) * 100\n", + "\n", + " # Calculate MAE and RMSE\n", + " mae = np.mean(np.abs(y_true - y_pred))\n", + " rmse = np.sqrt(np.mean(np.square(y_true - y_pred)))\n", + "\n", + " return out_of_range, mape, within_10_percent, mae, rmse\n", + "\n", " callbacks = [\n", - " # Early Stopping\n", " EarlyStopping(\n", " monitor='val_loss',\n", " patience=15,\n", @@ -855,9 +1147,8 @@ " verbose=1,\n", " min_delta=1e-4\n", " ),\n", - " # ReduceLROnPlateau for MAE\n", " ReduceLROnPlateau(\n", - " monitor='mae',\n", + " monitor='val_loss',\n", " factor=0.2,\n", " patience=5,\n", " verbose=1,\n", @@ -866,18 +1157,6 @@ " cooldown=3,\n", " min_lr=1e-7\n", " ),\n", - " # ReduceLROnPlateau for loss\n", - " ReduceLROnPlateau(\n", - " monitor='val_loss',\n", - " factor=0.2,\n", - " patience=3,\n", - " verbose=1,\n", - " mode='min',\n", - " min_delta=1e-4,\n", - " cooldown=2,\n", - " min_lr=1e-7\n", - " ),\n", - " # Model Checkpoint\n", " tf.keras.callbacks.ModelCheckpoint(\n", " filepath=f'{folder_name}_best_model.h5',\n", " monitor='val_loss',\n", @@ -885,26 +1164,25 @@ " mode='min',\n", " save_weights_only=False\n", " ),\n", - " # TensorBoard\n", " tf.keras.callbacks.TensorBoard(\n", - " log_dir=f'./logs_{folder_name}',\n", + " log_dir=f'./{folder_name}_logs',\n", " histogram_freq=1,\n", " write_graph=True,\n", - " update_freq='epoch',\n", - " profile_batch=0\n", + " update_freq='epoch'\n", " ),\n", - " # Lambda Callback for solar radiation monitoring\n", " tf.keras.callbacks.LambdaCallback(\n", " on_epoch_end=lambda epoch, logs: (\n", - " lambda y_pred: print(\n", - " f\"\\nEpoch {epoch + 1}:\"\n", - " f\"\\nPredictions out of range (0-1500 W/m²): \"\n", - " f\"{np.sum((y_pred < 0) | (y_pred > 1500))}\"\n", - " f\"\\nMAPE: {np.mean(np.abs((y_test - y_pred) / (y_test + 1e-7))) * 100:.2f}%\"\n", - " f\"\\nPredictions within ±10%: \"\n", - " f\"{np.mean(np.abs((y_pred - y_test) / (y_test + 1e-7)) <= 0.10) * 100:.2f}%\"\n", - " )\n", - " )(model.predict(X_test)) if epoch % 20 == 0 else None\n", + " print(f\"\\nEpoch {epoch + 1} Detailed Metrics:\") and\n", + " (lambda: (\n", + " y_pred := model.predict(X_test, verbose=0),\n", + " metrics := calculate_metrics(y_test, y_pred),\n", + " print(f\"Out of range: {metrics[0]} predictions\"),\n", + " print(f\"MAPE: {metrics[1]:.2f}%\"),\n", + " print(f\"Within ±10%: {metrics[2]:.2f}%\"),\n", + " print(f\"MAE: {metrics[3]:.2f}\"),\n", + " print(f\"RMSE: {metrics[4]:.2f}\")\n", + " ))()\n", + " ) if epoch % 5 == 0 else None\n", " )\n", " ]\n", "\n", @@ -916,24 +1194,21 @@ " batch_size=batch_size,\n", " callbacks=callbacks,\n", " verbose=1,\n", - " shuffle=False,\n", - " validation_freq=1,\n", + " shuffle=False\n", " )\n", "\n", - " # Post-training analysis\n", " print(\"\\nTraining completed successfully!\")\n", "\n", - " # Final evaluation on test set\n", - " test_loss, test_mae, test_mse = model.evaluate(X_test, y_test, verbose=0)\n", - " print(f\"\\nFinal metrics on test set:\")\n", - " print(f\"Loss: {test_loss:.4f}\")\n", - " print(f\"MAE: {test_mae:.4f}\")\n", - " print(f\"MSE: {test_mse:.4f}\")\n", + " # Final evaluation\n", + " final_pred = model.predict(X_test, verbose=0)\n", + " metrics = calculate_metrics(y_test, final_pred)\n", "\n", - " # Prediction analysis\n", - " predictions = model.predict(X_test)\n", - " out_of_range = np.sum((predictions < 0) | (predictions > 11))\n", - " print(f\"\\nOut of range predictions: {out_of_range} ({out_of_range / len(predictions) * 100:.2f}%)\")\n", + " print(\"\\nFinal Model Performance:\")\n", + " print(f\"Out of range predictions: {metrics[0]} ({metrics[0] / len(y_test) * 100:.2f}%)\")\n", + " print(f\"MAPE: {metrics[1]:.2f}%\")\n", + " print(f\"Predictions within ±10%: {metrics[2]:.2f}%\")\n", + " print(f\"MAE: {metrics[3]:.2f}\")\n", + " print(f\"RMSE: {metrics[4]:.2f}\")\n", "\n", " plot_training_history(history, folder_name=folder_name)\n", "\n", @@ -944,7 +1219,6 @@ " raise\n", "\n", " finally:\n", - " # Memory cleanup\n", " tf.keras.backend.clear_session()\n", "\n", "\n", @@ -976,8 +1250,7 @@ " dates_pre_2010 = df[mask_pre_2010]['datetime'].iloc[sequence_length - 1:]\n", " predictions_df = pd.DataFrame({\n", " 'datetime': dates_pre_2010,\n", - " 'solarradiation_predicted': predictions.flatten()\n", - " })\n", + " 'solarradiation_predicted': predictions.flatten()})\n", "\n", " # Merge with original dataset\n", " df = df.merge(predictions_df, on='datetime', how='left')\n", @@ -991,119 +1264,613 @@ " print(f\"Added {len(predictions)} predictions to dataset\")\n", " print(f\"Rows with solar radiation after integration: {df['solarradiation'].notna().sum()}\")\n", "\n", - " return df\n", - "\n", - "\n", - "def train_solarradiation_bounded_model(df):\n", - " \"\"\"\n", - " Training of the model with specific constraints for solar radiation\n", - " \"\"\"\n", - " print(\"Initializing solar radiation model training...\")\n", - "\n", - " try:\n", - " # Data preparation\n", - " print(\"\\n1. Preparing data...\")\n", - " X_train_seq, X_test_seq, y_train, y_test, scaler, features, X_to_predict_seq = prepare_hybrid_data(df)\n", - "\n", - " print(f\"Training data shape: {X_train_seq.shape}\")\n", - " print(f\"Test data shape: {X_test_seq.shape}\")\n", - "\n", - " # Data quality verification\n", - " if np.isnan(X_train_seq).any() or np.isnan(y_train).any():\n", - " raise ValueError(\"Found NaN values in training data\")\n", - "\n", - " # Model creation\n", - " print(\"\\n2. Creating model...\")\n", - " input_shape = (X_train_seq.shape[1], X_train_seq.shape[2])\n", - " model = create_solarradiation_model(input_shape, folder_name)\n", - "\n", - " print(\"\\n4. Starting training...\")\n", - " history = train_hybrid_model(\n", - " model=model,\n", - " X_train=X_train_seq,\n", - " y_train=y_train,\n", - " X_test=X_test_seq,\n", - " y_test=y_test,\n", - " epochs=100,\n", - " batch_size=128,\n", - " folder_name=folder_name\n", - " )\n", - "\n", - " print(\"\\n5. Generating predictions...\")\n", - " predictions = model.predict(X_test_seq)\n", - " predictions = np.clip(predictions, 0, 11)\n", - "\n", - " print(\"\\n6. Evaluating model...\")\n", - " metrics = evaluate_solarradiation_predictions(y_test, predictions, folder_name=folder_name)\n", - "\n", - " # Create results dictionary\n", - " training_results = {\n", - " 'model_params': {\n", - " 'input_shape': input_shape,\n", - " 'n_features': len(features),\n", - " 'sequence_length': X_train_seq.shape[1]\n", - " },\n", - " 'training_params': {\n", - " 'batch_size': 32,\n", - " 'total_epochs': len(history.history['loss']),\n", - " 'best_epoch': np.argmin(history.history['val_loss']) + 1\n", - " },\n", - " 'performance_metrics': {\n", - " 'final_loss': float(history.history['val_loss'][-1]),\n", - " 'final_mae': float(history.history['val_mae'][-1]),\n", - " 'best_val_loss': float(min(history.history['val_loss'])),\n", - " 'out_of_range_predictions': int(np.sum((predictions < 0) | (predictions > 11)))\n", - " }\n", - " }\n", - "\n", - " print(\"\\n7. Predicting missing data...\")\n", - " to_predict_predictions = model.predict(X_to_predict_seq)\n", - " to_predict_predictions = np.clip(to_predict_predictions, 0, 11)\n", - "\n", - " print(\"\\n8. Integrating predictions into original dataset...\")\n", - " df_updated = integrate_predictions(df.copy(), to_predict_predictions)\n", - "\n", - " df_updated.to_parquet('../../sources/weather_data_solarradiation.parquet')\n", - "\n", - " # Add prediction statistics to training_results\n", - " training_results['prediction_stats'] = {\n", - " 'n_predictions_added': len(to_predict_predictions),\n", - " 'mean_predicted_solarradiation': float(to_predict_predictions.mean()),\n", - " 'min_predicted_solarradiation': float(to_predict_predictions.min()),\n", - " 'max_predicted_solarradiation': float(to_predict_predictions.max()),\n", - " }\n", - "\n", - " print(\"\\nTraining completed successfully!\")\n", - "\n", - " return model, scaler, features, history, predictions, y_test, metrics, training_results\n", - "\n", - " except Exception as e:\n", - " print(f\"\\nError during training: {str(e)}\")\n", - " raise\n", - "\n", - " finally:\n", - " # Memory cleanup\n", - " tf.keras.backend.clear_session()" + " return df" ], "outputs": [], "execution_count": null }, { "cell_type": "code", + "execution_count": 5, "id": "initial_id", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initializing solar radiation model training...\n", + "\n", + "1. Preparing data...\n", + "\n", + "Selected features:\n", + "Number of features: 40\n", + "Features list: ['uvindex', 'cloudcover', 'visibility', 'temp', 'pressure', 'humidity', 'solar_elevation', 'solar_angle', 'day_length', 'hour_sin', 'hour_cos', 'day_of_year_sin', 'day_of_year_cos', 'month_sin', 'month_cos', 'clear_sky_index', 'atmospheric_attenuation', 'theoretical_radiation', 'expected_radiation', 'cloud_elevation', 'visibility_elevation', 'uv_cloud_interaction', 'temp_radiation_potential', 'cloud_rolling_12h', 'temp_rolling_12h', 'uv_rolling_12h', 'cloudcover_rolling_mean_6h', 'temp_rolling_mean_6h', 'temp_1h_lag', 'cloudcover_1h_lag', 'humidity_1h_lag', 'uv_lag_1h', 'season_Spring', 'season_Summer', 'season_Autumn', 'season_Winter', 'time_period_Morning', 'time_period_Afternoon', 'time_period_Evening', 'time_period_Night']\n", + "Training data shape: (103798, 24, 40)\n", + "Test data shape: (25933, 24, 40)\n" + ] + } + ], "source": [ "df = pd.read_parquet('../../sources/weather_data_uvindex.parquet')\n", "\n", - "model, scaler, features, history, predictions, y_test, metrics, training_results = train_solarradiation_bounded_model(df)" - ], - "outputs": [], - "execution_count": null + "print(\"Initializing solar radiation model training...\")\n", + "\n", + "# Data preparation\n", + "print(\"\\n1. Preparing data...\")\n", + "X_train_seq, X_test_seq, y_train, y_test, feature_scaler, target_scaler, features, X_to_predict_seq = prepare_hybrid_data(df)\n", + "\n", + "print(f\"Training data shape: {X_train_seq.shape}\")\n", + "print(f\"Test data shape: {X_test_seq.shape}\")\n", + "\n", + "# Save or load scaler and features\n", + "feature_scaler_path = f'{folder_name}_scale_X.joblib'\n", + "target_scaler_path = f'{folder_name}_scale_y.joblib'\n", + "features_path = f'{folder_name}_features.json'\n", + "model_path = f'{folder_name}_best_model.h5'\n", + "history_path = f'{folder_name}_training_history.json'\n", + "\n", + "if os.path.exists(feature_scaler_path):\n", + " print(f\"Loading existing scaler X from: {feature_scaler_path}\")\n", + " scaler = joblib.load(feature_scaler_path)\n", + "else:\n", + " print(f\"Saving scaler X to: {feature_scaler_path}\")\n", + " joblib.dump(feature_scaler, feature_scaler_path)\n", + "\n", + "if os.path.exists(target_scaler_path):\n", + " print(f\"Loading existing scaler X from: {target_scaler_path}\")\n", + " scaler = joblib.load(target_scaler_path)\n", + "else:\n", + " print(f\"Saving scaler X to: {target_scaler_path}\")\n", + " joblib.dump(target_scaler, target_scaler_path)\n", + "\n", + "if os.path.exists(features_path):\n", + " print(f\"Loading existing features from: {features_path}\")\n", + " with open(features_path, 'r') as f:\n", + " features = json.load(f)\n", + "else:\n", + " print(f\"Saving features to: {features_path}\")\n", + " with open(features_path, 'w') as f:\n", + " json.dump(features, f)\n", + "\n", + "# Data quality verification\n", + "if np.isnan(X_train_seq).any() or np.isnan(y_train).any():\n", + " raise ValueError(\"Found NaN values in training data\")" + ] }, { "cell_type": "code", + "execution_count": 6, + "id": "44749f6a-8941-41e8-8105-c36417245ed5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "2. Creating model...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2024-11-20 18:26:58.091461: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1639] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 43404 MB memory: -> device: 0, name: NVIDIA L40, pci bus id: 0000:a1:00.0, compute capability: 8.9\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model: \"SolarRadiationModel\"\n", + "__________________________________________________________________________________________________\n", + " Layer (type) Output Shape Param # Connected to \n", + "==================================================================================================\n", + " input_1 (InputLayer) [(None, 24, 40)] 0 [] \n", + " \n", + " bidirectional (Bidirection (None, 24, 512) 608256 ['input_1[0][0]'] \n", + " al) \n", + " \n", + " layer_normalization (Layer (None, 24, 512) 1024 ['bidirectional[0][0]'] \n", + " Normalization) \n", + " \n", + " dropout (Dropout) (None, 24, 512) 0 ['layer_normalization[0][0]'] \n", + " \n", + " dense (Dense) (None, 24, 512) 20992 ['input_1[0][0]'] \n", + " \n", + " stochastic_depth (Stochast (None, 24, 512) 0 ['dropout[0][0]', \n", + " icDepth) 'dense[0][0]'] \n", + " \n", + " multi_head_attention (Mult (None, 24, 512) 1680230 ['stochastic_depth[0][0]', \n", + " iHeadAttention) 4 'stochastic_depth[0][0]'] \n", + " \n", + " stochastic_depth_1 (Stocha (None, 24, 512) 0 ['stochastic_depth[0][0]', \n", + " sticDepth) 'multi_head_attention[0][0]']\n", + " \n", + " layer_normalization_1 (Lay (None, 24, 512) 1024 ['stochastic_depth_1[0][0]'] \n", + " erNormalization) \n", + " \n", + " max_pooling1d (MaxPooling1 (None, 12, 512) 0 ['layer_normalization_1[0][0]'\n", + " D) ] \n", + " \n", + " bidirectional_1 (Bidirecti (None, 12, 256) 656384 ['max_pooling1d[0][0]'] \n", + " onal) \n", + " \n", + " layer_normalization_2 (Lay (None, 12, 256) 512 ['bidirectional_1[0][0]'] \n", + " erNormalization) \n", + " \n", + " dropout_1 (Dropout) (None, 12, 256) 0 ['layer_normalization_2[0][0]'\n", + " ] \n", + " \n", + " dense_1 (Dense) (None, 12, 256) 131328 ['max_pooling1d[0][0]'] \n", + " \n", + " stochastic_depth_2 (Stocha (None, 12, 256) 0 ['dropout_1[0][0]', \n", + " sticDepth) 'dense_1[0][0]'] \n", + " \n", + " multi_head_attention_1 (Mu (None, 12, 256) 3155200 ['stochastic_depth_2[0][0]', \n", + " ltiHeadAttention) 'stochastic_depth_2[0][0]'] \n", + " \n", + " stochastic_depth_3 (Stocha (None, 12, 256) 0 ['stochastic_depth_2[0][0]', \n", + " sticDepth) 'multi_head_attention_1[0][0]\n", + " '] \n", + " \n", + " layer_normalization_3 (Lay (None, 12, 256) 512 ['stochastic_depth_3[0][0]'] \n", + " erNormalization) \n", + " \n", + " max_pooling1d_1 (MaxPoolin (None, 6, 256) 0 ['layer_normalization_3[0][0]'\n", + " g1D) ] \n", + " \n", + " bidirectional_2 (Bidirecti (None, 6, 128) 164352 ['max_pooling1d_1[0][0]'] \n", + " onal) \n", + " \n", + " layer_normalization_4 (Lay (None, 6, 128) 256 ['bidirectional_2[0][0]'] \n", + " erNormalization) \n", + " \n", + " dropout_2 (Dropout) (None, 6, 128) 0 ['layer_normalization_4[0][0]'\n", + " ] \n", + " \n", + " dense_2 (Dense) (None, 6, 128) 32896 ['max_pooling1d_1[0][0]'] \n", + " \n", + " stochastic_depth_4 (Stocha (None, 6, 128) 0 ['dropout_2[0][0]', \n", + " sticDepth) 'dense_2[0][0]'] \n", + " \n", + " multi_head_attention_2 (Mu (None, 6, 128) 527488 ['stochastic_depth_4[0][0]', \n", + " ltiHeadAttention) 'stochastic_depth_4[0][0]'] \n", + " \n", + " stochastic_depth_5 (Stocha (None, 6, 128) 0 ['stochastic_depth_4[0][0]', \n", + " sticDepth) 'multi_head_attention_2[0][0]\n", + " '] \n", + " \n", + " layer_normalization_5 (Lay (None, 6, 128) 256 ['stochastic_depth_5[0][0]'] \n", + " erNormalization) \n", + " \n", + " bidirectional_3 (Bidirecti (None, 64) 41216 ['layer_normalization_5[0][0]'\n", + " onal) ] \n", + " \n", + " layer_normalization_6 (Lay (None, 64) 128 ['bidirectional_3[0][0]'] \n", + " erNormalization) \n", + " \n", + " dropout_3 (Dropout) (None, 64) 0 ['layer_normalization_6[0][0]'\n", + " ] \n", + " \n", + " dense_3 (Dense) (None, 64) 4160 ['dropout_3[0][0]'] \n", + " \n", + " batch_normalization (Batch (None, 64) 256 ['dense_3[0][0]'] \n", + " Normalization) \n", + " \n", + " activation (Activation) (None, 64) 0 ['batch_normalization[0][0]'] \n", + " \n", + " dropout_4 (Dropout) (None, 64) 0 ['activation[0][0]'] \n", + " \n", + " dense_4 (Dense) (None, 32) 2080 ['dropout_4[0][0]'] \n", + " \n", + " batch_normalization_1 (Bat (None, 32) 128 ['dense_4[0][0]'] \n", + " chNormalization) \n", + " \n", + " activation_1 (Activation) (None, 32) 0 ['batch_normalization_1[0][0]'\n", + " ] \n", + " \n", + " dropout_5 (Dropout) (None, 32) 0 ['activation_1[0][0]'] \n", + " \n", + " dense_5 (Dense) (None, 1) 33 ['dropout_5[0][0]'] \n", + " \n", + " lambda (Lambda) (None, 1) 0 ['dense_5[0][0]'] \n", + " \n", + "==================================================================================================\n", + "Total params: 22150785 (84.50 MB)\n", + "Trainable params: 22150593 (84.50 MB)\n", + "Non-trainable params: 192 (768.00 Byte)\n", + "__________________________________________________________________________________________________\n", + "\n", + "4. Starting training...\n", + "Epoch 1/100\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2024-11-20 18:28:08.462396: I tensorflow/compiler/xla/stream_executor/cuda/cuda_blas.cc:606] TensorFloat-32 will be used for the matrix multiplication. This will only be logged once.\n", + "2024-11-20 18:28:08.551588: I tensorflow/compiler/xla/stream_executor/cuda/cuda_dnn.cc:432] Loaded cuDNN version 8905\n", + "2024-11-20 18:28:08.771296: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x7494b4d65840 initialized for platform CUDA (this does not guarantee that XLA will be used). Devices:\n", + "2024-11-20 18:28:08.771333: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): NVIDIA L40, Compute Capability 8.9\n", + "2024-11-20 18:28:08.779091: I tensorflow/compiler/mlir/tensorflow/utils/dump_mlir_util.cc:255] disabling MLIR crash reproducer, set env var `MLIR_CRASH_REPRODUCER_DIRECTORY` to enable.\n", + "2024-11-20 18:28:08.849938: I tensorflow/tsl/platform/default/subprocess.cc:304] Start cannot spawn child process: No such file or directory\n", + "2024-11-20 18:28:08.914097: I ./tensorflow/compiler/jit/device_compiler.h:186] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "810/811 [============================>.] - ETA: 0s - loss: 72528.1172 - mse: 106644.4453 - mae: 187.8485 - rmse: 303.3813 - custom_mape: 54.8740" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.11/dist-packages/keras/src/engine/training.py:3000: UserWarning: You are saving your model as an HDF5 file via `model.save()`. This file format is considered legacy. We recommend using instead the native Keras format, e.g. `model.save('my_model.keras')`.\n", + " saving_api.save_model(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Epoch 1 Detailed Metrics:\n", + "811/811 [==============================] - 59s 47ms/step - loss: 72456.4219 - mse: 106540.3906 - mae: 187.7001 - rmse: 303.1588 - custom_mape: 54.8602 - val_loss: 65954.8828 - val_mse: 98078.7031 - val_mae: 177.0511 - val_rmse: 289.9380 - val_custom_mape: 52.7771 - lr: 2.5941e-05\n", + "Epoch 2/100\n", + "811/811 [==============================] - 35s 43ms/step - loss: 69535.9297 - mse: 104347.7812 - mae: 185.7435 - rmse: 299.4631 - custom_mape: 53.3868 - val_loss: 63015.7383 - val_mse: 95844.1562 - val_mae: 175.0045 - val_rmse: 286.3577 - val_custom_mape: 52.6138 - lr: 2.1071e-04\n", + "Epoch 3/100\n", + "811/811 [==============================] - 34s 42ms/step - loss: 65040.6328 - mse: 100867.1875 - mae: 182.4250 - rmse: 293.5602 - custom_mape: 52.5410 - val_loss: 56593.6914 - val_mse: 90806.5000 - val_mae: 170.5536 - val_rmse: 278.2007 - val_custom_mape: 51.3653 - lr: 5.0264e-05\n", + "Epoch 4/100\n", + "811/811 [==============================] - 35s 43ms/step - loss: 63179.4570 - mse: 99390.6328 - mae: 181.0240 - rmse: 291.0518 - custom_mape: 52.2108 - val_loss: 54896.5859 - val_mse: 89427.9453 - val_mae: 169.4865 - val_rmse: 276.2857 - val_custom_mape: 51.1932 - lr: 2.4079e-04\n", + "Epoch 5/100\n", + "811/811 [==============================] - 36s 44ms/step - loss: 58537.2383 - mse: 95561.4453 - mae: 177.0757 - rmse: 284.3125 - custom_mape: 51.0609 - val_loss: 48058.6758 - val_mse: 83616.4297 - val_mae: 162.7125 - val_rmse: 266.4749 - val_custom_mape: 48.8749 - lr: 2.0369e-04\n", + "Epoch 6/100\n", + "810/811 [============================>.] - ETA: 0s - loss: 52993.6406 - mse: 90827.1172 - mae: 172.1619 - rmse: 275.9435 - custom_mape: 49.6688\n", + "Epoch 6 Detailed Metrics:\n", + "811/811 [==============================] - 35s 43ms/step - loss: 52937.2539 - mse: 90734.0391 - mae: 172.0164 - rmse: 275.7198 - custom_mape: 49.6529 - val_loss: 44455.3203 - val_mse: 80384.6250 - val_mae: 160.1475 - val_rmse: 260.5288 - val_custom_mape: 48.5323 - lr: 1.3436e-04\n", + "Epoch 7/100\n", + "811/811 [==============================] - 34s 42ms/step - loss: 49213.3164 - mse: 87367.3594 - mae: 168.3520 - rmse: 269.5628 - custom_mape: 48.4534 - val_loss: 40941.0117 - val_mse: 77138.5859 - val_mae: 156.7561 - val_rmse: 255.2473 - val_custom_mape: 47.8560 - lr: 5.9983e-05\n", + "Epoch 8/100\n", + "811/811 [==============================] - 33s 41ms/step - loss: 47519.0391 - mse: 85789.4453 - mae: 166.6271 - rmse: 266.6346 - custom_mape: 48.0879 - val_loss: 41349.0312 - val_mse: 77484.2734 - val_mae: 156.9061 - val_rmse: 255.2714 - val_custom_mape: 47.6252 - lr: 9.7321e-06\n", + "Epoch 9/100\n", + "811/811 [==============================] - 34s 42ms/step - loss: 46780.1719 - mse: 85090.1484 - mae: 165.8883 - rmse: 265.3610 - custom_mape: 47.9995 - val_loss: 40748.4062 - val_mse: 76847.7734 - val_mae: 156.1971 - val_rmse: 253.6026 - val_custom_mape: 48.0470 - lr: 2.1795e-04\n", + "Epoch 10/100\n", + "811/811 [==============================] - 34s 42ms/step - loss: 42443.9609 - mse: 80814.5703 - mae: 160.8849 - rmse: 257.1220 - custom_mape: 46.6063 - val_loss: 35794.1914 - val_mse: 71881.1797 - val_mae: 149.8344 - val_rmse: 244.4584 - val_custom_mape: 45.0777 - lr: 2.0849e-04\n", + "Epoch 11/100\n", + "810/811 [============================>.] - ETA: 0s - loss: 37364.0820 - mse: 75557.8281 - mae: 154.7132 - rmse: 246.8283 - custom_mape: 45.6366\n", + "Epoch 11 Detailed Metrics:\n", + "811/811 [==============================] - 35s 43ms/step - loss: 37322.7383 - mse: 75477.1875 - mae: 154.5700 - rmse: 246.6078 - custom_mape: 45.6219 - val_loss: 29906.3047 - val_mse: 65430.3633 - val_mae: 141.8013 - val_rmse: 231.2519 - val_custom_mape: 42.4489 - lr: 1.8906e-04\n", + "Epoch 12/100\n", + "811/811 [==============================] - 35s 43ms/step - loss: 32976.7734 - mse: 70634.2344 - mae: 148.5551 - rmse: 236.7462 - custom_mape: 44.1733 - val_loss: 29356.2773 - val_mse: 64463.9414 - val_mae: 141.1121 - val_rmse: 229.5340 - val_custom_mape: 42.9936 - lr: 1.6162e-04\n", + "Epoch 13/100\n", + "811/811 [==============================] - 37s 46ms/step - loss: 29592.6035 - mse: 66591.3828 - mae: 143.4485 - rmse: 228.2309 - custom_mape: 43.5998 - val_loss: 22979.4648 - val_mse: 56865.0938 - val_mae: 131.7958 - val_rmse: 214.5151 - val_custom_mape: 39.4901 - lr: 1.2891e-04\n", + "Epoch 14/100\n", + "811/811 [==============================] - 34s 42ms/step - loss: 26951.7656 - mse: 63337.9648 - mae: 139.0988 - rmse: 221.0572 - custom_mape: 41.7504 - val_loss: 25277.5273 - val_mse: 59844.8008 - val_mae: 134.7617 - val_rmse: 219.8931 - val_custom_mape: 40.0160 - lr: 9.4242e-05\n", + "Epoch 15/100\n", + "811/811 [==============================] - 32s 39ms/step - loss: 25191.9902 - mse: 61055.3008 - mae: 135.9996 - rmse: 215.9450 - custom_mape: 40.7117 - val_loss: 20492.2637 - val_mse: 53286.4492 - val_mae: 126.0936 - val_rmse: 205.3292 - val_custom_mape: 37.5140 - lr: 6.1091e-05\n", + "Epoch 16/100\n", + "810/811 [============================>.] - ETA: 0s - loss: 24165.8750 - mse: 59707.5938 - mae: 134.1485 - rmse: 212.9445 - custom_mape: 40.2365\n", + "Epoch 16 Detailed Metrics:\n", + "811/811 [==============================] - 32s 39ms/step - loss: 24138.5391 - mse: 59641.1523 - mae: 134.0126 - rmse: 212.7257 - custom_mape: 40.2135 - val_loss: 18706.9590 - val_mse: 51048.4062 - val_mae: 124.1925 - val_rmse: 201.2298 - val_custom_mape: 37.6503 - lr: 3.2793e-05\n", + "Epoch 17/100\n", + "811/811 [==============================] - 32s 39ms/step - loss: 23539.9023 - mse: 58823.9805 - mae: 132.9010 - rmse: 210.9564 - custom_mape: 40.2574 - val_loss: 18301.4316 - val_mse: 49967.2422 - val_mae: 121.6120 - val_rmse: 197.4946 - val_custom_mape: 36.3558 - lr: 1.2196e-05\n", + "Epoch 18/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 23317.7012 - mse: 58529.7852 - mae: 132.4304 - rmse: 210.2198 - custom_mape: 39.6456 - val_loss: 18765.3145 - val_mse: 50811.3203 - val_mae: 123.1689 - val_rmse: 199.7548 - val_custom_mape: 37.1078 - lr: 1.3695e-06\n", + "Epoch 19/100\n", + "811/811 [==============================] - 30s 37ms/step - loss: 22958.7871 - mse: 58021.4062 - mae: 131.7025 - rmse: 209.0721 - custom_mape: 39.5251 - val_loss: 22003.3301 - val_mse: 53933.9766 - val_mae: 125.5596 - val_rmse: 204.8436 - val_custom_mape: 36.6993 - lr: 1.9652e-04\n", + "Epoch 20/100\n", + "811/811 [==============================] - 31s 39ms/step - loss: 20586.0566 - mse: 54516.5820 - mae: 126.9349 - rmse: 201.2817 - custom_mape: 40.1354 - val_loss: 19601.9219 - val_mse: 51482.2773 - val_mae: 123.8536 - val_rmse: 202.0632 - val_custom_mape: 37.4784 - lr: 1.9403e-04\n", + "Epoch 21/100\n", + "810/811 [============================>.] - ETA: 0s - loss: 18059.2461 - mse: 50707.9844 - mae: 121.4836 - rmse: 192.6480 - custom_mape: 37.9434\n", + "Epoch 21 Detailed Metrics:\n", + "811/811 [==============================] - 30s 37ms/step - loss: 18040.1738 - mse: 50651.9258 - mae: 121.3665 - rmse: 192.4565 - custom_mape: 37.9314 - val_loss: 27332.0293 - val_mse: 61814.3359 - val_mae: 138.1345 - val_rmse: 223.8045 - val_custom_mape: 41.7334 - lr: 1.8912e-04\n", + "Epoch 22/100\n", + "811/811 [==============================] - 32s 39ms/step - loss: 15813.7461 - mse: 47093.9961 - mae: 116.1009 - rmse: 183.7298 - custom_mape: 36.6234 - val_loss: 15547.1533 - val_mse: 25035.1250 - val_mae: 83.4982 - val_rmse: 138.2488 - val_custom_mape: 26.6810 - lr: 1.8191e-04\n", + "Epoch 23/100\n", + "811/811 [==============================] - 30s 37ms/step - loss: 14064.2656 - mse: 44066.1055 - mae: 111.5707 - rmse: 176.2691 - custom_mape: 35.6786 - val_loss: 15586.9551 - val_mse: 33592.5234 - val_mae: 96.0797 - val_rmse: 154.1422 - val_custom_mape: 30.0333 - lr: 1.7260e-04\n", + "Epoch 24/100\n", + "811/811 [==============================] - 30s 37ms/step - loss: 13045.5820 - mse: 41777.5039 - mae: 108.8138 - rmse: 172.3399 - custom_mape: 35.9103 - val_loss: 21892.5098 - val_mse: 38512.5820 - val_mae: 102.0757 - val_rmse: 169.1723 - val_custom_mape: 30.7781 - lr: 1.6140e-04\n", + "Epoch 25/100\n", + "811/811 [==============================] - 30s 38ms/step - loss: 11775.0107 - mse: 39650.0430 - mae: 105.5830 - rmse: 166.6329 - custom_mape: 34.5414 - val_loss: 15617.9189 - val_mse: 24887.7910 - val_mae: 81.2674 - val_rmse: 134.0242 - val_custom_mape: 27.7191 - lr: 1.4861e-04\n", + "Epoch 26/100\n", + "810/811 [============================>.] - ETA: 0s - loss: 10885.3691 - mse: 37987.7930 - mae: 103.5588 - rmse: 163.0795 - custom_mape: 34.6734\n", + "Epoch 26 Detailed Metrics:\n", + "811/811 [==============================] - 32s 40ms/step - loss: 10874.6182 - mse: 37946.5391 - mae: 103.4657 - rmse: 162.9293 - custom_mape: 34.6890 - val_loss: 11223.3662 - val_mse: 30266.1914 - val_mae: 92.8420 - val_rmse: 151.5255 - val_custom_mape: 29.9186 - lr: 1.3456e-04\n", + "Epoch 27/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 10069.0938 - mse: 36349.3711 - mae: 100.6019 - rmse: 158.6973 - custom_mape: 33.1503 - val_loss: 12460.3320 - val_mse: 29399.4160 - val_mae: 91.2526 - val_rmse: 146.5061 - val_custom_mape: 29.6366 - lr: 1.1958e-04\n", + "Epoch 28/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 9476.7852 - mse: 35165.4648 - mae: 99.0255 - rmse: 156.0713 - custom_mape: 32.9813 - val_loss: 13038.0391 - val_mse: 25782.1328 - val_mae: 83.4327 - val_rmse: 134.0097 - val_custom_mape: 27.6063 - lr: 1.0408e-04\n", + "Epoch 29/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 9004.3877 - mse: 34155.9062 - mae: 97.4144 - rmse: 153.6510 - custom_mape: 32.3526 - val_loss: 14318.9199 - val_mse: 27135.3652 - val_mae: 85.2753 - val_rmse: 138.5686 - val_custom_mape: 27.5048 - lr: 8.8425e-05\n", + "Epoch 30/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 8699.8916 - mse: 33452.5859 - mae: 96.3121 - rmse: 152.1849 - custom_mape: 31.9938 - val_loss: 14860.2725 - val_mse: 26410.0449 - val_mae: 84.2833 - val_rmse: 135.7974 - val_custom_mape: 27.4504 - lr: 7.3026e-05\n", + "Epoch 31/100\n", + "810/811 [============================>.] - ETA: 0s - loss: 8397.3701 - mse: 32822.3984 - mae: 95.5427 - rmse: 150.7910 - custom_mape: 32.0949\n", + "Epoch 31 Detailed Metrics:\n", + "811/811 [==============================] - 32s 39ms/step - loss: 8389.3984 - mse: 32788.4531 - mae: 95.4662 - rmse: 150.6722 - custom_mape: 32.1090 - val_loss: 10881.0303 - val_mse: 21581.2246 - val_mae: 76.6546 - val_rmse: 122.9109 - val_custom_mape: 26.1594 - lr: 5.8271e-05\n", + "Epoch 32/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 8211.7285 - mse: 32299.0742 - mae: 94.7628 - rmse: 149.5487 - custom_mape: 31.8022 - val_loss: 10990.5146 - val_mse: 22554.5059 - val_mae: 78.0447 - val_rmse: 125.7095 - val_custom_mape: 26.2527 - lr: 4.4531e-05\n", + "Epoch 33/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 8059.6475 - mse: 31937.1406 - mae: 94.2104 - rmse: 148.7915 - custom_mape: 31.6591 - val_loss: 11965.4951 - val_mse: 19633.5859 - val_mae: 71.8940 - val_rmse: 115.6991 - val_custom_mape: 25.1729 - lr: 3.2155e-05\n", + "Epoch 34/100\n", + "811/811 [==============================] - 32s 39ms/step - loss: 7951.0010 - mse: 31709.4746 - mae: 93.8289 - rmse: 148.3072 - custom_mape: 31.4630 - val_loss: 9540.8096 - val_mse: 22911.6699 - val_mae: 78.2621 - val_rmse: 125.1414 - val_custom_mape: 26.4563 - lr: 2.1455e-05\n", + "Epoch 35/100\n", + "811/811 [==============================] - 32s 39ms/step - loss: 7870.2021 - mse: 31553.3457 - mae: 93.6221 - rmse: 147.9300 - custom_mape: 31.4443 - val_loss: 9422.6035 - val_mse: 21434.2637 - val_mae: 75.5224 - val_rmse: 120.7919 - val_custom_mape: 25.9513 - lr: 1.2703e-05\n", + "Epoch 36/100\n", + "810/811 [============================>.] - ETA: 0s - loss: 7791.0630 - mse: 31464.9941 - mae: 93.5448 - rmse: 147.9198 - custom_mape: 31.4216\n", + "Epoch 36 Detailed Metrics:\n", + "811/811 [==============================] - 32s 39ms/step - loss: 7783.9956 - mse: 31433.4629 - mae: 93.4737 - rmse: 147.8126 - custom_mape: 31.4435 - val_loss: 9728.4277 - val_mse: 23398.5430 - val_mae: 78.7421 - val_rmse: 126.2052 - val_custom_mape: 26.5261 - lr: 6.1193e-06\n", + "Epoch 37/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 7782.7549 - mse: 31406.9688 - mae: 93.3864 - rmse: 147.6053 - custom_mape: 31.3862 - val_loss: 9560.6436 - val_mse: 23029.3730 - val_mae: 78.1451 - val_rmse: 125.1727 - val_custom_mape: 26.4319 - lr: 1.8714e-06\n", + "Epoch 38/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 7777.0708 - mse: 31382.8203 - mae: 93.4302 - rmse: 147.6423 - custom_mape: 31.4434 - val_loss: 9647.4736 - val_mse: 23123.4121 - val_mae: 78.2223 - val_rmse: 125.4518 - val_custom_mape: 26.4217 - lr: 6.6522e-08\n", + "Epoch 39/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 7725.5112 - mse: 31040.5840 - mae: 93.0916 - rmse: 147.1082 - custom_mape: 31.8782 - val_loss: 9582.8750 - val_mse: 20723.7246 - val_mae: 74.9037 - val_rmse: 119.4773 - val_custom_mape: 26.3673 - lr: 1.7698e-04\n", + "Epoch 40/100\n", + "810/811 [============================>.] - ETA: 0s - loss: 7263.8110 - mse: 30007.5918 - mae: 91.4642 - rmse: 144.8820 - custom_mape: 31.5126\n", + "Epoch 40: ReduceLROnPlateau reducing learning rate to 3.52531613316387e-05.\n", + "811/811 [==============================] - 31s 38ms/step - loss: 7262.0361 - mse: 29977.5000 - mae: 91.3955 - rmse: 144.7766 - custom_mape: 31.5394 - val_loss: 14648.0088 - val_mse: 20503.3223 - val_mae: 72.9793 - val_rmse: 118.3558 - val_custom_mape: 25.1001 - lr: 1.7627e-04\n", + "Epoch 41/100\n", + "810/811 [============================>.] - ETA: 0s - loss: 6973.3042 - mse: 28997.6914 - mae: 89.9694 - rmse: 142.9392 - custom_mape: 30.8228\n", + "Epoch 41 Detailed Metrics:\n", + "811/811 [==============================] - 31s 38ms/step - loss: 6969.2603 - mse: 28970.1289 - mae: 89.9065 - rmse: 142.8480 - custom_mape: 30.8349 - val_loss: 11942.8125 - val_mse: 15700.4219 - val_mae: 64.9745 - val_rmse: 107.5340 - val_custom_mape: 24.5915 - lr: 1.7500e-04\n", + "Epoch 42/100\n", + "811/811 [==============================] - 31s 39ms/step - loss: 6722.7314 - mse: 28121.0098 - mae: 88.7315 - rmse: 141.0947 - custom_mape: 30.9093 - val_loss: 18087.9434 - val_mse: 23490.2754 - val_mae: 77.7477 - val_rmse: 127.0767 - val_custom_mape: 26.3092 - lr: 1.7318e-04\n", + "Epoch 43/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 6352.7544 - mse: 27314.2441 - mae: 87.3129 - rmse: 139.6047 - custom_mape: 30.1676 - val_loss: 12681.6553 - val_mse: 17494.8359 - val_mae: 67.6718 - val_rmse: 111.1969 - val_custom_mape: 24.9519 - lr: 1.7083e-04\n", + "Epoch 44/100\n", + "811/811 [==============================] - 30s 37ms/step - loss: 6174.1055 - mse: 26661.8184 - mae: 86.5631 - rmse: 138.3531 - custom_mape: 30.2715 - val_loss: 9485.2715 - val_mse: 17080.8105 - val_mae: 68.2397 - val_rmse: 109.1803 - val_custom_mape: 24.5443 - lr: 1.6795e-04\n", + "Epoch 45/100\n", + "811/811 [==============================] - 31s 38ms/step - loss: 5928.2930 - mse: 25945.6465 - mae: 85.3553 - rmse: 136.5068 - custom_mape: 30.0199 - val_loss: 10805.3350 - val_mse: 12679.4893 - val_mae: 59.6128 - val_rmse: 95.3850 - val_custom_mape: 23.4863 - lr: 1.6457e-04\n", + "Epoch 46/100\n", + "810/811 [============================>.] - ETA: 0s - loss: 5771.2266 - mse: 25396.0840 - mae: 84.5208 - rmse: 135.4825 - custom_mape: 29.6018\n", + "Epoch 46 Detailed Metrics:\n", + "811/811 [==============================] - 31s 38ms/step - loss: 5771.6826 - mse: 25375.7852 - mae: 84.4771 - rmse: 135.4225 - custom_mape: 29.6105 - val_loss: 16886.9219 - val_mse: 15556.0742 - val_mae: 64.1053 - val_rmse: 103.2760 - val_custom_mape: 23.5403 - lr: 1.6071e-04\n", + "Epoch 47/100\n", + "811/811 [==============================] - ETA: 0s - loss: 5708.6367 - mse: 24972.6895 - mae: 83.7521 - rmse: 134.5005 - custom_mape: 29.4252\n", + "Epoch 47: ReduceLROnPlateau reducing learning rate to 3.127976669929922e-05.\n", + "811/811 [==============================] - 32s 39ms/step - loss: 5708.6367 - mse: 24972.6895 - mae: 83.7521 - rmse: 134.5005 - custom_mape: 29.4252 - val_loss: 19152.4121 - val_mse: 20032.2090 - val_mae: 72.7711 - val_rmse: 117.7244 - val_custom_mape: 24.8048 - lr: 1.5640e-04\n", + "Epoch 48/100\n", + "811/811 [==============================] - 31s 39ms/step - loss: 5571.7061 - mse: 24644.9062 - mae: 83.0004 - rmse: 133.9219 - custom_mape: 29.2346 - val_loss: 17331.9844 - val_mse: 16389.8301 - val_mae: 66.4118 - val_rmse: 105.8761 - val_custom_mape: 23.9444 - lr: 1.5165e-04\n", + "Epoch 49/100\n", + "811/811 [==============================] - 32s 39ms/step - loss: 5616.5620 - mse: 24360.8047 - mae: 82.9673 - rmse: 133.5276 - custom_mape: 29.4230 - val_loss: 35736.7578 - val_mse: 19179.0918 - val_mae: 70.1682 - val_rmse: 114.7201 - val_custom_mape: 25.1097 - lr: 1.4651e-04\n", + "Epoch 50/100\n", + "811/811 [==============================] - ETA: 0s - loss: 5390.3022 - mse: 24032.5449 - mae: 82.3451 - rmse: 132.8925 - custom_mape: 29.1358Restoring model weights from the end of the best epoch: 35.\n", + "811/811 [==============================] - 31s 38ms/step - loss: 5390.3022 - mse: 24032.5449 - mae: 82.3451 - rmse: 132.8925 - custom_mape: 29.1358 - val_loss: 13423.8428 - val_mse: 18049.5527 - val_mae: 67.9114 - val_rmse: 110.8442 - val_custom_mape: 23.8173 - lr: 1.4100e-04\n", + "Epoch 50: early stopping\n", + "\n", + "Training completed successfully!\n", + "\n", + "Final Model Performance:\n", + "Out of range predictions: 0 (0.00%)\n", + "MAPE: 25.97%\n", + "Predictions within ±10%: 50.91%\n", + "MAE: 75.52\n", + "RMSE: 146.40\n", + "\n", + "Training history plot saved as: 2024-11-20_18-26_training_history.png\n", + "Training history data saved as: 2024-11-20_18-26_training_history.csv\n", + "Final statistics saved as: 2024-11-20_18-26_training_stats.json\n", + "\n", + "Final Training Statistics:\n", + "Final Loss (train/val): 5390.3022/13423.8428\n", + "Final MAE (train/val): 82.3451/67.9114\n", + "Best validation loss: 9422.6035\n", + "Best validation MAE: 59.6128\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Model creation\n", + "print(\"\\n2. Creating model...\")\n", + "input_shape = (X_train_seq.shape[1], X_train_seq.shape[2])\n", + "\n", + "MAX_RADIATION = 885\n", + "\n", + "min_val_scaled = target_scaler.transform([[0]])[0][0]\n", + "max_val_scaled = target_scaler.transform([[MAX_RADIATION]])[0][0]\n", + "\n", + "model = create_solarradiation_model(input_shape=input_shape, folder_name=folder_name, min_output=min_val_scaled, max_output=max_val_scaled)\n", + "\n", + "print(\"\\n4. Starting training...\")\n", + "history = train_hybrid_model(\n", + " model=model,\n", + " X_train=X_train_seq,\n", + " y_train=y_train,\n", + " X_test=X_test_seq,\n", + " y_test=y_test,\n", + " epochs=100,\n", + " batch_size=192,\n", + " folder_name=folder_name\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ad6226ea-ab01-47aa-9571-52ea9e654c01", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "5. Generating predictions...\n", + "811/811 [==============================] - 5s 6ms/step\n", + "\n", + "6. Evaluating model...\n", + "\n", + "Solar Radiation Prediction Metrics:\n", + "\n", + "Absolute Metrics:\n", + "MAE: 175.39 W/m²\n", + "RMSE: 313.03 W/m²\n", + "R² Score: -0.413\n", + "MAPE: 9983339.55%\n", + "\n", + "Percentage Accuracy:\n", + "Within ±5%: 46.6%\n", + "Within ±10%: 46.6%\n", + "Within ±20%: 46.6%\n", + "\n", + "Level Accuracy:\n", + "Level Accuracy: 68.7%\n", + "\n", + "Confusion Matrix for Radiation Levels:\n", + " Very Low Low Moderate High Very High Extreme\n", + "Very Low 0 0 0 0 0 10\n", + "Low 0 0 0 0 0 1827\n", + "Moderate 0 0 0 0 0 2861\n", + "High 0 0 0 0 0 2296\n", + "Very High 0 0 0 0 0 1131\n", + "Extreme 0 0 0 0 0 17808\n", + "\n", + "Plot saved as: 2024-11-20_18-26_radiation_analysis.png\n", + "\n", + "Error Statistics:\n", + "Mean error: -175.370\n", + "Error standard deviation: 259.295\n", + "Median error: -12.000\n", + "95th percentile absolute error: 773.000\n" + ] + } + ], + "source": [ + "print(\"\\n5. Generating predictions...\")\n", + "predictions = model.predict(X_test_seq)\n", + "predictions = np.clip(predictions, 0, 11)\n", + "\n", + "predictions_original = target_scaler.inverse_transform(predictions)\n", + "y_test_original = target_scaler.inverse_transform(y_test)\n", + "\n", + "print(\"\\n6. Evaluating model...\")\n", + "metrics = evaluate_solarradiation_predictions(y_test_original, predictions_original, folder_name=folder_name)\n", + "\n", + "# Create results dictionary\n", + "training_results = {\n", + " 'model_params': {\n", + " 'input_shape': input_shape,\n", + " 'n_features': len(features),\n", + " 'sequence_length': X_train_seq.shape[1]\n", + " },\n", + " 'training_params': {\n", + " 'batch_size': 32,\n", + " 'total_epochs': len(history.history['loss']),\n", + " 'best_epoch': np.argmin(history.history['val_loss']) + 1\n", + " },\n", + " 'performance_metrics': {\n", + " 'final_loss': float(history.history['val_loss'][-1]),\n", + " 'final_mae': float(history.history['val_mae'][-1]),\n", + " 'best_val_loss': float(min(history.history['val_loss'])),\n", + " 'out_of_range_predictions': int(np.sum((predictions < 0) | (predictions > 11)))\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "2c42461d-b189-4dc0-81da-4eb4879b9135", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "7. Predicting missing data...\n", + "7122/7122 [==============================] - 42s 6ms/step\n", + "\n", + "8. Integrating predictions into original dataset...\n", + "Added 227879 predictions to dataset\n", + "Rows with solar radiation after integration: 357615\n", + "\n", + "Training completed successfully!\n" + ] + } + ], + "source": [ + "print(\"\\n7. Predicting missing data...\")\n", + "to_predict_predictions = model.predict(X_to_predict_seq)\n", + "to_predict_predictions = np.clip(to_predict_predictions, 0, 11)\n", + "\n", + "print(\"\\n8. Integrating predictions into original dataset...\")\n", + "df_updated = integrate_predictions(df.copy(), to_predict_predictions)\n", + "\n", + "df_updated.to_parquet('../../sources/weather_data_solarradiation.parquet')\n", + "\n", + "# Add prediction statistics to training_results\n", + "training_results['prediction_stats'] = {\n", + " 'n_predictions_added': len(to_predict_predictions),\n", + " 'mean_predicted_solarradiation': float(to_predict_predictions.mean()),\n", + " 'min_predicted_solarradiation': float(to_predict_predictions.min()),\n", + " 'max_predicted_solarradiation': float(to_predict_predictions.max()),\n", + "}\n", + "\n", + "print(\"\\nTraining completed successfully!\")\n", + "\n", + "tf.keras.backend.clear_session()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, "id": "08fd4208-0afb-4bf1-bdef-b10b4065fe55", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Plot saved as: 2024-11-20_18-26_error_analysis.png\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABdEAAAHqCAYAAADrpwd3AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAADSKklEQVR4nOzdeXhMZ//H8c9kj8hiSyKkEftalFbtW4hSte9qS9GW2qtULVUttdVW1NNa+jRKrfVYUilaLaldW4qilNKgDUlRZDm/P/LLMLKIbJPl/bquc8mcc899vmcSc8985sx9TIZhGAIAAAAAAAAAAInYWLsAAAAAAAAAAACyK0J0AAAAAAAAAACSQYgOAAAAAAAAAEAyCNEBAAAAAAAAAEgGIToAAAAAAAAAAMkgRAcAAAAAAAAAIBmE6AAAAAAAAAAAJIMQHQAAAAAAAACAZBCiAwAAAAAAAACQDEJ04DGUKFFCffr0Md/+5ptvZDKZ9M0332TYPkwmkyZNmpRh/SGxh3+PmeX8+fMymUxavny5eV2fPn2UP3/+TN93Av6eACBz8Pwar1GjRmrUqJH5dlJjn7U9XGNW6dOnj0qUKJHl+wUAIDux1ng4adIkmUymLN8vci9CdOQYy5cvl8lkMi9OTk4qW7asBg8erCtXrli7vMeydevWbPfGO2GASW4JDw+3dolJatSokblGGxsbubm5qVy5cnrxxRcVGhqaYfvJjr+zBNm5NgBIjYULF8pkMqlWrVpp7uPy5cuaNGmSjh49mnGFZXMJH+YnLPb29ipZsqR69eql3377zdrlPZa9e/dq0qRJunHjRpbv+/DhwzKZTHrrrbeSbXP69GmZTCaNGDEiCysDgNzl4ff0Dy8//PCDtUvM9m7cuCEnJyeZTCadOHEizf0sXLgw23zgffXqVdnZ2alnz57Jtvnnn3/k7Oys9u3bZ2FlgCU7axcAPK7JkyfL399fd+7c0ffff69FixZp69atOnbsmPLly5eltTRo0ED//vuvHBwcHut+W7du1Ycffphk8Pnvv//Kzs56/zUXLVqU5JnSHh4eWV9MKhUvXlxTp06VJN26dUtnzpzR+vXr9dlnn6lz58767LPPZG9vb25/6tQp2dg83meIKf3OkuPn56d///3XYt+ZITv/PQFAagQHB6tEiRLav3+/zpw5o9KlSz92H5cvX9bbb7+tEiVKqFq1ahlfZDY2ZMgQPf3004qOjtbhw4e1ZMkSbdmyRT///LN8fHyytJa0jn179+7V22+/rT59+mT5a46nnnpK5cuX1+eff64pU6Yk2WblypWSlOIbfABA6iS8p39YWsb/vGbNmjUymUzy9vZWcHBwsuPWoyxcuFCFCxfOkm9oP4qnp6eaNWumL7/8Urdv304y11m/fr3u3LnDOAyrIllBjvPcc8+pZs2akqSXXnpJhQoV0uzZs/Xll1+qW7duSd7n1q1bcnFxyfBabGxs5OTklKF9ZnR/j6tjx44qXLjwY93nzp07cnBwSDKYTu9jHxcXp3v37qX4uLi7uycaTKdNm6YhQ4Zo4cKFKlGihN5//33zNkdHxzTXkxoxMTGKi4uTg4OD1X+f1t4/ADzKuXPntHfvXq1fv14DBw5UcHCwJk6caO2ycpT69eurY8eOkqS+ffuqbNmyGjJkiFasWKGxY8cmeZ/Mem2U8G3BnKZHjx4aP368fvjhBz377LOJtn/++ecqX768nnrqKStUBwC5y4Pv6VPrwfdYD0vvmGYYhu7cuSNnZ+c095FVPvvsM7Vs2VJ+fn5auXJlmkP07KZHjx4KCQnRpk2b1LVr10TbV65cKXd3d7Vq1coK1QHxmM4FOV6TJk0kxb8Jl+7POX327Fm1bNlSrq6u6tGjh6T4QHbOnDmqVKmSnJyc5OXlpYEDB+r69esWfRqGoSlTpqh48eLKly+fGjdurOPHjyfad3Jzou/bt08tW7ZUgQIF5OLioieffFJz58411/fhhx9KksVX1xIkNcfqkSNH9Nxzz8nNzU358+dX06ZNE33VLeGrcXv27NGIESNUpEgRubi4qF27drp27dpjPqrJSzjmVatW6a233lKxYsWUL18+RUVFpfjY37p1SyNHjpSvr68cHR1Vrlw5zZw5U4ZhWPRvMpk0ePBgBQcHq1KlSnJ0dFRISMhj12lra6t58+apYsWKWrBggSIjI83bHp4TPTo6Wm+//bbKlCkjJycnFSpUSPXq1TNPB5PS7yxh7teZM2dqzpw5KlWqlBwdHfXLL7+kOC/sb7/9psDAQLm4uMjHx0eTJ0+2eCyS+9t6uM+c/vcEAMHBwSpQoIBatWqljh07Kjg4OMl2N27c0PDhw1WiRAk5OjqqePHi6tWrl/766y998803evrppyXFh8gJz4UJz5XJXQvj4bmy7927pwkTJqhGjRpyd3eXi4uL6tevr127dj32cV25ckV2dnZ6++23E207deqUTCaTFixYIOnR49Djevi1UcKUbb/88ou6d++uAgUKqF69eub2n332mWrUqCFnZ2cVLFhQXbt21cWLFxP1u2TJEpUqVUrOzs565pln9N133yVqk9zYd/LkSXXu3FlFihSRs7OzypUrp3Hjxpnre/311yVJ/v7+5t/f+fPnM6XGpCS8Xkk44/xBhw4d0qlTp8xtvvzyS7Vq1Uo+Pj5ydHRUqVKl9M477yg2NjbFfaR2bE9w8uRJdezYUQULFpSTk5Nq1qypTZs2WbTJ6L8dAMgOUnqPldKYFhMTo3feecfcvkSJEnrzzTd19+5di/5LlCih559/Xl999ZVq1qwpZ2dnffTRR5Kk0NBQ1atXTx4eHsqfP7/KlSunN998M8V6K1eurMaNGydaHxcXp2LFipk/6JakVatWqUaNGnJ1dZWbm5uqVKlizgoe5cKFC/ruu+/UtWtXde3a1XwiQlI+++wzPfPMM8qXL58KFCigBg0aaPv27ebjP378uL799lvzmJvweii5ecQT3h8+ODandTxMSrt27eTi4pLkOHz16lXt2LFDHTt2lKOjo7777jt16tRJTzzxhBwdHeXr66vhw4fr33//TXEfKb0/T+p986VLl9SvXz95eXnJ0dFRlSpV0tKlSxPdd/78+apUqZL5sa5Zs2aSx4GcjzPRkeOdPXtWklSoUCHzupiYGAUGBqpevXqaOXOm+etAAwcO1PLly9W3b18NGTJE586d04IFC3TkyBHt2bPH/NXjCRMmaMqUKWrZsqVatmypw4cPq3nz5rp3794j6wkNDdXzzz+vokWLaujQofL29taJEye0efNmDR06VAMHDtTly5cVGhqq//73v4/s7/jx46pfv77c3Nw0evRo2dvb66OPPlKjRo307bffJpo/9rXXXlOBAgU0ceJEnT9/XnPmzNHgwYO1evXqVD2eERERidbZ2dkl+mr1O++8IwcHB40aNUp37941nxGQ1GNvGIZeeOEF7dq1S0FBQapWrZq++uorvf7667p06ZI++OADi7537typL774QoMHD1bhwoXTfBESW1tbdevWTePHj9f333+f7KfWkyZN0tSpU/XSSy/pmWeeUVRUlA4ePKjDhw+rWbNmqfqdLVu2THfu3NGAAQPk6OioggULKi4uLsm2sbGxatGihZ599llNnz5dISEhmjhxomJiYjR58uTHOsbs/vcEAI8SHBys9u3by8HBQd26ddOiRYt04MABcyguSTdv3lT9+vV14sQJ9evXT0899ZT++usvbdq0SX/88YcqVKigyZMna8KECRowYIDq168vSapTp85j1RIVFaWPP/5Y3bp1U//+/fXPP//ok08+UWBgoPbv3/9Y08R4eXmpYcOG+uKLLxKdWb969WrZ2tqqU6dOkh49Dj2upF4bSVKnTp1UpkwZvffee+YPbt99912NHz9enTt31ksvvaRr165p/vz5atCggY4cOWIe/z/55BMNHDhQderU0bBhw/Tbb7/phRdeUMGCBeXr65tiPT/99JPq168ve3t7DRgwQCVKlNDZs2f1v//9T++++67at2+vX3/9VZ9//rk++OAD8zfiihQpkmU1+vv7q06dOvriiy/0wQcfyNbW1rwt4Y1w9+7dJcUHCfnz59eIESOUP39+7dy5UxMmTFBUVJRmzJjxqF9Pqhw/flx169ZVsWLFNGbMGLm4uOiLL75Q27ZttW7dOrVr105Sxv/tAEBWiIyM1F9//WWxzmQyJRq3knqPlSCpMe2ll17SihUr1LFjR40cOVL79u3T1KlTdeLECW3YsMGi71OnTqlbt24aOHCg+vfvr3Llyun48eN6/vnn9eSTT2ry5MlydHTUmTNntGfPnhSPp0uXLpo0aZLCw8Pl7e1tXv/999/r8uXL5jOrQ0ND1a1bNzVt2tT8TekTJ05oz549Gjp06CMft88//1wuLi56/vnn5ezsrFKlSik4ODjR6523335bkyZNUp06dTR58mQ5ODho37592rlzp5o3b645c+botddeU/78+c0faHt5eT1y/w/LyPHQxcVFbdq00dq1axUREWHxu169erViY2PNH2avWbNGt2/f1iuvvKJChQpp//79mj9/vv744w+tWbPmsY8jKVeuXNGzzz5rPsmvSJEi2rZtm4KCghQVFaVhw4ZJkv7zn/9oyJAh6tixo4YOHao7d+7op59+0r59+8yvG5CLGEAOsWzZMkOS8fXXXxvXrl0zLl68aKxatcooVKiQ4ezsbPzxxx+GYRhG7969DUnGmDFjLO7/3XffGZKM4OBgi/UhISEW669evWo4ODgYrVq1MuLi4szt3nzzTUOS0bt3b/O6Xbt2GZKMXbt2GYZhGDExMYa/v7/h5+dnXL9+3WI/D/Y1aNAgI7n/fpKMiRMnmm+3bdvWcHBwMM6ePWted/nyZcPV1dVo0KBBoscnICDAYl/Dhw83bG1tjRs3biS5vwQTJ040JCW5lCtXLtExlyxZ0rh9+7ZFH8k99hs3bjQkGVOmTLFY37FjR8NkMhlnzpyxOH4bGxvj+PHjKdaboGHDhkalSpWS3b5hwwZDkjF37lzzOj8/P4vfY9WqVY1WrVqluJ/kfmfnzp0zJBlubm7G1atXk9y2bNky87qEx+i1114zr4uLizNatWplODg4GNeuXTMMI/HfVkp9Zse/JwBIjYMHDxqSjNDQUMMw4p8PixcvbgwdOtSi3YQJEwxJxvr16xP1kfAcdeDAgUTPjwkeft5P0LBhQ6Nhw4bm2zExMcbdu3ct2ly/ft3w8vIy+vXrZ7H+4efXpHz00UeGJOPnn3+2WF+xYkWjSZMm5tupGYeSkjBWLF261Lh27Zpx+fJlY8uWLUaJEiUMk8lkHDhwwDCM+2N8t27dLO5//vx5w9bW1nj33Xct1v/888+GnZ2def29e/cMT09Po1q1ahaPz5IlSwxJFo9hUuNUgwYNDFdXV+P333+32M+D48uMGTMMSca5c+cyvcbkfPjhh4Yk46uvvjKvi42NNYoVK2bUrl3bvO7h1z+GYRgDBw408uXLZ9y5c8e8rnfv3oafn5/59uOM7U2bNjWqVKli0V9cXJxRp04do0yZMuZ1af3bAQBrSHiPkdTi6OhobpfSe6zkxrSjR48akoyXXnrJYv2oUaMMScbOnTvN6/z8/AxJRkhIiEXbDz74wJBkfk+WWqdOnTIkGfPnz7dY/+qrrxr58+c3jxtDhw413NzcjJiYmMfqP0GVKlWMHj16mG+/+eabRuHChY3o6GjzutOnTxs2NjZGu3btjNjYWIv7PzjuVqpUKcmxMeHxfVjC7+7BcTqt42FytmzZYkgyPvroI4v1zz77rFGsWDHz8SS136lTpxomk8nitcbDx5LUeJvg4dd1QUFBRtGiRY2//vrLol3Xrl0Nd3d3cw1t2rRJMY9A7sJ0LshxAgICVKRIEfn6+qpr167Knz+/NmzYoGLFilm0e+WVVyxur1mzRu7u7mrWrJn++usv81KjRg3lz5/f/FXtr7/+Wvfu3dNrr71m8TWmhE8aU3LkyBGdO3dOw4YNS3TmdlJfiXqU2NhYbd++XW3btlXJkiXN64sWLaru3bvr+++/V1RUlMV9BgwYYLGv+vXrKzY2Vr///nuq9rlu3TqFhoZaLMuWLUvUrnfv3snOGffwY79161bZ2tpqyJAhFutHjhwpwzC0bds2i/UNGzZUxYoVU1XvoyRcJPWff/5Jto2Hh4eOHz+u06dPp3k/HTp0MJ8xlxqDBw82/5zw6fa9e/f09ddfp7mGR7HG3xMApCQ4OFheXl7mr0CbTCZ16dJFq1atsvgq8Lp161S1alXz2bcPSsv4mhxbW1vzN6vi4uIUERGhmJgY1axZU4cPH37s/tq3by87OzuLb+8cO3ZMv/zyi7p06WJel95xqF+/fipSpIh8fHzUqlUr3bp1SytWrEg03+zLL79scXv9+vWKi4tT586dLV4beXt7q0yZMubXRgcPHtTVq1f18ssvW8xF26dPH7m7u6dY27Vr17R7927169dPTzzxhMW21PzusqLGBF26dJG9vb3FV7C//fZbXbp0yXz2mySL1z///POP/vrrL9WvX1+3b9/WyZMnU7WvlERERGjnzp3q3Lmzuf+//vpLf//9twIDA3X69GldunRJUsa8hgGArPbhhx8mes/58HtCKeX3WA+PaVu3bpUkjRgxwmL9yJEjJUlbtmyxWO/v76/AwECLdQnv4b/88stkv1WclLJly6patWoW431sbKzWrl2r1q1bm8cNDw8P3bp1K01Tbv3000/6+eefLa4D161bN/3111/66quvzOs2btyouLg4TZgwIdE1yzLyNZOU8eNh8+bNVaRIEYtx+Ny5c/rhhx/UrVs38/E8uN9bt27pr7/+Up06dWQYho4cOZKOI4pnGIbWrVun1q1byzAMi9cfgYGBioyMNL8u9PDw0B9//KEDBw6ke7/I/pjOBTnOhx9+qLJly8rOzk5eXl4qV65cosHBzs5OxYsXt1h3+vRpRUZGytPTM8l+r169KknmcLBMmTIW24sUKaICBQqkWFvC16crV66c+gNKwbVr13T79m2VK1cu0bYKFSooLi5OFy9eVKVKlczrH36DmlDzw/O+J6dBgwapurBoUldTl5J+7H///Xf5+PjI1dU10TEkbE9N32lx8+ZNSUq07wdNnjxZbdq0UdmyZVW5cmW1aNFCL774op588slU7+dxaraxsbEIsaX4F16SLOaYy2jW+HsCgOTExsZq1apVaty4sXnubkmqVauWZs2apR07dqh58+aS4sfXDh06ZEldK1as0KxZs3Ty5ElFR0eb16dlbCpcuLCaNm2qL774Qu+8846k+K8k29nZqX379uZ26R2HJkyYoPr168vW1laFCxdWhQoVZGeX+GX+w8dw+vRpGYaR6DVPgoRp7pJ7bWRvb59oPHvYb7/9Jintr42yosYEhQoVUmBgoDZs2KDFixfLyclJK1eulJ2dnTp37mxud/z4cb311lvauXNnog+fH7wGS1qdOXNGhmFo/PjxGj9+fJJtrl69qmLFimXIaxgAyGrPPPNMqi4smtLY+/C233//XTY2NipdurTFem9vb3l4eKTqPWeXLl308ccf66WXXtKYMWPUtGlTtW/fXh07dkyUOSR13zfffFOXLl1SsWLF9M033+jq1asWH5q/+uqr+uKLL/Tcc8+pWLFiat68uTp37qwWLVqk2LcUP8e5i4uLSpYsqTNnzkiSnJycVKJECQUHB5unLj179qxsbGwy7KS0lGT0eGhnZ6cuXbpo4cKF5scxIVB/8MPsCxcuaMKECdq0aVOi96UZMQ5fu3ZNN27c0JIlS7RkyZIk2yTkR2+88Ya+/vprPfPMMypdurSaN2+u7t27q27duumuA9kPITpynNQMuI6OjokGubi4OHl6eiZ7wbLHOYs4O3twDs8HGQ9dwDO9kjsLPanHPqP6Totjx45JUqIXUw9q0KCBzp49qy+//FLbt2/Xxx9/rA8++ECLFy/WSy+9lKr9ZPSV3JM7SyAtF2lJj6z6ewKQ9+zcuVN//vmnVq1apVWrViXaHhwcbA7R0yul59QHn+c+++wz9enTR23bttXrr78uT09P2draaurUqeYPyh9X165d1bdvXx09elTVqlXTF198oaZNm1p8YJ3ecahKlSoKCAh4ZLuHx6q4uDiZTCZt27Ytyef7hG9zWVNW19izZ09t3rxZmzdv1gsvvKB169aZz4yT4i9w27BhQ7m5uWny5MkqVaqUnJycdPjwYb3xxhspnrmY2rE9oY9Ro0YlOksyQcLrmox4DQMA2VVK77GS25bas62Tur+zs7N2796tXbt2acuWLQoJCdHq1avVpEkTbd++Pdn3RlJ8iD527FitWbNGw4YN0xdffCF3d3eLgNzT01NHjx7VV199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66+/rrVr16pTp07q16+fatSooYiICG3atEmLFy9W1apVVapUKXl4eGjx4sVydXWVi4uLatWqJX9/f7300ktau3atWrRooc6dO+vs2bP67LPPEo0/zz//vNavX6927dqpVatWOnfunBYvXqyKFSuar7GRFl26dFHPnj21cOFCBQYGJrr4eGrGocxQqlQpTZkyRWPHjtX58+fVtm1bubq66ty5c9qwYYMGDBigUaNGyd7eXlOmTNHAgQPVpEkTdenSRefOndOyZctSNd/4vHnzVK9ePT311FMaMGCA/P39df78eW3ZskVHjx6VdH8sGzdunLp27Sp7e3u1bt06y2p8UM+ePfXpp5/qq6++Uo8ePcwBvyTVqVNHBQoUUO/evTVkyBCZTCb997//TdU0Z48ztn/44YeqV6+eqlSpov79+6tkyZK6cuWKwsLC9Mcff+jHH3+UZL2/HQBIj23btiV54ck6deo89nN2gqpVq6p3795asmSJeaqR/fv3a8WKFWrbtq35IuYpmTx5snbv3q1WrVrJz89PV69e1cKFC1W8ePFHfrNZij9xb9SoURo1apQKFiyY6Czml156SREREWrSpImKFy+u33//XfPnz1e1atUSnWGe4O7du1q3bp2aNWuW7FnNL7zwgubOnaurV6+qdOnSGjdunN555x3Vr19f7du3l6Ojow4cOCAfHx9NnTpVUvy4u2jRIk2ZMkWlS5eWp6enmjRpoubNm+uJJ55QUFCQXn/9ddna2mrp0qUqUqSIxYfh6RkPH6Vnz56aPHmyvvzyS9WtW9f8bW1JKl++vEqVKqVRo0bp0qVLcnNz07p161J9za6XXnpJ06ZN00svvaSaNWtq9+7d5m+FP2jatGnatWuXatWqpf79+6tixYqKiIjQ4cOH9fXXX5s/cGnevLm8vb1Vt25deXl56cSJE1qwYIFatWqV4nXZkEMZQA6xbNkyQ5Jx4MCBFNv17t3bcHFxSXb7kiVLjBo1ahjOzs6Gq6urUaVKFWP06NHG5cuXzW1iY2ONt99+2yhatKjh7OxsNGrUyDh27Jjh5+dn9O7d29xu165dhiRj165dFvv4/vvvjWbNmhmurq6Gi4uL8eSTTxrz5883b4+JiTFee+01o0iRIobJZDIe/K8oyZg4caJFf4cPHzYCAwON/PnzG/ny5TMaN25s7N27N1WPT3I1Pmzi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mmv01FNPadasWXK5XJKk2bNnq0OHDnrmmWfUvXt3jRkzRr/61a/07LPPBuR6AQAAUMf69ZO2bydAB4BaGDJkiNxut1asWKF169apd+/eGjJkiLKysiQxiQ1A00OQjupqEiF6enq60tLSlJKS4rd93bp1Ki8v99verVs3tWvXTpmZmZKkzMxM9erVS4mJib42qampys/P15YtW3xtTjx3amqq7xwAAABoYj74QPJ6/bclJASmFgBoBg4fPqxvv/1WEydO1Pnnn68uXbpo+vTpKi4u1ubNmyUxiQ1A00SQjupo9CH6/Pnz9dVXX2natGlV9mVlZclutys2NtZve2Jiou9/wrOysvwC9Mr9lftO1yY/P18lJSUnrausrEz5+fl+DwAAADQCU6dK114rpadXDdIBADUSFxenrl276s0331RRUZHcbrdeffVVJSQkqH///pKYxAag6SJIx09p1CH6vn37dP/99+utt95SWFhYoMvxM23aNMXExPgebdu2DXRJAAAAmDpVmjy54uvZs6XlywNbDwA0ExaLRR999JHWr1+v6OhohYWFaebMmVq6dKlv2VUmsQFoygjScTqNOkRft26dcnJy1K9fP4WEhCgkJESrV6/WCy+8oJCQECUmJsrlcik3N9fvuOzsbCUlJUmSkpKSlJ2dXWV/5b7TtXE6nQoPDz9pbZMmTVJeXp7vsW/fvrq4ZAAAANTU8QG6JM2YIf3854GrBwCagIkTJ8pisZz2sX37dhljlJ6eroSEBH388cdau3athg4dquuuu04HDx6s1xqZxAagoRCk41QadYh+1VVXadOmTdqwYYPvMWDAAA0fPtz3dWhoqJYfN8Nox44d2rt3r5KTkyVJycnJ2rRpk3JycnxtMjIy5HQ61aNHD1+b5SfMUsrIyPCd42QcDoecTqffAwAAAAHyxz9WDdAnTAhcPQDQRDzwwAPatm3baR8dO3bUihUrtGjRIs2fP1+XXHKJ+vXrp5dfflnh4eGaN2+eJCaxAWgeCNJxMiGBLuB0oqOj1bNnT79tkZGRiouL820fNWqUxo8fr5YtW8rpdOree+9VcnKyLrroIknS4MGD1aNHD916662aMWOGsrKyNHnyZKWnp8vhcEiS7r77br300kt66KGHdPvtt2vFihV69913tXgx3/gAAACN3h//KD366LHnBOgAUG3x8fGKj4//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2NhYjRo1SoWFhQ19KTXm8Xj06KOP+o2TTz31lI6/5VRz7Ic1a9bouuuu01lnnSWLxaJ//etffvvr6pqr8/sFUFvNefxm7D45xm/Gb8Zvxu8aMwgqU6ZMMTNnzjTjx483MTExVfa73W7Ts2dPk5KSYtavX2+WLFliWrVqZSZNmuRr8/3335uIiAgzfvx4s3XrVvPiiy8am81mli5d6mszf/58Y7fbzRtvvGG2bNli7rjjDhMbG2uys7Mb4jJrpEuXLubaa681GzduNN9884255557TEREhDl48KAxpu76prH7f//v/5kWLVqYV155xezYscNs2bLFLFiwwLc/WPqh0n333WeuueYaI8msX7/etz0vL88kJiaa4cOHm82bN5t33nnHhIeHm1dffdXX5pNPPjE2m83MmDHDbN261UyePNmEhoaaTZs2BeBKztwHH3xgRo4caZYtW2a+++478+9//9skJCSYBx54wNcmGPrhVJri+xzqRzB8L6Smppo5c+aYzZs3mw0bNphrr73WtGvXzhQWFvra3H333aZt27Zm+fLl5ssvvzQXXXSRufjii337qzN+NBVr16417du3N+eff765//77fduDpQ+OHDlizjnnHDNy5Ejz+eefm++//94sW7bM7Ny509dm+vTpJiYmxvzrX/8yGzduNL/4xS9Mhw4dTElJia/N1VdfbXr37m0+++wz8/HHH5vOnTubm266KRCXVCNTp041cXFxZtGiRWbXrl1m4cKFJioqyjz//PO+Ns2xH5YsWWIeeeQR89577xlJ5p///Kff/rq45ur8fgHUVnMfvxm7q2L8Zvw2hvGb8bvmCNGD1Jw5c04aoi9ZssRYrVaTlZXl2/bKK68Yp9NpysrKjDHGPPTQQ+a8887zO+7GG280qampvucXXnihSU9P9z33eDzmrLPOMtOmTavjK6kbhw4dMpLMmjVrfNvy8/ONJJORkWGMqbu+aczKy8vN2WefbV577bVTtgmGfqi0ZMkS061bN7Nly5YqIfrLL79sWrRo4btmY4x5+OGHTdeuXX3Pf/Ob35i0tDS/cw4cONDcdddd9V57fZkxY4bp0KGD73mw9oMxTe99DvUnGL8XcnJyjCSzevVqY4wxubm5JjQ01CxcuNDXZtu2bUaSyczMNMZUb/xoCgoKCkyXLl1MRkaGufzyy31/hAdTHzz88MPm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4oknTFRUlFm/fr1Zv369KSgoMMYY43a7Tc+ePc3gwYPNhg0bzNKlS018fLyZNGmS7xzff/+9iYiIMBMmTDDbtm0zs2bNMjabzSxdutTXZv78+cbhcJi5c+earVu3mjvvvNPExsb63c26MTl06JCJi4szN9xwg9mwYYPZsWOHefDBB01oaKjZsGGDMabu+qaxu//++83ZZ59tli1bZrZv325GjRplEhISzJEjR4wxwdMPx9u1a5eRZNavX+/blpubaxITE82tt95qNm/ebObPn28iIiLMq6++6mvzySefmJCQEPOXv/zFbNu2zTz22GMmNDTUbNq0KQBXceZ++OEH07lzZ3PVVVeZH374wRw8eND3qBQM/XAqTe19DvUnGL4XRo8ebWJiYsyqVav83guKi4t9be6++27Trl07s2LFCvPll1+a5ORkk5yc7NtfnfGjqbn88svN/fff73seLH2wdu1aExISYqZOnWq+/fZb89Zbb5mIiAjzj3/8w9dm+vTpJjY21vz73/82X3/9tbn++utNhw4dTElJia/N1Vdfbfr27Ws+//xz89///td06dLF3HTTTYG4pBoZMWKEOfvss82iRYvMrl27zHvvvWdatWplHnroIV+b5tgPBQUFvr8hJJmZM2ea9evXmz179hhj6uaaq/P7BVBbzX38Zuw+NcZvxm/Gb8bvmiBEDzIjRowwkqo8Vq5c6Wuze/duc80115jw8HDTqlUr88ADD5jy8nK/86xcudL06dPH2O1207FjRzNnzpwqr/Xiiy+adu3aGbvdbi688ELz2Wef1fPV1c4XX3xhBg8ebFq2bGmio6PNRRddZJYsWeLXpq76pjFzuVzmgQceMAkJCSY6OtqkpKSYzZs3+7UJhn443slCdGOM2bhxo7n00kuNw+EwZ599tpk+fXqVY999911z7rnnGrvdbs477zyzePHiBqq69ubMmXPS94sT//+1uffD6TS19znUn+b+vXCq94Lj39tLSkrMPffcY1q0aGEiIiLML3/5S7//dDOmeuNHU3LiH+HB1Afvv/++6dmzp3E4HKZbt27mr3/9q99+r9drHn30UZOYmGgcDoe56qqrzI4dO/za/Pjjj+amm24yUVFRxul0mttuu803saMpyM/PN/fff79p166dCQsLMx07djSPPPKIKSsr87Vpjv2wcuXKk74fjBgxwhhTd9dcnd8vgNpqzuM3Y/epMX4zfjN+M37XhMUYY+p1qjsAAAAAAAAAAE0Ua6IDAAAAAAAAAHAKhOgAAAAAAAAAAJwCIToAAAAAAAAAAKdAiA4AAAAAAAAAwCkQogMAAAAAAAAAcAqE6AAAAAAAAAAAnAIhOgAAAAAAAAAAp0CIDgAAAAAAAADAKRCiAwAAAPCxWCz617/+Va+vMWjQII0dO7ZeXwMAgGDC+A3UL0J0AGds5MiRslgsVR5XX311oEsDAKDJyMzMlM1mU1pa2hkf2759ez333HN1X9RPuO6660453n/88ceyWCz6+uuvG7gqAAAaDuM3EJwI0QHUyNVXX62DBw/6Pd55552Tti0vL6+yzeVy1eh1a3ocAACNzeuvv657771Xa9as0YEDBwJdTrWMGjVKGRkZ+uGHH6rsmzNnjgYMGKDzzz8/AJUBANAwGL+B4ESIDqBGHA6HkpKS/B4tWrSQVPExsldeeUW/+MUvFBkZqalTp+rxxx9Xnz599Nprr6lDhw4KCwuTJO3du1fXX3+9oqKi5HQ69Zvf/EbZ2dm+1znVcQAANGWFhYVasGCBRo8erbS0NM2dO7dKm/fff18XXHCBwsLC1KpVK/3yl7+UVPFR6j179mjcuHG+T4NJx8bM4z333HNq37697/kXX3yhn//852rVqpViYmJ0+eWX66uvvqp23UOGDFF8fHyVegsLC7Vw4UKNGjVKP/74o2666SadffbZioiIUK9evU75H+2VTvYR9NjYWL/X2bdvn37zm98oNjZWLVu21PXXX6/du3f79q9atUoXXnihIiMjFRsbq0suuUR79uyp9rUBAPBTGL/9MX4jmBCiA6gXjz/+uH75y19q06ZNuv322yVJO3fu1P/93//pvffe04YNG+T1enX99dfryJEjWr16tTIyMvT999/rxhtv9DvXiccBANDUvfvuu+rWrZu6du2qW265RW+88YaMMb79ixcv1i9/+Utde+21Wr9+vZYvX64LL7xQkvTee++pTZs2evLJJ32fBquugoICjRgxQv/973/12WefqUuXLrr22mtVUFBQreNDQkL0u9/9TnPnzvWrd+HChfJ4PLrppptUWlqq/v37a/Hixdq8ebPuvPNO3XrrrVq7dm216zxReXm5UlNTFR0drY8//liffPKJoqKidPXVV8vlcsntdmvo0KG6/PLL9fXXXyszM1N33nmnL6AAAKAuMH6fGcZvNCchgS4AQNO0aNEiRUVF+W37wx/+oD/84Q+SpJtvvlm33Xab336Xy6U333xT8fHxkqSMjAxt2rRJu3btUtu2bSVJb775ps477zx98cUXuuCCC056HAAATd3rr7+uW265RVLFEml5eXlavXq1Bg0aJEmaOnWqfvvb3+qJJ57wHdO7d29JUsuWLWWz2RQdHa2kpKQzet0rr7zS7/lf//pXxcbGavXq1RoyZEi1znH77bfr6aef9qt3zpw5GjZsmGJiYhQTE6MHH3zQ1/7ee+/VsmXL9O677/qChDO1YMECeb1evfbaa74/rOfMmaPY2FitWrVKAwYMUF5enoYMGaJOnTpJkrp3716j1wIA4FQYv88M4zeaE2aiA6iRK664Qhs2bPB73H333b79AwYMqHLMOeec4xeEb9u2TW3btvUF6JLUo0cPxcbGatu2bac8DgCApmzHjh1au3atbrrpJkkVs8NuvPFGvf766742GzZs0FVXXVXnr52dna077rhDXbp0UUxMjJxOpwoLC7V3795qn6Nbt266+OKL9cYbb0iq+MTYxx9/rFGjRkmSPB6PnnrqKfXq1UstW7ZUVFSUli1bdkavcaKNGzdq586dio6OVlRUlKKiotSyZUuVlpbqu+++U8uWLTVy5Eilpqbquuuu0/PPP39GM/wAAPgpjN9njvEbzQkz0QHUSGRkpDp37nza/dXZVt3XAgCguXj99dfldrt11lln+bYZY+RwOPTSSy8pJiZG4eHhZ3xeq9Xq9xFtqerNvUeMGKEff/xRzz//vM455xw5HA4lJyef8Y27R40apXvvvVezZs3SnDlz1KlTJ11++eWSpKefflrPP/+8nnvuOfXq1UuRkZEaO3bsaV/DYrGctvbCwkL1799fb731VpVjK/+jfc6cObrvvvu0dOlSLViwQJMnT1ZGRoYuuuiiM7o2AABOhvG7KsZvBBNmogMImO7du2vfvn3at2+fb9vWrVuVm5urHj16BLAyAADqh9vt1ptvvqlnnnnG79NcGzdu1FlnneW7gdf555+v5cuXn/I8drtdHo/Hb1t8fLyysrL8/pg98V4in3zyie677z5de+21Ou+88+RwOHT48OEzvo7f/OY3slqtevvtt/Xmm2/q9ttv931M+5NPPtH111+vW265Rb1791bHjh31zTffnPZ88fHxfjPPvv32WxUXF/ue9+vXT99++60SEhLUuXNnv0dMTIyvXd++fTVp0iR9+umn6tmzp95+++0zvjYAAE7E+H1yjN8IJoToAGqkrKxMWVlZfo8zHcRTUlLUq1cvDR8+XF999ZXWrl2r3/3ud7r88stPuhwMAABN3aJFi3T06FGNGjVKPXv29HsMGzbM95Hwxx57TO+8844ee+wxbdu2TZs2bdKf//xn33nat2+vNWvWaP/+/b7xd9CgQTp06JBmzJih7777TrNmzdIHH3zg9/pdunTR3//+d23btk2ff/65hg8fXqNZc1FRUbrxxhs1adIkHTx4UCNHjvR7jYyMDH366afatm2b7rrrLmVnZ5/2fFdeeaVeeuklrV+/Xl9++aXuvvtuhYaG+vYPHz5crVq10vXXX6+PP/5Yu3bt0qpVq3Tffffphx9+0K5duzRp0iRlZmZqz549+vDDD/Xtt9+yrioAoE4wfp8c4zeCCSE6gBpZunSpWrdu7fe49NJLz+gcFotF//73v9WiRQtddtllSklJUceOHbVgwYJ6qhoAgMB6/fXXlZKS4jf7qtKwYcP05Zdf6uuvv9agQYO0cOFC/ec//1GfPn105ZVXau3atb62Tz75pHbv3q1OnTr5Pg7dvXt3vfzyy5o1a5Z69+6ttWvX+t0grPL1jx49qn79+unWW2/Vfffdp4SEhBpdy6hRo3T06FGlpqb6fbR98uTJ6tevn1JTUzVo0CAlJSVp6NChpz3XM888o7Zt2+pnP/uZbr75Zj344IOKiIjw7Y+IiNCaNWvUrl073XDDDerevbtGjRql0tJSOZ1ORUREaPv27Ro2bJjOPfdc3XnnnUpPT9ddd91Vo2sDAOB4jN8nx/iNYGIxJy5eBAAAAAAAAAAAJDETHQAAAAAAAACAUyJEBwAAAAAAAADgFAjRAQAAAAAAAAA4BUJ0AAAAAAAAAABOgRAdAAAAAAAAAIBTIEQHAAAAAAAAAOAUCNEBAAAAAAAAADgFQnQAAAAAAAAAAE6BEB0AAAAAAAAAgFMgRAcAAAAAAAAA4BQI0QEAAAAAAAAAOAVCdAAAAAAAAAAATuH/AyVGLqrhuLwEAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Error Statistics:\n", + "MAE: 175.3912\n", + "MSE: 97988.2659\n", + "RMSE: 313.0308\n", + "Mean error: -175.3699\n", + "Error std: 259.2946\n", + "Predictions within ±0.5: 46.6%\n", + "Predictions within ±1.0: 47.0%\n", + "Predictions within ±1.5: 47.0%\n", + "Predictions within ±2.0: 47.2%\n" + ] + } + ], "source": [ "def plot_error_analysis(y_true, y_pred, folder_name=None):\n", " \"\"\"\n", @@ -1125,8 +1892,6 @@ " - Errors vs Actual Values scatter plot\n", " - Comprehensive error statistics\n", " \"\"\"\n", - " import os\n", - " from datetime import datetime\n", "\n", " # Convert to 1D numpy arrays if needed\n", " if isinstance(y_true, pd.Series):\n", @@ -1172,11 +1937,7 @@ " if folder_name is not None:\n", " try:\n", " # Create directory if it doesn't exist\n", - " os.makedirs(folder_name, exist_ok=True)\n", - "\n", - " # Generate filename with timestamp\n", - " timestamp = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n", - " filename = os.path.join(folder_name, f'error_analysis_{timestamp}.png')\n", + " filename = f'{folder_name}_error_analysis.png'\n", "\n", " # Save figure\n", " plt.savefig(filename, dpi=300, bbox_inches='tight')\n", @@ -1203,9 +1964,15 @@ "\n", "# Example usage\n", "plot_error_analysis(y_test, predictions, folder_name=folder_name)" - ], + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f982c92c-ba99-4df6-b3c8-df92426679db", + "metadata": {}, "outputs": [], - "execution_count": null + "source": [] } ], "metadata": { diff --git a/src/models/uv_index/uv_index_model.ipynb b/src/models/uv_index/uv_index_model.ipynb old mode 100755 new mode 100644 index 4d8f01b..1ec4188 --- a/src/models/uv_index/uv_index_model.ipynb +++ b/src/models/uv_index/uv_index_model.ipynb @@ -66,39 +66,39 @@ "Requirement already satisfied: MarkupSafe>=2.1.1 in /usr/local/lib/python3.11/dist-packages (from werkzeug>=1.0.1->tensorboard<2.14,>=2.13->tensorflow==2.13.0) (2.1.3)\n", "Requirement already satisfied: pyasn1<0.6.0,>=0.4.6 in /usr/local/lib/python3.11/dist-packages (from pyasn1-modules>=0.2.1->google-auth<3,>=1.6.3->tensorboard<2.14,>=2.13->tensorflow==2.13.0) (0.5.0)\n", "Requirement already satisfied: oauthlib>=3.0.0 in /usr/lib/python3/dist-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<1.1,>=0.5->tensorboard<2.14,>=2.13->tensorflow==2.13.0) (3.2.0)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: numpy in /usr/local/lib/python3.11/dist-packages (1.24.3)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: pandas in /usr/local/lib/python3.11/dist-packages (2.2.3)\n", "Requirement already satisfied: numpy>=1.23.2 in /usr/local/lib/python3.11/dist-packages (from pandas) (1.24.3)\n", "Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.11/dist-packages (from pandas) (2.8.2)\n", "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.11/dist-packages (from pandas) (2024.2)\n", "Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.11/dist-packages (from pandas) (2024.2)\n", "Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: keras==2.13.1 in /usr/local/lib/python3.11/dist-packages (2.13.1)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: scikit-learn in /usr/local/lib/python3.11/dist-packages (1.5.2)\n", "Requirement already satisfied: numpy>=1.19.5 in /usr/local/lib/python3.11/dist-packages (from scikit-learn) (1.24.3)\n", "Requirement already satisfied: scipy>=1.6.0 in /usr/local/lib/python3.11/dist-packages (from scikit-learn) (1.14.1)\n", "Requirement already satisfied: joblib>=1.2.0 in /usr/local/lib/python3.11/dist-packages (from scikit-learn) (1.4.2)\n", "Requirement already satisfied: threadpoolctl>=3.1.0 in /usr/local/lib/python3.11/dist-packages (from scikit-learn) (3.5.0)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: matplotlib in /usr/local/lib/python3.11/dist-packages (3.8.0)\n", "Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (1.1.1)\n", "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (0.11.0)\n", @@ -110,20 +110,20 @@ "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (3.2.0)\n", "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.11/dist-packages (from matplotlib) (2.8.2)\n", "Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: joblib in /usr/local/lib/python3.11/dist-packages (1.4.2)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: pyarrow in /usr/local/lib/python3.11/dist-packages (18.0.0)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: fastparquet in /usr/local/lib/python3.11/dist-packages (2024.11.0)\n", "Requirement already satisfied: pandas>=1.5.0 in /usr/local/lib/python3.11/dist-packages (from fastparquet) (2.2.3)\n", "Requirement already satisfied: numpy in /usr/local/lib/python3.11/dist-packages (from fastparquet) (1.24.3)\n", @@ -134,16 +134,16 @@ "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.5.0->fastparquet) (2024.2)\n", "Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.5.0->fastparquet) (2024.2)\n", "Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.8.2->pandas>=1.5.0->fastparquet) (1.16.0)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: scipy in /usr/local/lib/python3.11/dist-packages (1.14.1)\n", "Requirement already satisfied: numpy<2.3,>=1.23.5 in /usr/local/lib/python3.11/dist-packages (from scipy) (1.24.3)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: seaborn in /usr/local/lib/python3.11/dist-packages (0.13.2)\n", "Requirement already satisfied: numpy!=1.24.0,>=1.20 in /usr/local/lib/python3.11/dist-packages (from seaborn) (1.24.3)\n", "Requirement already satisfied: pandas>=1.2 in /usr/local/lib/python3.11/dist-packages (from seaborn) (2.2.3)\n", @@ -159,34 +159,34 @@ "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.2->seaborn) (2024.2)\n", "Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.11/dist-packages (from pandas>=1.2->seaborn) (2024.2)\n", "Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.7->matplotlib!=3.6.1,>=3.4->seaborn) (1.16.0)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: tqdm in /usr/local/lib/python3.11/dist-packages (4.67.0)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: pydot in /usr/local/lib/python3.11/dist-packages (3.0.2)\n", "Requirement already satisfied: pyparsing>=3.0.9 in /usr/local/lib/python3.11/dist-packages (from pydot) (3.2.0)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: tensorflow-io in /usr/local/lib/python3.11/dist-packages (0.37.1)\n", "Requirement already satisfied: tensorflow-io-gcs-filesystem==0.37.1 in /usr/local/lib/python3.11/dist-packages (from tensorflow-io) (0.37.1)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n", "Requirement already satisfied: tensorflow-addons in /usr/local/lib/python3.11/dist-packages (0.23.0)\n", "Requirement already satisfied: packaging in /usr/local/lib/python3.11/dist-packages (from tensorflow-addons) (23.1)\n", "Requirement already satisfied: typeguard<3.0.0,>=2.7 in /usr/local/lib/python3.11/dist-packages (from tensorflow-addons) (2.13.3)\n", - "\u001B[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m24.3.1\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 -m pip install --upgrade pip\u001B[0m\n" + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\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.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.3.1\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 -m pip install --upgrade pip\u001b[0m\n" ] } ], @@ -832,6 +832,16 @@ " ]\n", " )\n", "\n", + " model.summary()\n", + "\n", + " # Save model architecture visualization\n", + " plot_model(model,\n", + " to_file=f'{folder_name}_model_architecture.png',\n", + " show_shapes=True,\n", + " show_layer_names=True,\n", + " dpi=150,\n", + " show_layer_activations=True)\n", + "\n", " return model\n", "\n", "\n", @@ -1902,7 +1912,7 @@ "print(\"\\n7. Integrating predictions into dataset...\")\n", "df_updated = integrate_predictions(df.copy(), to_predict_predictions)\n", "\n", - "output_path = f'../../sources/weather_data_uvindex.parquet'\n", + "output_path = f'{folder_name}_weather_data_uvindex.parquet'\n", "df_updated.to_parquet(output_path)\n", "print(f\"Updated dataset saved to: {output_path}\")\n", "\n",