diff --git a/Deep_Auto_ViML_Timeseries.ipynb b/Deep_Auto_ViML_Timeseries.ipynb new file mode 100644 index 0000000..2e3c440 --- /dev/null +++ b/Deep_Auto_ViML_Timeseries.ipynb @@ -0,0 +1,1140 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Looking in indexes: https://pypi.org/simple, https://pypi.ngc.nvidia.com\n", + "\u001b[31mERROR: Could not find a version that satisfies the requirement tensorflow-estimato (from versions: none)\u001b[0m\n", + "\u001b[31mERROR: No matching distribution found for tensorflow-estimato\u001b[0m\n", + "Looking in indexes: https://pypi.org/simple, https://pypi.ngc.nvidia.com\n", + "Requirement already satisfied: tensorflow-text==2.7.3 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (2.7.3)\n", + "Requirement already satisfied: tensorflow<2.8,>=2.7.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow-text==2.7.3) (2.7.0)\n", + "Requirement already satisfied: tensorflow-hub>=0.8.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow-text==2.7.3) (0.12.0)\n", + "Requirement already satisfied: gast<0.5.0,>=0.2.1 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (0.4.0)\n", + "Requirement already satisfied: six>=1.12.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.15.0)\n", + "Requirement already satisfied: astunparse>=1.6.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.6.3)\n", + "Requirement already satisfied: opt-einsum>=2.3.2 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (3.3.0)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.1.0)\n", + "Requirement already satisfied: absl-py>=0.4.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (0.15.0)\n", + "Requirement already satisfied: numpy>=1.14.5 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.19.5)\n", + "Requirement already satisfied: libclang>=9.0.1 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (13.0.0)\n", + "Requirement already satisfied: h5py>=2.9.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (3.1.0)\n", + "Requirement already satisfied: protobuf>=3.9.2 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (3.19.1)\n", + "Requirement already satisfied: tensorflow-estimator<2.8,~=2.7.0rc0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (2.7.0)\n", + "Requirement already satisfied: typing-extensions>=3.6.6 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (3.7.4.3)\n", + "Requirement already satisfied: wheel<1.0,>=0.32.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (0.37.1)\n", + "Requirement already satisfied: keras-preprocessing>=1.1.1 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.1.2)\n", + "Requirement already satisfied: flatbuffers<3.0,>=1.12 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.12)\n", + "Requirement already satisfied: tensorflow-io-gcs-filesystem>=0.21.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (0.23.1)\n", + "Requirement already satisfied: google-pasta>=0.1.1 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (0.2.0)\n", + "Requirement already satisfied: tensorboard~=2.6 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (2.7.0)\n", + "Requirement already satisfied: wrapt>=1.11.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.12.1)\n", + "Requirement already satisfied: grpcio<2.0,>=1.24.3 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.43.0)\n", + "Requirement already satisfied: keras<2.8,>=2.7.0rc0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (2.7.0)\n", + "Requirement already satisfied: markdown>=2.6.8 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (3.3.6)\n", + "Requirement already satisfied: tensorboard-plugin-wit>=1.6.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.8.0)\n", + "Requirement already satisfied: tensorboard-data-server<0.7.0,>=0.6.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (0.6.1)\n", + "Requirement already satisfied: requests<3,>=2.21.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (2.26.0)\n", + "Requirement already satisfied: setuptools>=41.0.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (58.0.4)\n", + "Requirement already satisfied: google-auth-oauthlib<0.5,>=0.4.1 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (0.4.6)\n", + "Requirement already satisfied: werkzeug>=0.11.15 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (2.0.2)\n", + "Requirement already satisfied: google-auth<3,>=1.6.3 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (2.3.3)\n", + "Requirement already satisfied: pyasn1-modules>=0.2.1 in /home/adarsh/.local/lib/python3.8/site-packages (from google-auth<3,>=1.6.3->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (0.2.8)\n", + "Requirement already satisfied: rsa<5,>=3.1.4 in /home/adarsh/.local/lib/python3.8/site-packages (from google-auth<3,>=1.6.3->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (4.8)\n", + "Requirement already satisfied: cachetools<5.0,>=2.0.0 in /home/adarsh/.local/lib/python3.8/site-packages (from google-auth<3,>=1.6.3->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (4.2.4)\n", + "Requirement already satisfied: requests-oauthlib>=0.7.0 in /home/adarsh/.local/lib/python3.8/site-packages (from google-auth-oauthlib<0.5,>=0.4.1->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.3.0)\n", + "Requirement already satisfied: importlib-metadata>=4.4 in /home/adarsh/.local/lib/python3.8/site-packages (from markdown>=2.6.8->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (4.10.0)\n", + "Requirement already satisfied: zipp>=0.5 in /home/adarsh/.local/lib/python3.8/site-packages (from importlib-metadata>=4.4->markdown>=2.6.8->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (3.6.0)\n", + "Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /home/adarsh/.local/lib/python3.8/site-packages (from pyasn1-modules>=0.2.1->google-auth<3,>=1.6.3->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (0.4.8)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (2021.10.8)\n", + "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (1.26.7)\n", + "Requirement already satisfied: charset-normalizer~=2.0.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (2.0.9)\n", + "Requirement already satisfied: idna<4,>=2.5 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (3.3)\n", + "Requirement already satisfied: oauthlib>=3.0.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<0.5,>=0.4.1->tensorboard~=2.6->tensorflow<2.8,>=2.7.0->tensorflow-text==2.7.3) (3.1.1)\n" + ] + } + ], + "source": [ + "!pip install --upgrade tensorflow-estimato\n", + "!pip install tensorflow-text==2.7.3" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Looking in indexes: https://pypi.org/simple, https://pypi.ngc.nvidia.com\n", + "Requirement already satisfied: tensorflow in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (2.7.0)\n", + "Requirement already satisfied: keras in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (2.7.0)\n", + "Requirement already satisfied: keras-preprocessing>=1.1.1 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (1.1.2)\n", + "Requirement already satisfied: grpcio<2.0,>=1.24.3 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow) (1.43.0)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (1.1.0)\n", + "Requirement already satisfied: astunparse>=1.6.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (1.6.3)\n", + "Requirement already satisfied: google-pasta>=0.1.1 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (0.2.0)\n", + "Requirement already satisfied: opt-einsum>=2.3.2 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (3.3.0)\n", + "Requirement already satisfied: gast<0.5.0,>=0.2.1 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (0.4.0)\n", + "Requirement already satisfied: typing-extensions>=3.6.6 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow) (3.7.4.3)\n", + "Requirement already satisfied: numpy>=1.14.5 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow) (1.19.5)\n", + "Requirement already satisfied: absl-py>=0.4.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow) (0.15.0)\n", + "Requirement already satisfied: flatbuffers<3.0,>=1.12 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (1.12)\n", + "Requirement already satisfied: h5py>=2.9.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (3.1.0)\n", + "Requirement already satisfied: wheel<1.0,>=0.32.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (0.37.1)\n", + "Requirement already satisfied: libclang>=9.0.1 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow) (13.0.0)\n", + "Requirement already satisfied: wrapt>=1.11.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (1.12.1)\n", + "Requirement already satisfied: tensorflow-estimator<2.8,~=2.7.0rc0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow) (2.7.0)\n", + "Requirement already satisfied: tensorboard~=2.6 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (2.7.0)\n", + "Requirement already satisfied: six>=1.12.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (1.15.0)\n", + "Requirement already satisfied: tensorflow-io-gcs-filesystem>=0.21.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorflow) (0.23.1)\n", + "Requirement already satisfied: protobuf>=3.9.2 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorflow) (3.19.1)\n", + "Requirement already satisfied: tensorboard-data-server<0.7.0,>=0.6.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow) (0.6.1)\n", + "Requirement already satisfied: google-auth<3,>=1.6.3 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow) (2.3.3)\n", + "Requirement already satisfied: requests<3,>=2.21.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow) (2.26.0)\n", + "Requirement already satisfied: google-auth-oauthlib<0.5,>=0.4.1 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow) (0.4.6)\n", + "Requirement already satisfied: werkzeug>=0.11.15 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow) (2.0.2)\n", + "Requirement already satisfied: setuptools>=41.0.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow) (58.0.4)\n", + "Requirement already satisfied: markdown>=2.6.8 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow) (3.3.6)\n", + "Requirement already satisfied: tensorboard-plugin-wit>=1.6.0 in /home/adarsh/.local/lib/python3.8/site-packages (from tensorboard~=2.6->tensorflow) (1.8.0)\n", + "Requirement already satisfied: cachetools<5.0,>=2.0.0 in /home/adarsh/.local/lib/python3.8/site-packages (from google-auth<3,>=1.6.3->tensorboard~=2.6->tensorflow) (4.2.4)\n", + "Requirement already satisfied: pyasn1-modules>=0.2.1 in /home/adarsh/.local/lib/python3.8/site-packages (from google-auth<3,>=1.6.3->tensorboard~=2.6->tensorflow) (0.2.8)\n", + "Requirement already satisfied: rsa<5,>=3.1.4 in /home/adarsh/.local/lib/python3.8/site-packages (from google-auth<3,>=1.6.3->tensorboard~=2.6->tensorflow) (4.8)\n", + "Requirement already satisfied: requests-oauthlib>=0.7.0 in /home/adarsh/.local/lib/python3.8/site-packages (from google-auth-oauthlib<0.5,>=0.4.1->tensorboard~=2.6->tensorflow) (1.3.0)\n", + "Requirement already satisfied: importlib-metadata>=4.4 in /home/adarsh/.local/lib/python3.8/site-packages (from markdown>=2.6.8->tensorboard~=2.6->tensorflow) (4.10.0)\n", + "Requirement already satisfied: zipp>=0.5 in /home/adarsh/.local/lib/python3.8/site-packages (from importlib-metadata>=4.4->markdown>=2.6.8->tensorboard~=2.6->tensorflow) (3.6.0)\n", + "Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /home/adarsh/.local/lib/python3.8/site-packages (from pyasn1-modules>=0.2.1->google-auth<3,>=1.6.3->tensorboard~=2.6->tensorflow) (0.4.8)\n", + "Requirement already satisfied: charset-normalizer~=2.0.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard~=2.6->tensorflow) (2.0.9)\n", + "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard~=2.6->tensorflow) (1.26.7)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard~=2.6->tensorflow) (2021.10.8)\n", + "Requirement already satisfied: idna<4,>=2.5 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from requests<3,>=2.21.0->tensorboard~=2.6->tensorflow) (3.3)\n", + "Requirement already satisfied: oauthlib>=3.0.0 in /home/adarsh/anaconda3/envs/DAViML/lib/python3.8/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<0.5,>=0.4.1->tensorboard~=2.6->tensorflow) (3.1.1)\n" + ] + } + ], + "source": [ + "!pip install --upgrade tensorflow keras" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:tensorflow:Silencing TF2.x warnings\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2022-01-30 18:36:35.341066: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_UNKNOWN: unknown error\n", + "2022-01-30 18:36:35.341170: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:169] retrieving CUDA diagnostic information for host: Ra\n", + "2022-01-30 18:36:35.341232: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:176] hostname: Ra\n", + "2022-01-30 18:36:35.341478: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:200] libcuda reported version is: 470.86.0\n", + "2022-01-30 18:36:35.341579: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:204] kernel reported version is: 470.86.0\n", + "2022-01-30 18:36:35.341602: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:310] kernel version seems to match DSO: 470.86.0\n", + "2022-01-30 18:36:35.342025: I tensorflow/core/platform/cpu_feature_guard.cc:151] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 FMA\n", + "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Imported deep_auto_viml. version=0.0.77\n", + "from deep_autoviml import deep_autoviml as deepauto\n", + "-------------------\n", + "model, cat_vocab_dict = deepauto.fit(train, target, keras_model_type=\"fast\",\n", + "\t\tproject_name=\"deep_autoviml\", keras_options=keras_options, \n", + "\t\tmodel_options=model_options, save_model_flag=True, use_my_model='',\n", + "\t\tmodel_use_case='', verbose=0)\n", + "\n", + "predictions = deepauto.predict(model, project_name, test_dataset=test,\n", + " keras_model_type=keras_model_type, \n", + " cat_vocab_dict=cat_vocab_dict)\n", + " \n" + ] + } + ], + "source": [ + "# use pandas numpy as usual\n", + "import tensorflow as tf\n", + "import pandas as pd\n", + "import numpy as np\n", + "from deep_autoviml import deep_autoviml as deepauto\n", + "from tensorflow.python.ops.math_ops import reduce_prod" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'2.7.0'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tf.__version__\n", + "import keras\n", + "keras.__version__" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "datapath = ''\n", + "filename = 'energydata_complete.csv'\n", + "filename = 'https://archive.ics.uci.edu/ml/machine-learning-databases/00374/energydata_complete.csv'\n", + "sep = ','\n", + "\n", + "\n", + "#target = ['target_1','target_2','target_3']\n", + "target = 'Appliances'" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(19735, 29)\n" + ] + } + ], + "source": [ + "# load dataset\n", + "train = pd.read_csv(filename, header=0, sep=sep)\n", + "print(train.shape)\n", + "train = train.dropna()\n", + "train.to_csv(\"/home/adarsh/Desktop/OpenWorld/deep_AutoViML/dataset/energydata_complete.csv\")\n", + "filename = \"/home/adarsh/Desktop/OpenWorld/deep_AutoViML/dataset/energydata_complete.csv\"\n", + "train_datafile = datapath+filename" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(19735, 29) (19735, 30)\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Unnamed: 0dateApplianceslightsT1RH_1T2RH_2T3RH_3T4RH_4T5RH_5T6RH_6T7RH_7T8RH_8T9RH_9T_outPress_mm_hgRH_outWindspeedVisibilityTdewpointrv1rv2
002016-01-11 17:00:00603019.89000047.59666719.20000044.79000019.79000044.73000019.00000045.56666717.16666755.2000007.02666784.25666717.20000041.62666718.200048.90000017.03333345.53006.600000733.592.0000007.00000063.0000005.30000013.27543313.275433
112016-01-11 17:10:00603019.89000046.69333319.20000044.72250019.79000044.79000019.00000045.99250017.16666755.2000006.83333384.06333317.20000041.56000018.200048.86333317.06666745.56006.483333733.692.0000006.66666759.1666675.20000018.60619518.606195
222016-01-11 17:20:00503019.89000046.30000019.20000044.62666719.79000044.93333318.92666745.89000017.16666755.0900006.56000083.15666717.20000041.43333318.200048.73000017.00000045.50006.366667733.792.0000006.33333355.3333335.10000028.64266828.642668
332016-01-11 17:30:00504019.89000046.06666719.20000044.59000019.79000045.00000018.89000045.72333317.16666755.0900006.43333383.42333317.13333341.29000018.100048.59000017.00000045.40006.250000733.892.0000006.00000051.5000005.00000045.41038945.410389
442016-01-11 17:40:00604019.89000046.33333319.20000044.53000019.79000045.00000018.89000045.53000017.20000055.0900006.36666784.89333317.20000041.23000018.100048.59000017.00000045.40006.133333733.992.0000005.66666747.6666674.90000010.08409710.084097
.............................................................................................
19730197302016-05-27 17:20:00100025.56666746.56000025.89000042.02571427.20000041.16333324.70000045.59000023.20000052.40000024.7966671.00000024.50000044.50000024.700050.07400023.20000046.790022.733333755.255.6666673.33333323.66666713.33333343.09681243.096812
19731197312016-05-27 17:30:0090025.50000046.50000025.75400042.08000027.13333341.22333324.70000045.59000023.23000052.32666724.1966671.00000024.55714344.41428624.700049.79000023.20000046.790022.600000755.256.0000003.50000024.50000013.30000049.28294049.282940
19732197322016-05-27 17:40:002701025.50000046.59666725.62857142.76857127.05000041.69000024.70000045.73000023.23000052.26666723.6266671.00000024.54000044.40000024.700049.66000023.20000046.790022.466667755.256.3333333.66666725.33333313.26666729.19911729.199117
19733197332016-05-27 17:50:004201025.50000046.99000025.41400043.03600026.89000041.29000024.70000045.79000023.20000052.20000022.4333331.00000024.50000044.29571424.662549.51875023.20000046.817522.333333755.256.6666673.83333326.16666713.2333336.3227846.322784
19734197342016-05-27 18:00:004301025.50000046.60000025.26428642.97142926.82333341.15666724.70000045.96333323.20000052.20000021.0266671.00000024.50000044.05400024.736049.73600023.20000046.845022.200000755.257.0000004.00000027.00000013.20000034.11885134.118851
\n", + "

