<jupyter_start><jupyter_text>Predict Paramters of Nucler Plant Operations (Multi-Output Regression) Contents1. [Background](Background)2. [Data](Data)3. [Exploratory Data Analysis](Exploratory-Data-Analysis)4. [Feature Engineering](Feature-Engineering)    - [Fourier Transform](Fourier-Transform)    - [Aggregate Features](Aggregate-Features)5. [Trial 1](Trial-1)6. [Model Deployment and Testing](Model-Deployment-and-Testing)7. [Clean up](Clean-up)8. [Test Cases](Test-Cases)9. [Lambda Functions](Lambda-Functions)10. [End to End Architcture and Next Steps](End-to-End-Architcture-and-Next-Steps)  BackgroundNuclear Powerplants are one of the significant energy generators for world-leading nations. It is some times considered as a 'clean energy' source. Atomic power plants heat water to produce steam. The steam is used to spin large turbines that generate electricity. Nuclear power plants use the heat produced during nuclear fission to heat water. Nuclear energy generation of the US itself is 99.6 million kilowatts as of April 2020. Active monitoring of the powerplant systems is required to maintain balance in the systems. Any symptoms of abnormal behavior will result in catastrophic reactions. The objective of the current project is to predict x-coordinate,y-coordinate, mass, and velocity from the vibration data. This model is useful for identifying and detecting early signs of faults.<jupyter_code>import warnings; warnings.simplefilter('ignore')
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import io
import os
import sys
import time
import json
from IPython.display import display
from time import strftime, gmtime
import boto3
import re

import seaborn as sns 
import sklearn as sl
import scipy as sp
from numpy import save

from tqdm import tqdm
import sagemaker
from sklearn.model_selection import train_test_split
from sagemaker import get_execution_role
from sagemaker.predictor import csv_serializer
from sagemaker.debugger import (rule_configs,
                                Rule,
                                DebuggerHookConfig)
from sagemaker.model_monitor import (DataCaptureConfig,
                                     DatasetFormat,
                                     DefaultModelMonitor)
from sagemaker.s3 import (S3Uploader,
                          S3Downloader)

from smexperiments.experiment import Experiment
from smexperiments.trial import Trial
from smexperiments.trial_component import TrialComponent
from smexperiments.tracker import Tracker
from sagemaker.amazon.amazon_estimator import get_image_uri
docker_image_name = get_image_uri(boto3.Session().region_name, 
                                  'xgboost',
                                  repo_version='0.90-2')
from utils import (create_train_test_split,
                   generate_agg_feats,
                   fft_features,
                   plot_vibration_data)<jupyter_output><empty_output><jupyter_text>DataThe train data contains five attributes. The attribute id and time are self-explanatory. The acceleration parameters in the collider are labeled as S1, S2, S3, and S4. In this data, each id is corresponding to one training instance. The timestamp difference between each observation in id is four seconds, and it can be considered an equispaced time series data-set. For each id, there is a corresponding entry in the training targets data. There are 1050000 in the training data and 2800 entries. The training target contains 2800 entries for X, Y, M, and V. These are the prediction target, the collider parameters.Unlike the traditional data-sets in Machine learning exercises, we can't jump into modeling immediately. The data should be further converted to an appropriate scientific format before approaching the problem. One of the widely adopted methods is to apply Fourier Transform before using any modeling techniques. Let's explore the data further to understand the same.<jupyter_code>s3_bucket_name = 'nukeall'
s3_prefix = 'nuclear'
data_file = "train_features.csv"
data_target_file = "train_target.csv"

features = pd.read_csv(f"s3://{s3_bucket_name}/{s3_prefix}/{data_file}")
targets = pd.read_csv(f"s3://{s3_bucket_name}/{s3_prefix}/{data_target_file}")
features.head()
targets.head()<jupyter_output><empty_output><jupyter_text>Exploratory Data AnalysisUnlike the traditional Machine Learning dataset, the vibration data is arranged by the observation id's. Each id contains approximately 375 observations, which is of time series in nature. Exploration and pre-processing of the data require specific requirements than the traditional space. Let's explore a set of observations from the data.<jupyter_code>features[features.id == 10]
data_id = 10
plot_vibration_data(features[features.id == 10],
                    "Vibration Readings for the ID {0}".format(data_id))
