{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# **Amazon Lookout for Equipment** - Demonstration on an anonymized compressor dataset\n", "*Part 1: Data preparation*\n", "\n", "**Change your bucket name here:**" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# BUCKET = ''\n", "# PREFIX = 'data'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Initialization\n", "---\n", "This repository is initially structured as follow:\n", "```\n", "/lookout-equipment-demo\n", "|\n", "+-- dataset/ <<< Original dataset <<<\n", "| |-- labels.csv\n", "| |-- tags_description.csv\n", "| |-- timeranges.txt\n", "| \\-- timeseries.zip\n", "|\n", "+-- notebooks/\n", "| |-- 1_data_preparation.ipynb <<< This notebook <<<\n", "| |-- 2_dataset_creation.ipynb\n", "| |-- 3_model_training.ipynb\n", "| |-- 4_model_evaluation.ipynb\n", "| \\-- 5_inference_scheduling.ipynb\n", "|\n", "+-- utils/\n", " \\-- lookout_equipment_utils.py\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Notebook configuration update\n", "Amazon Lookout for Equipment being a very recent service, we need to make sure that we have access to the latest version of the AWS Python packages. If you see a `pip` dependency error, check that the `boto3` version is ok: if it's greater than 1.17.48 (the first version that includes the `lookoutequipment` API), you can discard this error and move forward with the next cell:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "boto3 version: 1.17.53 (should be >= 1.17.48 to include Lookout for Equipment API)\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "!pip install --quiet --upgrade boto3 tqdm tsia\n", "\n", "import boto3\n", "print(f'boto3 version: {boto3.__version__} (should be >= 1.17.48 to include Lookout for Equipment API)')\n", "\n", "# Restart the current notebook to ensure we take into account the previous updates:\n", "from IPython.core.display import HTML\n", "HTML(\"\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Imports" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import os\n", "import pandas as pd\n", "import pyarrow as pa\n", "import pyarrow.parquet as pq\n", "import shutil\n", "import sys\n", "import tsia\n", "import warnings\n", "\n", "from tqdm import tqdm" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "sys.path.append('../utils')\n", "import lookout_equipment_utils as lookout" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Parameters" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "RAW_DATA = os.path.join('..', 'dataset')\n", "DATA = os.path.join('..', 'data')\n", "LABEL_DATA = os.path.join(DATA, 'labelled-data')\n", "TRAIN_DATA = os.path.join(DATA, 'training-data', 'expander')\n", "\n", "os.makedirs(DATA, exist_ok=True)\n", "os.makedirs(LABEL_DATA, exist_ok=True)\n", "os.makedirs(TRAIN_DATA, exist_ok=True)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "plt.style.use('Solarize_Light2')\n", "plt.rcParams['lines.linewidth'] = 0.5\n", "warnings.filterwarnings(\"ignore\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Loading datasets of interest\n", "---\n", "### Analysis time ranges\n", "The dataset provided with this repository is one year long with some known anomaly periods appearing both at the beginning and at the end of the year. Using the following training / evaluation split, will allow Lookout for Equipment to have labelled periods on both side of the split date:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Training period: from 2015-01-01 00:00:00 to 2015-08-31 23:59:00\n", "Evaluation period: from 2015-09-01 00:00:00 to 2015-11-30 23:59:00\n" ] } ], "source": [ "timeranges_fname = os.path.join(DATA, 'timeranges.txt')\n", "shutil.copyfile(os.path.join(RAW_DATA, 'timeranges.txt'), timeranges_fname)\n", "with open(timeranges_fname, 'r') as f:\n", " timeranges = f.readlines()\n", " \n", "training_start = pd.to_datetime(timeranges[0][:-1])\n", "training_end = pd.to_datetime(timeranges[1][:-1])\n", "evaluation_start = pd.to_datetime(timeranges[2][:-1])\n", "evaluation_end = pd.to_datetime(timeranges[3][:-1])\n", "\n", "print(f'Training period: from {training_start} to {training_end}')\n", "print(f'Evaluation period: from {evaluation_start} to {evaluation_end}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Labels\n", "Historical maintenance record time ranges are recorded in a CSV files with two columns containing *start time* and *end time* of each range:" ] }, { "cell_type": "code", "execution_count": 8, "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", "
startend
02015-01-10 10:00:002015-01-10 20:00:00
12015-01-15 13:00:002015-01-16 15:00:00
22015-03-05 10:00:002015-03-27 00:00:00
32015-03-29 10:00:002015-03-29 19:00:00
42015-11-11 18:00:002015-11-13 12:00:00
\n", "
" ], "text/plain": [ " start end\n", "0 2015-01-10 10:00:00 2015-01-10 20:00:00\n", "1 2015-01-15 13:00:00 2015-01-16 15:00:00\n", "2 2015-03-05 10:00:00 2015-03-27 00:00:00\n", "3 2015-03-29 10:00:00 2015-03-29 19:00:00\n", "4 2015-11-11 18:00:00 2015-11-13 12:00:00" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "labels_fname = os.path.join(LABEL_DATA, 'labels.csv')\n", "shutil.copyfile(os.path.join(RAW_DATA, 'labels.csv'), labels_fname)\n", "labels_df = pd.read_csv(os.path.join(LABEL_DATA, 'labels.csv'), header=None)\n", "labels_df[0] = pd.to_datetime(labels_df[0])\n", "labels_df[1] = pd.to_datetime(labels_df[1])\n", "labels_df.columns = ['start', 'end']\n", "labels_df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Time series\n", "The raw timeseries is a zipped parquet file, let's deflate it:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Archive: ../dataset/timeseries.zip\n", " inflating: ../data/training-data/expander.parquet \n" ] } ], "source": [ "timeseries_fname = os.path.join(RAW_DATA, 'timeseries.zip')\n", "!unzip -o $timeseries_fname -d $DATA/training-data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The dataframe stored there has 122 tags and 480,886 rows, ranging from *January 1st* to *November 30, 2015*:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(480886, 122)\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", "
signal-001signal-002signal-003signal-004signal-005signal-006signal-007signal-008signal-009signal-010...signal-113signal-114signal-115signal-116signal-117signal-118signal-119signal-120signal-121signal-122
Timestamp
2015-01-01 00:00:000.3923710.5450050.2967740.4132890.1707440.4829800.2220630.2686910.7498600.475116...0.9390240.8307690.8113210.6534650.7894740.8103450.8035710.7878790.7647060.810345
2015-01-01 00:01:000.3894150.5691550.2906450.4156460.1423680.5322970.2220630.2908040.7767810.486884...0.9390240.8307690.8113210.6534650.7894740.8103450.8035710.7878790.7794120.810345
2015-01-01 00:02:000.3781790.5477500.2906450.4064560.1609590.4701150.2356730.2771150.7823890.472665...0.9390240.8307690.8113210.6534650.7894740.8103450.8035710.7878790.7647060.810345
2015-01-01 00:03:000.3811350.5477500.2845160.4017440.1707440.4987940.2492840.2704460.7717330.484432...0.9390240.8307690.8113210.6534650.7894740.8103450.8035710.7878790.7647060.810345
2015-01-01 00:04:000.3811350.5532380.2845160.4064560.1423680.4934330.1948420.2720250.7498600.484432...0.9390240.8307690.8113210.6534650.7894740.8103450.8035710.7878790.7647060.810345
\n", "

5 rows × 122 columns

\n", "
" ], "text/plain": [ " signal-001 signal-002 signal-003 signal-004 \\\n", "Timestamp \n", "2015-01-01 00:00:00 0.392371 0.545005 0.296774 0.413289 \n", "2015-01-01 00:01:00 0.389415 0.569155 0.290645 0.415646 \n", "2015-01-01 00:02:00 0.378179 0.547750 0.290645 0.406456 \n", "2015-01-01 00:03:00 0.381135 0.547750 0.284516 0.401744 \n", "2015-01-01 00:04:00 0.381135 0.553238 0.284516 0.406456 \n", "\n", " signal-005 signal-006 signal-007 signal-008 \\\n", "Timestamp \n", "2015-01-01 00:00:00 0.170744 0.482980 0.222063 0.268691 \n", "2015-01-01 00:01:00 0.142368 0.532297 0.222063 0.290804 \n", "2015-01-01 00:02:00 0.160959 0.470115 0.235673 0.277115 \n", "2015-01-01 00:03:00 0.170744 0.498794 0.249284 0.270446 \n", "2015-01-01 00:04:00 0.142368 0.493433 0.194842 0.272025 \n", "\n", " signal-009 signal-010 ... signal-113 signal-114 \\\n", "Timestamp ... \n", "2015-01-01 00:00:00 0.749860 0.475116 ... 0.939024 0.830769 \n", "2015-01-01 00:01:00 0.776781 0.486884 ... 0.939024 0.830769 \n", "2015-01-01 00:02:00 0.782389 0.472665 ... 0.939024 0.830769 \n", "2015-01-01 00:03:00 0.771733 0.484432 ... 0.939024 0.830769 \n", "2015-01-01 00:04:00 0.749860 0.484432 ... 0.939024 0.830769 \n", "\n", " signal-115 signal-116 signal-117 signal-118 \\\n", "Timestamp \n", "2015-01-01 00:00:00 0.811321 0.653465 0.789474 0.810345 \n", "2015-01-01 00:01:00 0.811321 0.653465 0.789474 0.810345 \n", "2015-01-01 00:02:00 0.811321 0.653465 0.789474 0.810345 \n", "2015-01-01 00:03:00 0.811321 0.653465 0.789474 0.810345 \n", "2015-01-01 00:04:00 0.811321 0.653465 0.789474 0.810345 \n", "\n", " signal-119 signal-120 signal-121 signal-122 \n", "Timestamp \n", "2015-01-01 00:00:00 0.803571 0.787879 0.764706 0.810345 \n", "2015-01-01 00:01:00 0.803571 0.787879 0.779412 0.810345 \n", "2015-01-01 00:02:00 0.803571 0.787879 0.764706 0.810345 \n", "2015-01-01 00:03:00 0.803571 0.787879 0.764706 0.810345 \n", "2015-01-01 00:04:00 0.803571 0.787879 0.764706 0.810345 \n", "\n", "[5 rows x 122 columns]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all_tags_fname = os.path.join(DATA, 'training-data', 'expander.parquet')\n", "table = pq.read_table(all_tags_fname)\n", "all_tags_df = table.to_pandas()\n", "del table\n", "\n", "print(all_tags_df.shape)\n", "all_tags_df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tags description" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This dataset comes with a tag description file including:\n", "\n", "* `Tag`: the tag name as it is recorded by the customer in his historian system (for instance the [Honeywell process history database](https://www.honeywellprocess.com/en-US/explore/products/advanced-applications/uniformance/Pages/uniformance-phd.aspx))\n", "* `UOM`: the unit of measure for the recorded signal\n", "* `Subsystem`: an ID linked to the part of the asset this sensor is attached to" ] }, { "cell_type": "code", "execution_count": 11, "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", "
TagUOMSubsystem
0signal-001micra ppsubsystem-05
1signal-002micra ppsubsystem-05
2signal-003micra ppsubsystem-05
3signal-004micra ppsubsystem-05
4signal-005micra ppsubsystem-08
\n", "
" ], "text/plain": [ " Tag UOM Subsystem\n", "0 signal-001 micra pp subsystem-05\n", "1 signal-002 micra pp subsystem-05\n", "2 signal-003 micra pp subsystem-05\n", "3 signal-004 micra pp subsystem-05\n", "4 signal-005 micra pp subsystem-08" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tags_description_fname = os.path.join(RAW_DATA, 'tags_description.csv')\n", "tags_description_df = pd.read_csv(tags_description_fname)\n", "tags_description_df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's extract a list of features from this table: we group them by unit of measure for more convenience:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "features = list(tags_description_df.sort_values(by='UOM')['Tag'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Dataset overview\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Build a list of dataframes, one per feature (this will be useful for visualizations purpose). An early event in the year skews the data: we remove that part for visualization purpose only (hence the `start` and `end` range definition below), but will keep the period starting January 1st as a training period later on." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "start = pd.to_datetime('2015-04-05 00:00:00')\n", "end = evaluation_end\n", "\n", "df_list = []\n", "feature_groups = dict()\n", "for f in features:\n", " # Get the unit of measure for the current feature:\n", " uom = str(list(tags_description_df.loc[tags_description_df['Tag'] == f, 'UOM'])[0])\n", " \n", " # We have already some features in this group, add it:\n", " if uom in feature_groups.keys():\n", " feature_groups.update({uom: feature_groups[uom] + [f]})\n", " \n", " # Otherwise, create this group:\n", " else:\n", " feature_groups.update({uom: [f]})\n", " \n", " # Add the dataframe to the list:\n", " current_df = all_tags_df.loc[start:end, [f]]\n", " current_df = current_df.replace(np.nan, 0.0)\n", " df_list.append(current_df)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "image/png": "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W1cIABg2GjFsNE7pidDSEhkZCZPJ5H9FIhWeN0Q0G/jZQtPB84aIyD+bzcbYwAzT+2jP47dxT3Z6InoGjOgbGoHVZsP+qiasKsjSrBMfE4nq5g4AgHF0HF39RiTFRZ/isImIiIiIiIiIaKb4zQTS63S4dsdmPPTkaxBFCVtX5yM9KQ67DlYDALaXF+GSM1fjz8+/i/t+/ywA4OpzyxEVETarAyciIiIiIiIiosAF1BNoZX4mVuZnau7bXl7k+HdsdARuv/7CmR0ZERERERERERHNGM7jTkRERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERES0BDAIRERERERERETzRpKk+R7CksEgEBERERERERHNG4aA5g6DQERERERERERES0BQICtVNrTh6Vf3QZQknLFmBS7ausptnZqTnXjm1X2wiRKiIkJx58cunvHBEhEREREREdHiIkkAhPkexdLgNwgkiiKefHkvbr/+QsQZIvDDR/+HVSuWIT0p1rHO2IQZT768B7d99ALEx0TBaBqfzTETERERERER0SLBcrC547ccrLmjD8nx0UiKi0aQXo8NJctxrLZFs86+iiasLcxGfEwUAMAQGT47oyUiIiIiIiIiomnxmwk0ODKGuOhIx+1YQySa2ns16/QMDMMmSnjgry/BbLHi3A3F2Lwqf+ZHS0RERERERESLCicHmzsB9QRyJbjU6tlECS2dffjyDTswabXhx4+/gOUZSUhJiNGst/tQDXYfrgUA3LRzC9JTEqc3aloyYgyG+R4CnYZ43hDRbOBnC00HzxsiIt/0eiMMhmiE6NkUaKaMjo56XeY3CBQXHYHBEZPj9pDRhNioCO06hghERWQgNCQYoSHBWLEsFW09g25BoG3rCrFtXSEAYNhoxLDROKUnQktLZGQkTCaT/xWJVHjeENFs4GcLTQfPGyIi/2w2G4aMRoQyCDRj9DrvnX/89gTKTk9Ez4ARfUMjsNps2F/VhFUFWZp1VhcsQ31rD2yiCMukFc0dvUh1CQAREREREREREbliOdjc8ZsJpNfpcO2OzXjoydcgihK2rs5HelIcdh2sBgBsLy9CWmIsSnMz8L0//Bc6QcAZa1YgIzlu1gdPRERERERERESBCagn0Mr8TKzMz9Tct728SHP7wi1luHBL2cyNjIiIiIiIiIgWvf5xICN6vkexNPgtByMiIiIiIiIimi1VfawHmysMAhERERERERHRvGEIaO4wCERERERERERE84ZBoLnDIBARERERERERzRuRUaA5wyAQEREREREREc0bThE/dxgEIiIiIiIiIqJ5I873AJYQBoGIiIiIiIiIaP4wE2jOMAhERERERERERPPm37WMAs0VBoGIiIiIiIiIaN6wMfTcYRCIiIiIiIiIFgWThdEEIl8YBCIiIiIiIloE+scZALn1tdO/xbDJImHCytdyql5rFmFlSpFfDAIREREREREtAne+efoHQAj49rsinqiau2DGS43iosig+nulhP97i+8BfxgEIiIiIiIiokXDYju9AxoD40Dz8Nzt76kTEp44cXofM8XgxHyPYOFjEIiIiIiIiGgR6jZJMJoXx8X9VLQYgSM90mldHjfXVU3vtZ2+x8qVJM38c5mwSpg8zYOLCgaBiIiIiIiIFqHn6iW81bI4Llyn4rVmCb/cL57W5XHj89gTqGFQwlMnTt9jd/sbMz/2v1dJeKFhcbyXGAQiIiIiIiJahDpGgf/USmgaWhwXr4Ha2+F8vqdradiIZe73qWTQPN8g4aVGCaZJ38fONeOmyyShfWT+j7fRPLX1JUnC4W7nuA93S26ZUbtbJTxbN//PbSYwCERERERERLQIKcGfXx44fbM6TtVnXz49n7sgzP0+b35RPlZH7AGRA53OZZ97xYaXGkWIkgTRHvy5+UXRsS4AfONtEXfvmtrxfmceMtVcg1cSgAdV75Hn6yX84ejped4EgkEgIiIiIiKiRaJuQNJc0ALA8BQzI05X3nrBnI7ZQLMZAxJ99MxRL3urRUL9oASbKMFslRtIf/JFEZ98UUTPmDPA2GqU8NdK96DJhFVCi9H3sX+/feZem/Vp7ketfUTC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EREREREREdHpi0EgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlgEEgIiIiIiIiIqIlIGi+djxsNM7XromIiIiIiIiIFiUBgMFg8Lhs3oJARERERERERLR0GC2jaDF1eF2uE3QojsmDIAhzOKrFR6fzXvTFIBARERERERERzbrn295ApD4MwfoQj8sP9h/Hx5ZfheWGrDke2dLBIBARERERERERzTpRElESV4C4YM+lSr3j/ZiUJud4VEsLg0BERERERERENOskSBAgeC33EgRAmuMxLTWcHYyIiIiIiIiIZp0kAQK89/sRIEBiGGhWMQhERERERERERHNA8hECAuBnKZ06BoGIiIiIiIiIaNZJkOSaLy8EAJLETKDZxCAQEREREREREc06CSwHm28MAhERERERERHRrJMkP+VgrAabdQwCEREREREREdEckHOBvGEm0OxjEIiIiIiIiIiIZp0Eny2B5CAQY0CzikEgIiIiIiIiIpp1cjmYv5ovRoFmE4NARERERERERDQHfAd4BEFgCGiWMQhERERERERERLMukAAPewLNLgaBiIiIiIiIiGjWSfBdDiYAYFOg2cUgEBERERERERHNCcFXZ2iwHGy2MQhERERERERERPPOX8toOnUMAhERERERERHRrPM3M5jcGJq5QLOJQSAiIiIiIiIiWgCYCzTbGAQiIiIiIiIionknAJDYGHpWMQhERERERERERPNOAMvBZhuDQEREREREREQ0/1gNNusYBCIiIiIiIiKiecdMoNnHIBARERERERERzTu5J9B8j2JxYxCIiIiIiIiIiBYAAWAm0KxiEIiIiIiIiIiI5p0gCAwBzTIGgYiIiIiIiIho3sl5QAwDzSYGgYiIiIiIiIhoARDYFGiWMQhERERERERERLPOX5YPOwLNPgaBiIiIiIiIiGhBYDnY7GIQiIiIiIiIiIjmnSAI8z2ERS9ovnYsSRJERviIiIiI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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tag = 'signal-028'\n", "tag_df = all_tags_df.loc[start:end, [tag]]\n", "tag_df.columns = ['Value']\n", "\n", "fig, axes = lookout.plot_timeseries(\n", " tag_df, \n", " tag, \n", " fig_width=20, \n", " tag_split=evaluation_start, \n", " labels_df=labels_df\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Run the following two cells **only on instances with high memory** (at least `ml.m5.xlarge`): on smaller instances, the image generated by `matplotlib` are too large to be displayed:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig = tsia.plot.plot_multivariate_timeseries(\n", " timeseries_list=df_list,\n", " tags_list=features,\n", " split_date=evaluation_start,\n", " tags_description_df=tags_description_df,\n", " tags_grouping_key='UOM',\n", " num_cols=4,\n", " col_size=5\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "# Discretize each signal in 3 bins:\n", "array = tsia.markov.discretize_multivariate(df_list)\n", "\n", "# Grouping the signals based on their unit of measure (UOM):\n", "num_timesteps = array.shape[1]\n", "separator = np.zeros(shape=(1, num_timesteps))\n", "separator = np.where(separator==0, np.nan, separator)\n", "grouped_array = []\n", "signal_list = []\n", "current_row = 0\n", "for uom in feature_groups.keys():\n", " num_features = len(feature_groups[uom])\n", " signal_list = signal_list + features[current_row:current_row + num_features + 1]\n", " signal_list.append(uom)\n", " grouped_array.append(array[current_row:current_row + num_features + 1])\n", " grouped_array.append(separator)\n", " current_row += num_features\n", "grouped_array = np.concatenate(grouped_array)\n", "\n", "# Plot the strip chart:\n", "tsia.plot.plot_timeseries_strip_chart(\n", " grouped_array, \n", " signal_list=signal_list,\n", " fig_width=20,\n", " dates=df_list[0].index.to_pydatetime(),\n", " day_interval=2\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Building and uploading the dataset\n", "---\n", "We will structure our S3 bucket like this:\n", "```\n", "s3://sagemaker-lookout-equipment-demo/\n", "|\n", "+-- training-data/\n", "| |\n", "| +-- expander/\n", "| |\n", "| +-- subsystem-01\n", "| | \\-- subsystem-01.csv\n", "| |\n", "| +-- subsystem-02\n", "| | \\-- subsystem-02.csv\n", "| |\n", "| +-- ...\n", "| |\n", "| \\-- subsystem-24\n", "| \\-- subsystem-24.csv\n", "|\n", "+-- labelled-data/\n", " |\n", " \\-- labels.csv\n", "```" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Component subsystem-17: 100%|██████████| 24/24 [00:00<00:00, 398.16it/s]\n" ] } ], "source": [ "# Process each subsystem one by one:\n", "components = list(tags_description_df['Subsystem'].unique())\n", "progress_bar = tqdm(components)\n", "for component in progress_bar:\n", " progress_bar.set_description(f'Component {component}')\n", " progress_bar.refresh()\n", " \n", " # Check if CSV file already exist and do not overwrite it:\n", " component_tags_fname = os.path.join(TRAIN_DATA, f'{component}', f'{component}.csv')\n", " if not os.path.exists(component_tags_fname):\n", " # Build the dataframe with all the signal timeseries for the current subsystem:\n", " component_tags_list = list(tags_description_df[tags_description_df['Subsystem'] == component]['Tag'])\n", " component_tags_df = all_tags_df[component_tags_list]\n", " component_tags_df = component_tags_df.reset_index()\n", " component_tags_df['Timestamp'] = component_tags_df['Timestamp'].dt.strftime('%Y-%m-%dT%H:%M:%S.%f')\n", " \n", " # Save to disk:\n", " os.makedirs(os.path.join(TRAIN_DATA, f'{component}'), exist_ok=True)\n", " component_tags_df.to_csv(component_tags_fname, index=None)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "upload: ../data/training-data/expander/subsystem-03/subsystem-03.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-03/subsystem-03.csv\n", "upload: ../data/training-data/expander/subsystem-06/subsystem-06.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-06/subsystem-06.csv\n", "upload: ../data/training-data/expander/subsystem-01/subsystem-01.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-01/subsystem-01.csv\n", "upload: ../data/training-data/expander/subsystem-02/subsystem-02.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-02/subsystem-02.csv\n", "upload: ../data/training-data/expander/subsystem-04/subsystem-04.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-04/subsystem-04.csv\n", "upload: ../data/training-data/expander/subsystem-10/subsystem-10.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-10/subsystem-10.csv\n", "upload: ../data/training-data/expander/subsystem-11/subsystem-11.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-11/subsystem-11.csv\n", "upload: ../data/training-data/expander/subsystem-12/subsystem-12.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-12/subsystem-12.csv\n", "upload: ../data/training-data/expander/subsystem-13/subsystem-13.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-13/subsystem-13.csv\n", "upload: ../data/training-data/expander/subsystem-14/subsystem-14.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-14/subsystem-14.csv\n", "upload: ../data/training-data/expander/subsystem-15/subsystem-15.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-15/subsystem-15.csv\n", "upload: ../data/training-data/expander/subsystem-16/subsystem-16.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-16/subsystem-16.csv\n", "upload: ../data/training-data/expander/subsystem-17/subsystem-17.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-17/subsystem-17.csv\n", "upload: ../data/training-data/expander/subsystem-05/subsystem-05.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-05/subsystem-05.csv\n", "upload: ../data/training-data/expander/subsystem-08/subsystem-08.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-08/subsystem-08.csv\n", "upload: ../data/training-data/expander/subsystem-09/subsystem-09.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-09/subsystem-09.csv\n", "upload: ../data/training-data/expander/subsystem-07/subsystem-07.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-07/subsystem-07.csv\n", "upload: ../data/training-data/expander/subsystem-18/subsystem-18.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-18/subsystem-18.csv\n", "upload: ../data/training-data/expander/subsystem-19/subsystem-19.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-19/subsystem-19.csv\n", "upload: ../data/training-data/expander/subsystem-20/subsystem-20.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-20/subsystem-20.csv\n", "upload: ../data/training-data/expander/subsystem-21/subsystem-21.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-21/subsystem-21.csv\n", "upload: ../data/training-data/expander/subsystem-22/subsystem-22.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-22/subsystem-22.csv\n", "upload: ../data/training-data/expander/subsystem-23/subsystem-23.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-23/subsystem-23.csv\n", "upload: ../data/training-data/expander/subsystem-24/subsystem-24.csv to s3://sagemaker-lookout-equipment-demo/data4/training-data/expander/subsystem-24/subsystem-24.csv\n" ] } ], "source": [ "# Uploading training dataset to S3:\n", "training_src_dir = TRAIN_DATA\n", "training_s3_dest_path = f's3://{BUCKET}/{PREFIX}/training-data/expander'\n", "!aws s3 cp --recursive $training_src_dir $training_s3_dest_path" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "upload: ../data/labelled-data/labels.csv to s3://sagemaker-lookout-equipment-demo/data4/labelled-data/labels.csv\n" ] } ], "source": [ "# Uploading label dataset to S3:\n", "label_src_fname = os.path.join(LABEL_DATA, 'labels.csv')\n", "label_s3_dest_path = f's3://{BUCKET}/{PREFIX}/labelled-data/labels.csv'\n", "!aws s3 cp $label_src_fname $label_s3_dest_path" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conclusion\n", "---\n", "At this stage, we have built:\n", "* A single Parquet dataset that contains all the historical data for all tags provided by the customer: this is **58,668,092** at a **1 minute** sampling rate for **122 tags**.\n", "* **24 individual CSV files** (1 for each subsystem, each subsystem can contain several timeseries) filed in their respective subsystem directories\n", "\n", "Looking at the plot for **signal-028** above, we are going to try and predict the event that happens on **November 2015**: to achieve this, we will use a training set spanning from **January 2015** to **August 2015** and we will test on **September 2015** to **November 2015**." ] } ], "metadata": { "kernelspec": { "display_name": "conda_python3", "language": "python", "name": "conda_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.6.13" } }, "nbformat": 4, "nbformat_minor": 4 }