19735 rows × 30 columns

\n", + "
" + ], + "text/plain": [ + " Unnamed: 0 date Appliances lights T1 \\\n", + "0 0 2016-01-11 17:00:00 60 30 19.890000 \n", + "1 1 2016-01-11 17:10:00 60 30 19.890000 \n", + "2 2 2016-01-11 17:20:00 50 30 19.890000 \n", + "3 3 2016-01-11 17:30:00 50 40 19.890000 \n", + "4 4 2016-01-11 17:40:00 60 40 19.890000 \n", + "... ... ... ... ... ... \n", + "19730 19730 2016-05-27 17:20:00 100 0 25.566667 \n", + "19731 19731 2016-05-27 17:30:00 90 0 25.500000 \n", + "19732 19732 2016-05-27 17:40:00 270 10 25.500000 \n", + "19733 19733 2016-05-27 17:50:00 420 10 25.500000 \n", + "19734 19734 2016-05-27 18:00:00 430 10 25.500000 \n", + "\n", + " RH_1 T2 RH_2 T3 RH_3 T4 \\\n", + "0 47.596667 19.200000 44.790000 19.790000 44.730000 19.000000 \n", + "1 46.693333 19.200000 44.722500 19.790000 44.790000 19.000000 \n", + "2 46.300000 19.200000 44.626667 19.790000 44.933333 18.926667 \n", + "3 46.066667 19.200000 44.590000 19.790000 45.000000 18.890000 \n", + "4 46.333333 19.200000 44.530000 19.790000 45.000000 18.890000 \n", + "... ... ... ... ... ... ... \n", + "19730 46.560000 25.890000 42.025714 27.200000 41.163333 24.700000 \n", + "19731 46.500000 25.754000 42.080000 27.133333 41.223333 24.700000 \n", + "19732 46.596667 25.628571 42.768571 27.050000 41.690000 24.700000 \n", + "19733 46.990000 25.414000 43.036000 26.890000 41.290000 24.700000 \n", + "19734 46.600000 25.264286 42.971429 26.823333 41.156667 24.700000 \n", + "\n", + " RH_4 T5 RH_5 T6 RH_6 T7 \\\n", + "0 45.566667 17.166667 55.200000 7.026667 84.256667 17.200000 \n", + "1 45.992500 17.166667 55.200000 6.833333 84.063333 17.200000 \n", + "2 45.890000 17.166667 55.090000 6.560000 83.156667 17.200000 \n", + "3 45.723333 17.166667 55.090000 6.433333 83.423333 17.133333 \n", + "4 45.530000 17.200000 55.090000 6.366667 84.893333 17.200000 \n", + "... ... ... ... ... ... ... \n", + "19730 45.590000 23.200000 52.400000 24.796667 1.000000 24.500000 \n", + "19731 45.590000 23.230000 52.326667 24.196667 1.000000 24.557143 \n", + "19732 45.730000 23.230000 52.266667 23.626667 1.000000 24.540000 \n", + "19733 45.790000 23.200000 52.200000 22.433333 1.000000 24.500000 \n", + "19734 45.963333 23.200000 52.200000 21.026667 1.000000 24.500000 \n", + "\n", + " RH_7 T8 RH_8 T9 RH_9 T_out \\\n", + "0 41.626667 18.2000 48.900000 17.033333 45.5300 6.600000 \n", + "1 41.560000 18.2000 48.863333 17.066667 45.5600 6.483333 \n", + "2 41.433333 18.2000 48.730000 17.000000 45.5000 6.366667 \n", + "3 41.290000 18.1000 48.590000 17.000000 45.4000 6.250000 \n", + "4 41.230000 18.1000 48.590000 17.000000 45.4000 6.133333 \n", + "... ... ... ... ... ... ... \n", + "19730 44.500000 24.7000 50.074000 23.200000 46.7900 22.733333 \n", + "19731 44.414286 24.7000 49.790000 23.200000 46.7900 22.600000 \n", + "19732 44.400000 24.7000 49.660000 23.200000 46.7900 22.466667 \n", + "19733 44.295714 24.6625 49.518750 23.200000 46.8175 22.333333 \n", + "19734 44.054000 24.7360 49.736000 23.200000 46.8450 22.200000 \n", + "\n", + " Press_mm_hg RH_out Windspeed Visibility Tdewpoint rv1 \\\n", + "0 733.5 92.000000 7.000000 63.000000 5.300000 13.275433 \n", + "1 733.6 92.000000 6.666667 59.166667 5.200000 18.606195 \n", + "2 733.7 92.000000 6.333333 55.333333 5.100000 28.642668 \n", + "3 733.8 92.000000 6.000000 51.500000 5.000000 45.410389 \n", + "4 733.9 92.000000 5.666667 47.666667 4.900000 10.084097 \n", + "... ... ... ... ... ... ... \n", + "19730 755.2 55.666667 3.333333 23.666667 13.333333 43.096812 \n", + "19731 755.2 56.000000 3.500000 24.500000 13.300000 49.282940 \n", + "19732 755.2 56.333333 3.666667 25.333333 13.266667 29.199117 \n", + "19733 755.2 56.666667 3.833333 26.166667 13.233333 6.322784 \n", + "19734 755.2 57.000000 4.000000 27.000000 13.200000 34.118851 \n", + "\n", + " rv2 \n", + "0 13.275433 \n", + "1 18.606195 \n", + "2 28.642668 \n", + "3 45.410389 \n", + "4 10.084097 \n", + "... ... \n", + "19730 43.096812 \n", + "19731 49.282940 \n", + "19732 29.199117 \n", + "19733 6.322784 \n", + "19734 34.118851 \n", + "\n", + "[19735 rows x 30 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "url = datapath + filename\n", + "test = pd.read_csv(url, header=0, sep=sep)\n", + "print(train.shape, test.shape)\n", + "test = test.dropna()\n", + "test" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "train['date'] = pd.to_datetime(train['date'],infer_datetime_format= True)\n", + "test['date'] = pd.to_datetime(test['date'],infer_datetime_format= True)\n", + "\n", + "train.set_index('date')['T_out'].plot()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "keras_model_type = \"time series\" ## always try \"fast\" first, then \"fast1\", \"fast2\", \"auto\" in that order\n", + "project_name = \"energydata_complete\"\n", + "model_options = {'features':['Appliances','T_out','RH_1','Visibility'], 'window_length':720, 'sampling_rate':1,'stride':64, 'validation_size':0.2, 'prebuilt-model':'lstm'}\n", + "keras_options = {\"patience\":10, 'class_weight': True, 'early_stopping': True, \n", + " 'lr_scheduler': '', \"optimizer\": 'adam', 'epochs':1, 'batch_size':128}" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Only CPU found on this device\n", + "Setting CPU strategy using 1 devices\n", + "\n", + "Model and logs being saved in deep_autoviml/time series/model_2022_01_30-18_36_45\n", + "['Appliances', 'T_out', 'RH_1', 'Visibility'], features will be considered\n", + "Model: \"sequential_7\"\n", + "_________________________________________________________________\n", + " Layer (type) Output Shape Param # \n", + "=================================================================\n", + " lstm (LSTM) (None, 720, 128) 68096 \n", + " \n", + " leaky_re_lu (LeakyReLU) (None, 720, 128) 0 \n", + " \n", + " lstm_1 (LSTM) (None, 720, 128) 131584 \n", + " \n", + " leaky_re_lu_1 (LeakyReLU) (None, 720, 128) 0 \n", + " \n", + " dropout_13 (Dropout) (None, 720, 128) 0 \n", + " \n", + " lstm_2 (LSTM) (None, 64) 49408 \n", + " \n", + " dropout_14 (Dropout) (None, 64) 0 \n", + " \n", + " dense_17 (Dense) (None, 1) 65 \n", + " \n", + "=================================================================\n", + "Total params: 249,153\n", + "Trainable params: 249,153\n", + "Non-trainable params: 0\n", + "_________________________________________________________________\n", + "None\n", + "15/15 [==============================] - 89s 4s/step - loss: 0.8724 - acc: 0.0000e+00 - val_loss: 0.9873 - val_acc: 0.0000e+00\n" + ] + } + ], + "source": [ + "model, cat_vocab_dict = deepauto.fit(train_datafile, target, keras_model_type=keras_model_type,\n", + "\t\t keras_options=keras_options, model_options=model_options, \n", + "\t\tsave_model_flag=False, use_my_model='lstm', verbose=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "from deep_autoviml.utilities.utilities import plot_classification_results, print_regression_model_stats\n", + "from sklearn.metrics import classification_report, confusion_matrix, balanced_accuracy_score\n", + "#from autoviml.Auto_ViML import plot_regression_scatters" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Loading deep_autoviml model from folder. This will take time...\n", + "\n", + "Using model provided as input...\n", + "Time taken to load saved model = 0 seconds\n", + "[0.566 0.541 0.531 ... 0.539 0.549 0.539]\n", + "(19735,)\n", + "Boolean cols=False not converted to strings\n", + " Boolean columns successfully converted to Integers\n", + " Error in converting Boolean columns to Integers. Continuing...\n", + "Possible Conflict: Boolean columns in train and test data were passed differently. Check your test data types.\n", + " number of steps needed to predict: 1\n", + "(19015, 1)\n", + "(19015, 3)\n", + "(19015, 4)\n", + "Appliances 19015\n", + "T_out 19015\n", + "RH_1 19015\n", + "Visibility 19015\n", + "dtype: int64\n", + "(19015, 4)\n", + "Converting model predictions into classes or other forms is erroring. Convert it yourself.\n" + ] + } + ], + "source": [ + "predictions = deepauto.predict(model, project_name, test_dataset=url,\n", + " keras_model_type=keras_model_type, \n", + " cat_vocab_dict=cat_vocab_dict)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
AppliancesT_outRH_1VisibilityAppliances_pred
720801.60000038.26000040.000000143.602037
7211501.75000038.12666740.000000144.060068
7223801.90000038.23000040.000000143.588652
7232902.05000038.43000040.000000142.401173
7242702.20000038.56000040.000000140.692141
..................
1973010022.73333346.56000023.666667102.557396
197319022.60000046.50000024.500000102.916843
1973227022.46666746.59666725.333333103.335299
1973342022.33333346.99000026.166667103.858916
1973443022.20000046.60000027.000000104.578281
\n", + "

19015 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " Appliances T_out RH_1 Visibility Appliances_pred\n", + "720 80 1.600000 38.260000 40.000000 143.602037\n", + "721 150 1.750000 38.126667 40.000000 144.060068\n", + "722 380 1.900000 38.230000 40.000000 143.588652\n", + "723 290 2.050000 38.430000 40.000000 142.401173\n", + "724 270 2.200000 38.560000 40.000000 140.692141\n", + "... ... ... ... ... ...\n", + "19730 100 22.733333 46.560000 23.666667 102.557396\n", + "19731 90 22.600000 46.500000 24.500000 102.916843\n", + "19732 270 22.466667 46.596667 25.333333 103.335299\n", + "19733 420 22.333333 46.990000 26.166667 103.858916\n", + "19734 430 22.200000 46.600000 27.000000 104.578281\n", + "\n", + "[19015 rows x 5 columns]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "predictions" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "predictions[['Appliances','Appliances_pred']].plot()" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + }, + "kernelspec": { + "display_name": "Python 3.8.0 64-bit ('DAViML': conda)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/deep_autoviml/data_load/extract.py b/deep_autoviml/data_load/extract.py index 4fe5adc..5c8c4d3 100644 --- a/deep_autoviml/data_load/extract.py +++ b/deep_autoviml/data_load/extract.py @@ -51,6 +51,11 @@ tf.random.set_seed(42) from tensorflow.keras import layers from tensorflow import keras + +from keras.preprocessing.text import Tokenizer +from keras.preprocessing.sequence import TimeseriesGenerator +from sklearn.preprocessing import MinMaxScaler, StandardScaler + ############################################################################################ #### probably the most handy function of all! def left_subtract(l1,l2): @@ -1194,6 +1199,49 @@ def is_test(x, y): def is_train(x, y): return not is_test(x, y) ################################################################################## + +def load_train_timeseries(train_data_or_file, target, project_name, keras_options, model_options, + keras_model_type, verbose=0): + + """ + Author: Adarsh C + contact: chekodu.adarsh@gmail.com + + This Function loads the trainging data in csv format and converts into tensoflow TimeseriesGenerator. Before the conversion it splits the data for training and validation. + + """ + # Source: https://github.com/srivatsan88/End-to-End-Time-Series/blob/master/Multivariate_Time_Series_Modeling_using_LSTM.ipynb + # Source_Author: https://github.com/srivatsan88 + + df = pd.read_csv(train_data_or_file) # Currently supports only .csv + + scaler = MinMaxScaler() + + feature_data = scaler.fit_transform(df[model_options['features']]) + + + target_data = feature_data[:,df.columns.get_loc(target)] + + x_train, x_test, y_train, y_test = train_test_split(feature_data, target_data, test_size=model_options['validation_size'], random_state=123, shuffle = False) + train_generator = TimeseriesGenerator(x_train, y_train, length=model_options['window_length'], sampling_rate=model_options['sampling_rate'], batch_size=keras_model_type['batch_size'], stride=model_options['stride']) + valid_generator = TimeseriesGenerator(x_test, y_test, length=model_options['window_length'], sampling_rate=model_options['sampling_rate'], batch_size=keras_model_type['batch_size'], stride=model_options['stride']) + + ######################## Setting up Cat Vocab Dict ####################### + cat_vocab_dict = {} + cat_vocab_dict['modeltype'] = 'Timeseries' + cat_vocab_dict['target_variables'] = target + cat_vocab_dict['project_name'] = project_name + cat_vocab_dict['model_options'] = model_options + cat_vocab_dict['keras_options'] = keras_options + cat_vocab_dict['nlp_vars'] = "" + cat_vocab_dict['bools'] = False + cat_vocab_dict['bools_converted'] = False + cat_vocab_dict['num_labels'] = "" + cat_vocab_dict['num_classes'] = "" + + return train_generator, valid_generator, cat_vocab_dict + +################################################################################## def load_text_data(text_directory, project_name, keras_options, model_options, verbose=0): """ diff --git a/deep_autoviml/deep_autoviml.py b/deep_autoviml/deep_autoviml.py index 5acd739..96a64b7 100644 --- a/deep_autoviml/deep_autoviml.py +++ b/deep_autoviml/deep_autoviml.py @@ -53,6 +53,7 @@ ############################################################################################# from sklearn.metrics import roc_auc_score, mean_squared_error, mean_absolute_error +from sklearn.model_selection import train_test_split from IPython.core.display import Image, display import pickle ############################################################################################# @@ -84,7 +85,7 @@ from .data_load.extract import find_problem_type, transform_train_target from .data_load.extract import load_train_data, load_train_data_file from .data_load.extract import load_train_data_frame, load_image_data -from .data_load.extract import load_text_data +from .data_load.extract import load_text_data, load_train_timeseries # keras preprocessing from .preprocessing.preprocessing import perform_preprocessing @@ -108,6 +109,10 @@ from .utilities.utilities import check_if_GPU_exists, plot_history from .utilities.utilities import save_model_architecture + +from .models import basic, dnn, reg_dnn, dnn_drop, giant_deep, cnn1, cnn2, lstm1, gru1, rnn1 + + ############################################################################################# ### Split raw_train_set into train and valid data sets first ### This is a better way to split a dataset into train and test #### @@ -222,6 +227,12 @@ def fit(train_data_or_file, target, keras_model_type="basic", project_name="deep "image_channels": default is "" (empty string). Needed only for image use case. Number of channels. 'save_model_path': default is project_name/keras_model_type/datetime-hour-min/ If you provide your own model path as a string, it will save it there. + "features": list: list of features from thhe input time series data (to be considered for timeseries prediciton). + "window_length": window length for the time series data (to be considered for timeseries prediciton). + "sampling_rate": sampling rate for te time series data (to be considered for timeseries prediciton). + "stride": stride for the time series (to be considered for timeseries prediciton)). + "validation_size": train and validation split ratio (to be considered for timeseries prediciton). + "prebuilt-model": select the pre build model from "lstm". "gru", "rnn" ( to be considered for timeseries prediciton). model_use_case: default is "" (empty string). If "pipeline", you will get back pipeline only, not model. It is a placeholder for future purposes. At the moment, leave it as empty string. verbose = 1 will give you more charts and outputs. verbose 0 will run silently @@ -266,7 +277,6 @@ def fit(train_data_or_file, target, keras_model_type="basic", project_name="deep os.makedirs(save_logs_path, exist_ok = True) print('Model and logs being saved in %s' %save_model_path) - if keras_model_type.lower() in ['image', 'images', "image_classification"]: ############### Now do special IMAGE processing here ################################### if 'image_directory' in model_options.keys(): @@ -323,6 +333,8 @@ def fit(train_data_or_file, target, keras_model_type="basic", project_name="deep print('\nSplitting train into 80+20 percent: train and validation data') valid_ds = full_ds.enumerate().filter(is_valid).map(recover) train_ds = full_ds.enumerate().filter(is_train).map(recover) + + ################### P R E P R O C E S S T E X T ######################### try: deep_model = preprocessing_text(train_ds, keras_model_type, model_options) @@ -335,7 +347,62 @@ def fit(train_data_or_file, target, keras_model_type="basic", project_name="deep project_name, save_model_flag) print(deep_model.summary()) return deep_model, cat_vocab_dict + elif keras_model_type.lower() in ['predict time series', 'time series', "time_series", "predict_time_series"]: + """ + Author: Adarsh C + contact: chekodu.adarsh@gmail.com + """ + ############### Get the features columns ################################### + if 'features' in model_options.keys(): + print(str(model_options['features'])+", features will be considered") + else: + print(' Must provide the features') + return + ################ Load time series data ######### + + train_generator, valid_generator, cat_vocab_dict = load_train_timeseries( + train_data_or_file, target, project_name, keras_options_copy, + model_options_copy, keras_model_type, verbose=verbose) + + + + ################### Choosing the Pre-Built model ######################### + model = None + if model_options['prebuilt-model'].lower() == "lstm": + model = lstm1.make_lstm(model_options_copy) + + elif model_options['prebuilt-model'].lower() == "rnn": + model = rnn1.make_rnn(model_options_copy) + + elif model_options['prebuilt-model'].lower() == "gru": + model = gru1.make_gru(model_options_copy) + else: + print("Must choose lstm, gru, rnn in model_options['prebuilt-model'] ") + return + + print(model.summary()) + + ################### Training the Pre-Built model ######################### + + model.compile(loss='binary_crossentropy', optimizer=keras_options_copy['optimizer'],metrics=['acc']) + + if keras_options_copy["early_stopping"]: + early_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_loss', + patience=2, + mode='min') + + model.fit(train_generator, epochs=keras_options_copy['epochs'],batch_size=keras_options_copy['batch_size'], + validation_data=valid_generator, + shuffle=False, + callbacks=[early_stopping]) + else: + model.fit(train_generator, epochs=keras_options_copy['epochs'],batch_size=keras_options_copy['batch_size'], + validation_data=valid_generator, + shuffle=False) + cat_vocab_dict['train_generator'] = train_generator + cat_vocab_dict['valid_generator'] = valid_generator + return model, cat_vocab_dict shuffle_flag = False #### K E R A S O P T I O N S - THESE CAN BE OVERRIDDEN by your input keras_options dictionary #### keras_options_defaults = {} diff --git a/deep_autoviml/modeling/create_model.py b/deep_autoviml/modeling/create_model.py index eb1d59b..28bd3ba 100644 --- a/deep_autoviml/modeling/create_model.py +++ b/deep_autoviml/modeling/create_model.py @@ -27,7 +27,7 @@ from collections import defaultdict ############################################################################################ # data pipelines and feature engg here -from deep_autoviml.models import basic, dnn, reg_dnn, dnn_drop, giant_deep, cnn1, cnn2 +from deep_autoviml.models import basic, dnn, reg_dnn, dnn_drop, giant_deep, cnn1, cnn2, lstm1 from deep_autoviml.preprocessing.preprocessing_tabular import encode_fast_inputs, create_fast_inputs from deep_autoviml.preprocessing.preprocessing_tabular import encode_all_inputs, create_all_inputs from deep_autoviml.preprocessing.preprocessing_tabular import encode_num_inputs, encode_auto_inputs @@ -259,6 +259,7 @@ def create_model(use_my_model, nlp_inputs, meta_inputs, meta_outputs, nlp_output return model_body, keras_options ########################## This is for non-auto models ##################################### if isinstance(use_my_model, str) : + print("models "+keras_model_type.lower()) if use_my_model == "": if keras_model_type.lower() in ['basic', 'simple', 'default','sample model']: ########## Now that we have setup the layers correctly, we can build some more hidden layers diff --git a/deep_autoviml/modeling/predict_model.py b/deep_autoviml/modeling/predict_model.py index c1e2cb3..3ad0c32 100644 --- a/deep_autoviml/modeling/predict_model.py +++ b/deep_autoviml/modeling/predict_model.py @@ -49,6 +49,13 @@ from tensorflow.keras.optimizers import SGD from tensorflow.keras import regularizers + +from keras.preprocessing.text import Tokenizer +from keras.preprocessing.sequence import TimeseriesGenerator +from sklearn.preprocessing import MinMaxScaler, StandardScaler +from sklearn.model_selection import train_test_split + + ############################################################################################ # data pipelines from deep_autoviml.data_load.classify_features import classify_features_using_pandas @@ -290,6 +297,8 @@ def load_model_dict(model_or_model_path, cat_vocab_dict, project_name, keras_mod else: if modeltype == 'Regression': model = tf.keras.models.load_model(os.path.join(model_or_model_path)) + if modeltype == "Timeseries": + model = tf.keras.models.load_model(os.path.join(model_or_model_path)) else: model = tf.keras.models.load_model(os.path.join(model_or_model_path), custom_objects={'BalancedSparseCategoricalAccuracy': BalancedSparseCategoricalAccuracy}) @@ -309,6 +318,9 @@ def predict(model_or_model_path, project_name, test_dataset, start_time2 = time.time() model, cat_vocab_dict = load_model_dict(model_or_model_path, cat_vocab_dict, project_name, keras_model_type) ##### load the test data set here ####### + + + if keras_model_type.lower() in ['nlp', 'text']: NLP_VARS = cat_vocab_dict['predictors_in_train'] else: @@ -335,7 +347,16 @@ def combine_nlp_text(features): keepdims=False, separator=' ') return y ################################################################ - if isinstance(test_dataset, str): + feature_data = None + target_data = None + if keras_model_type.lower() in ['predict time series', 'time series', "time_series" "predict_time_series"]: + + scaler = MinMaxScaler() + test_generator, feature_data, target_data = load_test_timeseries( + test_dataset, cat_vocab_dict['target_variables'], project_name, cat_vocab_dict['keras_options'], + cat_vocab_dict['model_options'], keras_model_type, scaler, verbose=verbose) + + elif isinstance(test_dataset, str): test_ds, cat_vocab_dict2, test_small = load_test_data(test_dataset, project_name=project_name, cat_vocab_dict=cat_vocab_dict, verbose=verbose) ### You have to load only the NLP or text variables into dataset. otherwise, it will fail during predict @@ -392,7 +413,7 @@ def combine_nlp_text(features): print(' combined NLP or text vars: %s into a single combined_nlp_text successfully' %NLP_VARS) else: print('No NLP vars in data set. No preprocessing done.') - cat_vocab_dict2 = copy.deepcopy(cat_vocab_dict) + cat_vocab_dict2 = copy.deepcopy(cat_vocab_dict) ################################################################################## if cat_vocab_dict2['bools_converted']: BOOLS = [] @@ -473,12 +494,26 @@ def convert_boolean_to_string_predict(features_copy): num_classes = cat_vocab_dict2['num_classes'] ####### save the predictions only upto input size ### ######## This is where we start predictions on test data set ############## - try: + #try: + if keras_model_type.lower() in ['predict time series', 'time series', "time_series" "predict_time_series"]: + predictions = model.predict_generator(test_generator) + + df_pred=pd.concat([pd.DataFrame(predictions), pd.DataFrame(feature_data[:,1:][cat_vocab_dict['model_options']["length"]:])],axis=1) + #df_pred=pd.concat([pd.DataFrame(predictions), pd.DataFrame(x_test[:,1:][win_length:])],axis=1) + + rev_trans=scaler.inverse_transform(df_pred) + df = pd.read_csv(test_dataset) + + y_probas=df[cat_vocab_dict['model_options']['features']][predictions.shape[0]*-1:] + + y_probas[str(cat_vocab_dict['target_variables'])+'_pred']=rev_trans[:,0] + + else: y_probas = model.predict(test_ds, steps=num_steps) - except: - print('ERROR: Predictions from model erroring.') - print(' Check your model and ensure test data and their dtypes are same as train data and retry again.') - return + #except: + # print('ERROR: Predictions from model erroring.') + # print(' Check your model and ensure test data and their dtypes are same as train data and retry again.') + # return ###### Now convert the model predictions into classes ######### try: y_test_preds_list = convert_predictions_from_model(y_probas, cat_vocab_dict2, DS_LEN) @@ -492,6 +527,29 @@ def convert_boolean_to_string_predict(features_copy): print('Time taken in mins for predictions = %0.0f' %((time.time()-start_time2)/60)) return y_test_preds_list ############################################################################################ + +def load_test_timeseries(test_data_or_file, target, project_name, keras_options, model_options, + keras_model_type,scaler , verbose=0): + """ + Author: Adarsh C + contact: chekodu.adarsh@gmail.com + + This Function loads the testing data in csv format and converts into tensoflow TimeseriesGenerator. + + """ + + # Source: https://github.com/srivatsan88/End-to-End-Time-Series/blob/master/Multivariate_Time_Series_Modeling_using_LSTM.ipynb + # Source_Author: https://github.com/srivatsan88 + + df = pd.read_csv(test_data_or_file) + feature_data = scaler.fit_transform(df[model_options['features']]) + target_data = feature_data[:,df.columns.get_loc(target)] + test_generator = TimeseriesGenerator(feature_data, target_data, length=model_options['window_length'], sampling_rate=1, batch_size=keras_options['batch_size']) + return test_generator, feature_data, target_data + +############################################################################################ + + def convert_predictions_from_model(y_probas, cat_vocab_dict, DS_LEN): y_test_preds_list = [] target = cat_vocab_dict['target_variables'] diff --git a/deep_autoviml/models/gru1.py b/deep_autoviml/models/gru1.py new file mode 100644 index 0000000..cfbb632 --- /dev/null +++ b/deep_autoviml/models/gru1.py @@ -0,0 +1,57 @@ +############################################################################################ +#Copyright 2021 Google LLC + +#Licensed under the Apache License, Version 2.0 (the "License"); +#you may not use this file except in compliance with the License. +#You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +#Unless required by applicable law or agreed to in writing, software +#distributed under the License is distributed on an "AS IS" BASIS, +#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#See the License for the specific language governing permissions and +#limitations under the License. +############################################################################################ +import tensorflow as tf +from tensorflow import keras +#### Make sure it is Tensorflow 2.4 or greater! +from tensorflow.keras.optimizers import SGD, Adam, RMSprop +from tensorflow.keras import layers +from tensorflow.keras import optimizers +from tensorflow.keras import models +from tensorflow.keras import callbacks +from tensorflow.keras import backend as K +from tensorflow.keras import utils +from tensorflow.keras import layers +from tensorflow.keras.layers import BatchNormalization +from tensorflow.keras.optimizers import SGD +from tensorflow.keras import regularizers +from tensorflow.keras.layers import Reshape, MaxPooling1D, MaxPooling2D +from tensorflow.keras.layers import AveragePooling2D, AveragePooling1D +from tensorflow.keras import Model, Sequential +from tensorflow.keras.layers import Embedding, Reshape, Dropout, Dense, GRU, LeakyReLU +from tensorflow.keras.layers import Activation, Dense, Embedding, GlobalAveragePooling1D +from tensorflow.keras.layers import GlobalMaxPooling1D, Dropout, Conv1D +from tensorflow.keras.layers.experimental.preprocessing import TextVectorization +############################################################################################ + +def make_gru(model_options): + ''' + Author: Adarsh C + Date created: 30/01/2022 + Date last modified: 30/01/2022 + contact: chekodu.adarsh@gmail.com + Inputs: + model_options: contains important model hyper parameters + ''' + model = tf.keras.Sequential() + model.add(GRU(128, input_shape= (model_options['window_length'], len(model_options['features'])), return_sequences=True)) + model.add(LeakyReLU(alpha=0.5)) + model.add(GRU(128, return_sequences=True)) + model.add(LeakyReLU(alpha=0.5)) + model.add(Dropout(0.3)) + model.add(GRU(64, return_sequences=False)) + model.add(Dropout(0.3)) + model.add(Dense(1)) + return model \ No newline at end of file diff --git a/deep_autoviml/models/lstm1.py b/deep_autoviml/models/lstm1.py new file mode 100644 index 0000000..e84195d --- /dev/null +++ b/deep_autoviml/models/lstm1.py @@ -0,0 +1,61 @@ +############################################################################################ +#Copyright 2021 Google LLC + +#Licensed under the Apache License, Version 2.0 (the "License"); +#you may not use this file except in compliance with the License. +#You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +#Unless required by applicable law or agreed to in writing, software +#distributed under the License is distributed on an "AS IS" BASIS, +#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#See the License for the specific language governing permissions and +#limitations under the License. +############################################################################################ +import tensorflow as tf +from tensorflow import keras +#### Make sure it is Tensorflow 2.4 or greater! +from tensorflow.keras.optimizers import SGD, Adam, RMSprop +from tensorflow.keras import layers +from tensorflow.keras import optimizers +from tensorflow.keras import models +from tensorflow.keras import callbacks +from tensorflow.keras import backend as K +from tensorflow.keras import utils +from tensorflow.keras import layers +from tensorflow.keras.layers import BatchNormalization +from tensorflow.keras.optimizers import SGD +from tensorflow.keras import regularizers +from tensorflow.keras.layers import Reshape, MaxPooling1D, MaxPooling2D +from tensorflow.keras.layers import AveragePooling2D, AveragePooling1D +from tensorflow.keras import Model, Sequential +from tensorflow.keras.layers import Embedding, Reshape, Dropout, Dense, LSTM, LeakyReLU +from tensorflow.keras.layers import Activation, Dense, Embedding, GlobalAveragePooling1D +from tensorflow.keras.layers import GlobalMaxPooling1D, Dropout, Conv1D +from tensorflow.keras.layers.experimental.preprocessing import TextVectorization +############################################################################################ + +def make_lstm(model_options): + ''' + Author: Adarsh C + Date created: 30/01/2022 + Date last modified: 30/01/2022 + contact: chekodu.adarsh@gmail.com + Inputs: + model_options: contains important model hyper parameters + ''' + + # Source: https://github.com/srivatsan88/End-to-End-Time-Series/blob/master/Multivariate_Time_Series_Modeling_using_LSTM.ipynb + # Source_Author: https://github.com/srivatsan88 + + model = tf.keras.Sequential() + model.add(LSTM(128, input_shape= (model_options['window_length'], len(model_options['features'])), return_sequences=True)) + model.add(LeakyReLU(alpha=0.5)) + model.add(LSTM(128, return_sequences=True)) + model.add(LeakyReLU(alpha=0.5)) + model.add(Dropout(0.3)) + model.add(LSTM(64, return_sequences=False)) + model.add(Dropout(0.3)) + model.add(Dense(1)) + return model \ No newline at end of file diff --git a/deep_autoviml/models/rnn1.py b/deep_autoviml/models/rnn1.py new file mode 100644 index 0000000..4543712 --- /dev/null +++ b/deep_autoviml/models/rnn1.py @@ -0,0 +1,58 @@ +############################################################################################ +#Copyright 2021 Google LLC + +#Licensed under the Apache License, Version 2.0 (the "License"); +#you may not use this file except in compliance with the License. +#You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +#Unless required by applicable law or agreed to in writing, software +#distributed under the License is distributed on an "AS IS" BASIS, +#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#See the License for the specific language governing permissions and +#limitations under the License. +############################################################################################ +import tensorflow as tf +from tensorflow import keras +#### Make sure it is Tensorflow 2.4 or greater! +from tensorflow.keras.optimizers import SGD, Adam, RMSprop +from tensorflow.keras import layers +from tensorflow.keras import optimizers +from tensorflow.keras import models +from tensorflow.keras import callbacks +from tensorflow.keras import backend as K +from tensorflow.keras import utils +from tensorflow.keras import layers +from tensorflow.keras.layers import BatchNormalization +from tensorflow.keras.optimizers import SGD +from tensorflow.keras import regularizers +from tensorflow.keras.layers import Reshape, MaxPooling1D, MaxPooling2D +from tensorflow.keras.layers import AveragePooling2D, AveragePooling1D +from tensorflow.keras import Model, Sequential +from tensorflow.keras.layers import Embedding, Reshape, Dropout, Dense, SimpleRNN, LeakyReLU +from tensorflow.keras.layers import Activation, Dense, Embedding, GlobalAveragePooling1D +from tensorflow.keras.layers import GlobalMaxPooling1D, Dropout, Conv1D +from tensorflow.keras.layers.experimental.preprocessing import TextVectorization +############################################################################################ + + +def make_rnn(model_options): + ''' + Author: Adarsh C + Date created: 30/01/2022 + Date last modified: 30/01/2022 + contact: chekodu.adarsh@gmail.com + Inputs: + model_options: contains important model hyper parameters + ''' + model = tf.keras.Sequential() + model.add(SimpleRNN(128, input_shape= (model_options['window_length'], len(model_options['features'])), return_sequences=True)) + model.add(LeakyReLU(alpha=0.5)) + model.add(SimpleRNN(128, return_sequences=True)) + model.add(LeakyReLU(alpha=0.5)) + model.add(Dropout(0.3)) + model.add(SimpleRNN(64, return_sequences=False)) + model.add(Dropout(0.3)) + model.add(Dense(1)) + return model \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index da502f6..11c4029 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ ipython jupyter -tensorflow~=2.5 +tensorflow==2.7.0 +keras=2.7.0 pandas numpy~=1.19.2 matplotlib @@ -10,7 +11,7 @@ storm-tuner>=0.0.8 emoji xlrd tensorflow_hub>=0.12.0 -tensorflow-text~=2.5 +tensorflow-text==2.7.3 optuna statsmodels seaborn