data_id = 1250
plot_vibration_data(features[features.id == 1250],
                    "Vibration Readings for the ID {0}".format(data_id))
data_id = 2000
plot_vibration_data(features[features.id == 2000],
                    "Vibration Readings for the ID {0}".format(data_id))<jupyter_output><empty_output><jupyter_text>Feature EngineeringEach observation in the data consists of multiple records. We have to transform the data into a convenient format to apply any Machine Learning algorithm here. There are two prominent ways to create features from such data:- Apply Fourier Transform - Aggregate the dataLet's try out these approaches in this example.  Fourier TransformOne of the prominent methods to approach signal data is to apply Fourier transformation in the data. The Fourier transformed data can be used for training a model.  Aggregate FeaturesAn alternative approach in feature engineering is to aggregate the features and compute key statistics such as mean, median, standard deviation, minimum value, and skew.  Prapre Training Test and Validation DataDue to the very nature of the training data splitting the training test and validation is tricky. We adopted a technique by dividing the training target data frame to train, test, validation set. The ids of each respective set are used to filter the training data to the three splits.<jupyter_code>ttv = create_train_test_split(targets)
test_target = ttv['test']
test_feat = features[features.id.isin(list(test_target.id))]
test_feat_fft = fft_features(test_feat)
test_feat_agg = generate_agg_feats(test_feat)
test_target.to_csv("data/test_tgt.csv", index=False)
save("data/test_fft.npy",test_feat_fft)
test_feat_agg.to_csv("data/test_feat.csv", index=False)
train_target = ttv['train']
train_feat = features[features.id.isin(list(train_target.id))]
train_feat_fft = fft_features(train_feat)
train_feat_agg = generate_agg_feats(train_feat)
train_target.to_csv("data/train_tgt.csv", index=False)
save("data/train_fft.npy",train_feat_fft)
train_feat_agg.to_csv("data/train_feat.csv", index=False)
val_traget = ttv['validate']
val_feat = features[features.id.isin(list(val_traget.id))]
val_feat_fft = fft_features(val_feat)
val_feat_agg = generate_agg_feats(val_feat)
val_traget.to_csv("data/val_tgt.csv", index=False)
save("data/val_fft.npy",val_feat_fft)
val_feat_agg.to_csv("data/val_feat.csv", index=False)
S3Uploader.upload('data/train_tgt.csv', 's3://{}/{}/{}'.format(s3_bucket_name, s3_prefix,'train'))
S3Uploader.upload('data/train_fft.npy', 's3://{}/{}/{}'.format(s3_bucket_name, s3_prefix,'train'))
S3Uploader.upload('data/train_feat.csv', 's3://{}/{}/{}'.format(s3_bucket_name, s3_prefix,'train'))
S3Uploader.upload('data/test_tgt.csv', 's3://{}/{}/{}'.format(s3_bucket_name, s3_prefix,'test'))
S3Uploader.upload('data/test_fft.npy', 's3://{}/{}/{}'.format(s3_bucket_name, s3_prefix,'test'))
S3Uploader.upload('data/test_feat.csv', 's3://{}/{}/{}'.format(s3_bucket_name, s3_prefix,'test'))
S3Uploader.upload('data/val_tgt.csv', 's3://{}/{}/{}'.format(s3_bucket_name, s3_prefix,'val'))
S3Uploader.upload('data/val_fft.npy', 's3://{}/{}/{}'.format(s3_bucket_name, s3_prefix,'val'))
S3Uploader.upload('data/val_feat.csv', 's3://{}/{}/{}'.format(s3_bucket_name, s3_prefix,'val'))<jupyter_output><empty_output><jupyter_text>Trial 1In this trial, we will try to apply multi-output regression with GradientBoostingRegressor.<jupyter_code>sess = sagemaker.session.Session()

create_date = strftime("%Y-%m-%d-%H-%M-%S", gmtime())
nuclear_experiment = Experiment.create(experiment_name="nuclear-reactor-1{}".format(create_date), 
                                              description="Using xgboost to predict reactor params", 
                                              sagemaker_boto_client=boto3.client('sagemaker'))

