-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathev-demo
executable file
·416 lines (334 loc) · 15.3 KB
/
ev-demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
#!/bin/bash
######################################################################
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. #
# SPDX-License-Identifier: MIT-0 #
######################################################################
############################################################################################
# EV Demo Description:
# --------------------------
# This script demonstrates an application of the aws-do-pm framework for a single electric vehicle (EV).
# A a configured number of electric vehicles, each driving a specified number of routes is simulated
# through generation of vehicle, route, and battery data using an emperical model.
# A generic neural network model is then trained with a dataset combined from all initial routes.
# A single vehicle is selected randomly. The model is then updated for the
# specific vehicle by using data from the next route, creating a digital twin that is tuned for the selected asset.
# Model sensitivity analysis is performed to assess the parameter interactions.
# The configured number of predictions are also made for the modeled vehicle, assessing the error and updating the model if necessary.
# The demo also shows the capability of aws-do-pm to serve a model as a gRPC service, implicitly or explicitly.
############################################################################################
############################################################################################
# CONFIGURATION:
# Import system settings
source .env
# Enable QUIET mode to allow command output parsing
export QUIET=true
# Number of vehicles and routes to generate. Only one vehicle will be randomly selected for the demo.
export NUM_VEHICLES=10
export NUM_ROUTES=10
# Number of routes to predict. Route 0 is used for training, route 1 is used for update, predictions start from route 2.
# NUM_PREDICTED_ROUTES<=NUM_ROUTES-2
export NUM_PREDICTED_ROUTES=3
# Model update threshold. If the prediction error is greater than this value, the model for the current vehicle will be udpated.
export MODEL_UPDATE_THRESHOLD=0.05
# If needed, set target orchestrator
if [ ! "$TO" == "$PM_TO" ]; then
echo $PM_TO > wd/.to
source .env
fi
############################################################################################
############################################################################################
# Functions:
function clear_system(){
# Erase all data, delete storage bucket, local work directory, remove graph
echo ""
echo "================================================================================="
echo " Clearing system ..."
echo "================================================================================="
echo ""
./pm system clear
}
function initialize_system(){
# Create storage bucket and local work directory, creates graph,
# register system techniques
echo ""
echo "================================================================================="
echo " Initializing system ..."
echo "================================================================================="
echo ""
./pm system init
}
function generate_ev_data(){
# Generate raw data for fleet of $NV number of vehicles and $NR routes each
# and save it in directory $DP
DP=$1
NV=$2
NR=$3
if [ -d $DP ]; then
echo ""
echo "Generated data found in path $DP"
echo "Skipping data generation"
echo ""
else
echo ""
echo "================================================================================="
echo " Generating Electric Vehicle data for $NV vehicles, $NR routes each ..."
echo "================================================================================="
echo ""
echo "Number of electrical vehicles: ${NUM_VEHICLES}"
echo "Number of routes per vehicle: ${NUM_ROUTES}"
echo ""
# Login to Docker registry if needed
./login.sh
CMD="docker run -it --rm -v ${PROJECT_HOME}/wd:/wd -e NUM_VEHICLES=$NV -e NUM_ROUTES=$NR -e DEST_PATH=$DP ${REGISTRY}aws-do-pm-ev_datagen_em${TAG} /bin/bash -c /src/python/example/ev/task/ev_data_generate.sh"
if [ "${VERBOSE}" == "true" ]; then
echo "${CMD}"
fi
eval "${CMD}"
fi
}
function register_raw_dataset(){
# Upload and register raw EV dataset in aws-do-pm system
# Read data from folder $DP, include information about
# number of vehicles $NV and number of routes $NR in metadata
DP=$1
NV=$2
NR=$3
echo ""
echo "================================================================================="
echo " Registering raw data set ..."
echo "================================================================================="
echo ""
OUTPUT=$(./pm data register wd/generated_ev_data overall_pd.csv "Generated raw EV data set for a fleet of ${NV} vehicles and ${NR} routes each")
echo "$OUTPUT"
RAW_EV_DATA_ID_OUT=$(echo "$OUTPUT" | grep data | grep -v load | grep -v path | grep -v python | grep -v task)
RAW_EV_DATA_ID=$(echo $RAW_EV_DATA_ID_OUT | tr -d '\r' | cut -d '/' -f 2)
echo "RAW_EV_DATA_ID=$RAW_EV_DATA_ID"
}
function register_training_dataset(){
# Upload and register model training dataset in aws-do-pm system
# Read dataset from local folder $DP
DP=$1
echo ""
echo "================================================================================="
echo " Registering data for model training ..."
echo "================================================================================="
echo ""
OUTPUT=$(./pm data register $DP input_output.json "Generated EV data for model training")
echo "$OUTPUT"
TRAIN_DATA_ID_RAW=$(echo "$OUTPUT" | grep data\/ | grep -v load | grep -v path | grep -v python)
TRAIN_DATA_ID=$(echo $TRAIN_DATA_ID_RAW | tr -d '\r' | cut -d '/' -f 2)
echo "TRAIN_DATA_ID=$TRAIN_DATA_ID"
}
function build_model(){
# Build EV battery degradation model using Artificial Neural Network modeling technique
# Use specified data ID $DID
DID=$1
echo ""
echo "================================================================================="
echo " Building Neural Network model using DATA_ID $DID ..."
echo "================================================================================="
echo ""
OUTPUT=$(./pm model build $DID)
echo "$OUTPUT"
MODEL_ID_RAW=$(echo "$OUTPUT" | grep model\/ | grep -v nitializing | grep -v ported | grep -v sync | grep -v upload)
echo "MODEL_ID_RAW=$MODEL_ID_RAW"
MODEL_ID=$(echo $MODEL_ID_RAW | tr -d '\r' | cut -d '/' -f 2)
echo "MODEL_ID=$MODEL_ID"
}
function register_custom_technique(){
# Register EV data selection technique
# This is a custom technique which extracts data for a particular electric vehicle and route
# and saves it as a new dataset in the aws-do-pm system
echo ""
echo "================================================================================="
echo " Registering custom technique for EV data selection ..."
echo "================================================================================="
echo ""
./cp-to.sh platform 1 src/python/example/ev/technique/ev_data_select/technique_registration_ev_data_select.json /tmp/technique_registration_ev_data_select.json
echo "{ \"technique_name\": \"technique_registration_graphdb\", \"analyticSettings\": { \"config\": \"/tmp/technique_registration_ev_data_select.json\" } }" > ${PM_ROOT_PATH}/tmp/task_register_technique_ev_data_select.json
./pm do ${PM_ROOT_PATH}/tmp/task_register_technique_ev_data_select.json
}
function select_data(){
# Use EV data selection technique to extract data for vehicle id $VID, route id $RID
# from raw data set $RDID and save it as a new dataset in the aws-do-pm system
RDID=$1
VID=$2
RID=$3
echo ""
echo "================================================================================="
echo " Selecting new data for vehicle # $VID, route # $RID ..."
echo "================================================================================="
echo ""
./pm go select ev data | sed -e "s/<data_id>/${RDID}/g" -e "s/<vehicle_id>/${VID}/g" -e "s/<route_id>/${RID}/g" > ${PM_ROOT_PATH}/tmp/task_ev_data_select.json
OUTPUT=$(./pm do ${PM_ROOT_PATH}/tmp/task_ev_data_select\.json)
echo "$OUTPUT"
NEW_DATA_ID_OUT=$(echo "$OUTPUT" | grep data\/ | grep -v load | grep -v path | grep -v port | grep -v task)
NEW_DATA_ID=$(echo $NEW_DATA_ID_OUT | tr -d '\r' | cut -d '/' -f 2)
echo "NEW_DATA_ID=$NEW_DATA_ID"
}
function update_model(){
# Update model id $MID using the UKF technique and data $DID
MID=$1
DID=$2
echo ""
echo "================================================================================="
echo " Updating model $MID using data $DID ..."
echo "================================================================================="
echo ""
OUTPUT=$(./pm model update $MID $DID)
echo "$OUTPUT"
UPDATED_MODEL_ID_RAW=$(echo "$OUTPUT" | grep Exported | grep model\/ | grep -v metadata)
UPDATED_MODEL_ID=$(echo $UPDATED_MODEL_ID_RAW | cut -d '/' -f 3 | tr -d '\r')
echo "UPDATED_MODEL_ID=$UPDATED_MODEL_ID"
}
function deploy_model_service(){
# Start gRPC model service for model $MID
MID=$1
echo ""
echo "================================================================================="
echo " Deploying model $MID as a gRPC service ..."
echo "================================================================================="
echo ""
OUTPUT=$(./pm service deploy ${MID})
echo "$OUTPUT"
SERVICE_ID_RAW=$(echo "$OUTPUT" | grep SERVICE_ID)
echo "SERVICE_ID_RAW=$SERVICE_ID_RAW"
SERVICE_ID=$(echo "$SERVICE_ID_RAW" | cut -d '=' -f 2 | tr -d '\r')
echo "SERVICE_ID=$SERVICE_ID"
}
function predict(){
# Generate a predicted dataset using the specified model service $SID and data $DID
SID=$1
DID=$2
echo ""
echo "================================================================================="
echo " Predicting with model service $SID and data $DID ..."
echo "================================================================================="
echo ""
OUTPUT=$(./pm model predict $SID $DID)
echo "$OUTPUT"
PREDICTED_DATA_ID_RAW=$(echo "$OUTPUT" | grep data | grep -v s3 | grep -v kubectl | grep -v ported | grep -v task)
PREDICTED_DATA_ID=$(echo "$PREDICTED_DATA_ID_RAW" | cut -d '/' -f 2 | tr -d '\r')
echo "PREDICTED_DATA_ID=$PREDICTED_DATA_ID"
PREDICTION_ERROR=$(./pm data describe ${PREDICTED_DATA_ID} | jq -r .mae_overall)
echo "PREDICTION_ERROR=$PREDICTION_ERROR"
}
function analyze_model_sensitivity(){
# Analyze model sensitivity using the specified model id $MID and data $DID
MID=$1
DID=$2
echo ""
echo "================================================================================="
echo " Analyzing model sensitivity using model $MID and data $DID ..."
echo "================================================================================="
echo ""
./pm model sensitivity $MID $DID
}
function destroy_model_service(){
# Shutdown and remove the specified model service $SID
SID=$1
echo ""
echo "================================================================================="
echo " Destroying gRPC service $SID ..."
echo "================================================================================="
echo ""
OUTPUT=$(./pm service destroy ${SID})
echo "$OUTPUT"
}
function demo_start(){
# Display demo start message
echo ""
echo "================================================================================="
echo " Executing EV demo "
echo " for a single vehicle, randomly selected from "
echo " a fleet of $NUM_VEHICLES electric vehicles "
echo " driving $NUM_ROUTES routes each "
echo "================================================================================="
echo ""
TIMESTAMP_START=$(date +%Y%m%d-%H%M%S)
TIME_START=$(date +%s)
echo ""
echo "Launch time: ${TIMESTAMP_START}"
echo ""
}
function demo_end(){
# Display demo completed message
echo ""
echo "================================================================================="
echo " EV demo completed. "
echo " Browse model and data results at http://${PM_UI_HOST_EXT}:${PM_UI_PORT_EXT}"
echo " See resulting graph at http://${PM_GRAPHDB_HOST_EXT}:${PM_GRAPHDB_PORT_EXT}"
echo "================================================================================="
echo ""
TIMESTAMP_END=$(date +%Y%m%d-%H%M%S)
TIME_END=$(date +%s)
stty sane
echo ""
echo "Launch end time: ${TIMESTAMP_END}"
echo ""
echo "Total elapsed time: $(( (${TIME_END} - ${TIME_START})/60 )) minutes"
echo ""
}
############################################################################################
# Demo:
# Print start headers
demo_start
# Delete any existing data and graphs
clear_system
# Create storage and initialize graph
initialize_system
# Generate raw data for configured number of vehicles and routes
generate_ev_data wd/generated_ev_data $NUM_VEHICLES $NUM_ROUTES
# Import and register raw dataset in system
register_raw_dataset wd/generated_ev_data $NUM_VEHICLES $NUM_ROUTES
# Import and register training data
register_training_dataset wd/generated_ev_data/train_data
# Train neural network using route 0 from all vehicles
build_model $TRAIN_DATA_ID
# Register a user-defined technique for selection of vehicle and route from the raw dataset
register_custom_technique
# Randomly select a vehicle id and route number
UPDATE_VEHICLE_ID=$(seq 0 $((NUM_VEHICLES-1)) | sort -R | head -n 1)
UPDATE_ROUTE_ID=1
# Select data for the randomly selected vehicle id and route number using the custom technique
select_data $RAW_EV_DATA_ID $UPDATE_VEHICLE_ID $UPDATE_ROUTE_ID
# Update the generic neural network model with the data from the selected vehicle
# This method will automatically deploy the model as a service to perform the update
# and destroy the service when the update is completed
update_model $MODEL_ID $NEW_DATA_ID
# Analyze sensitivity of the model to changes of the model inputs
# This method will also automatically deploy the model as a service to perform the analysis
# and destroy the service when the analysis is completed
analyze_model_sensitivity $UPDATED_MODEL_ID $NEW_DATA_ID
# Explicitly deploy the model as a service to perform the specified number of predictions
deploy_model_service $UPDATED_MODEL_ID
echo "SERVICE_ID=$SERVICE_ID"
# Predict the next routes and update the model when the prediction error exceeds the threshold
r=2
pr=0
SELECTED_VEHICLE=$UPDATE_VEHICLE_ID
while [ $pr -lt $NUM_PREDICTED_ROUTES ]; do
route=$((r+pr))
if [ $route -lt $NUM_ROUTES ]; then
echo ""
echo "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv"
echo " Predicting route $route for vehicle ${SELECTED_VEHICLE} ..."
select_data $RAW_EV_DATA_ID ${SELECTED_VEHICLE} $route
SERVICE_ID_V=${SERVICE_ID}
predict ${SERVICE_ID_V} ${NEW_DATA_ID}
if (( $(echo "$PREDICTION_ERROR $MODEL_UPDATE_THRESHOLD" | awk '{print ($1 > $2)}') )); then
echo ""
echo "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv"
echo " Updating model for vehicle for vehicle ${SELECTED_VEHICLE} ..."
echo "Using service id ${SERVICE_ID_V}"
update_model ${SERVICE_ID_V} ${NEW_DATA_ID}
echo "Configuring service id ${SERVICE_ID_V} with model ${UPDATED_MODEL_ID}"
./pm service configure ${SERVICE_ID_V} ${UPDATED_MODEL_ID}
fi
fi
pr=$((pr+1))
done
# Destroy the model service explicitly
destroy_model_service $SERVICE_ID
# Print footnotes
demo_end