trial = Trial.create(trial_name="algorithm-mode-trial-{}".format(strftime("%Y-%m-%d-%H-%M-%S", gmtime())), 
                     experiment_name=nuclear_experiment.experiment_name,
                     sagemaker_boto_client=boto3.client('sagemaker'))
debug_rules = [Rule.sagemaker(rule_configs.loss_not_decreasing()),
               Rule.sagemaker(rule_configs.overtraining()),
               Rule.sagemaker(rule_configs.overfit())
              ]
from sagemaker.sklearn.estimator import SKLearn
role = sagemaker.get_execution_role()
sagemaker_session = sagemaker.Session()
script_path = 'train_script.py'

sklearn = SKLearn(
    entry_point=script_path,
    train_instance_type="ml.c4.xlarge",
    role=role,
    sagemaker_session=sagemaker_session,
    rules=debug_rules,
    hyperparameters={'ftype': 'fft'},
    framework_version="0.23-1")
train_s3 = "s3://nukeall/nuclear/train/"
sklearn.fit({'train': train_s3},
             wait=True,
            experiment_config={
                    "ExperimentName": nuclear_experiment.experiment_name, 
                    "TrialName": trial.trial_name,
                    "TrialComponentDisplayName": "Training",
                })<jupyter_output>WARNING:sagemaker:'s3_input' class will be renamed to 'TrainingInput' in SageMaker Python SDK v2.
INFO:sagemaker:Creating training-job with name: sagemaker-scikit-learn-2020-08-13-22-18-17-678<jupyter_text>Model Deployment and TestingWe will use the test FFT features to generate some payload to the model endpoint to test.<jupyter_code>data_capture_prefix = '{}/datacapture_1'.format(s3_prefix)

endpoint_name = "demo-nuke-reactor-new" + strftime("%Y-%m-%d-%H-%M-%S", gmtime())
print("EndpointName = {}".format(endpoint_name))
sklp = sklearn.deploy(initial_instance_count=1,
                      instance_type='ml.m4.xlarge',
                      endpoint_name=endpoint_name,
                      data_capture_config=DataCaptureConfig(enable_capture=True,
                                                            sampling_percentage=100,
                                                            destination_s3_uri='s3://{}/{}'.format(s3_bucket_name,
                                                                                                   data_capture_prefix))
                           )
from sagemaker.predictor import csv_serializer
from sagemaker.predictor import (numpy_deserializer,
                                 npy_serializer
                                )
sklp.content_type = 'application/x-npy'
sklp.serializer = npy_serializer
sklp.deserializer = numpy_deserializer
for idx,sample in enumerate(test_feat_fft[:10]):
    pred = sklp.predict(np.asarray([test_feat_fft[idx]]))
    print(pred)
    time.sleep(0.5)<jupyter_output>[[400. 300. 175.   1.]]
[[400. 300. 175.   1.]]
[[400. 300. 175.   1.]]
[[400. 300. 175.   1.]]
[[400. 300. 175.   1.]]
[[400. 300. 175.   1.]]
[[400. 300. 175.   1.]]
[[400. 300. 175.   1.]]
[[400. 300. 175.   1.]]
[[400. 300. 175.   1.]]<jupyter_text>Clean up<jupyter_code>def cleanup(experiment):
    '''Clean up everything in the given experiment object'''
    for trial_summary in experiment.list_trials():
        trial = Trial.load(trial_name=trial_summary.trial_name)
        
        for trial_comp_summary in trial.list_trial_components():
            trial_step=TrialComponent.load(trial_component_name=trial_comp_summary.trial_component_name)
            print('Starting to delete TrialComponent..' + trial_step.trial_component_name)
            sm.disassociate_trial_component(TrialComponentName=trial_step.trial_component_name, TrialName=trial.trial_name)
            trial_step.delete()
            time.sleep(1)
         
        trial.delete()
    
    experiment.delete()

#cleanup(nuclear_experiment)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10012867942737655, 'fraction_numerical': 0.021392954801351134, 'mean_word_length': 3.7845325125048097, 'pattern_counts': {'":': 3, '<': 27, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '63398', 'license': 'Apache-2.0', 'n_tokens_mistral': 3922, 'n_tokens_neox': 3619, 'n_words': 968, 'path': 'AWS_Training_competition.ipynb', 'repo_name': 'jaganadhg/aws_training_comp_aiml_arch', 'size': '12434'}