forked from aws-deepracer-community/deepracer-analysis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ActionSpace_analysis.py
460 lines (372 loc) · 15.7 KB
/
ActionSpace_analysis.py
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
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
# ---
# jupyter:
# jupytext:
# formats: ipynb,py:light
# text_representation:
# extension: .py
# format_name: light
# format_version: '1.5'
# jupytext_version: 1.15.2
# kernelspec:
# display_name: Python 3 (ipykernel)
# language: python
# name: python3
# ---
# # Action Space analysis for AWS DeepRacer
# This notebook has been built for the [AWS DeepRacer-Analysis](https://github.com/aws-deepracer-community/deepracer-analysis.git)
# provided by the [AWS DeepRacer Community](http://join.deepracing.io).
#
# ## Contributions
# As usual, your ideas are very welcome and encouraged so if you have any suggestions either bring them
# to [the AWS DeepRacer Community](http://join.deepracing.io) or share as code contributions.
#
# ## Requirements
# Installed [AWS DeepRacer-Analysis](https://github.com/aws-deepracer-community/deepracer-analysis.git)
#
# ## Credits
# I would like to thank [the AWS DeepRacer Community](http://join.deepracing.io)
#
# # Log Analysis
#
# Let's get to it.
#
# ## Installs and setups
#
# If you are using an AWS SageMaker Notebook or Sagemaker Studio Lab to run the log analysis, you will need to ensure you install required dependencies. To do that uncomment and run the following:
# +
# Make sure you have the required pre-reqs
# import sys
# # !{sys.executable} -m pip install --upgrade -r requirements.txt
# -
#
# ## Imports
#
# Run the imports block below:
# +
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# %matplotlib inline
from pprint import pprint
from deepracer.tracks import TrackIO, Track
from deepracer.logs import \
SimulationLogsIO as slio, \
PlottingUtils as pu,\
AnalysisUtils as au, \
DeepRacerLog, \
S3FileHandler
import os
# Ignore deprecation warnings we have no power over
import warnings
warnings.filterwarnings('ignore')
# -
# ## Login
#
# Login to AWS. There are several ways to log in:
# 1. On EC2 instance or Sagemaker Notebook with correct IAM execution role assigned.
# 2. AWS credentials available in `.aws/` through using the `aws configure` command. (DeepRacer-for-Cloud's `dr-start-loganalysis` supports this)
# 3. Setting the relevant environment variables by uncommenting the below section.
# +
# os.environ["AWS_DEFAULT_REGION"] = "" #<-Add your region
# os.environ["AWS_ACCESS_KEY_ID"] = "" #<-Add your access key
# os.environ["AWS_SECRET_ACCESS_KEY"] = "" #<-Add you secret access key
# os.environ["AWS_SESSION_TOKEN"] = "" #<-Add your session key if you have one
# -
# ## Load waypoints for the track you want to run analysis on
#
# Remeber that evaluation npy files are a community effort to visualise the tracks in the trainings, they aren't 100% accurate.
#
# Tracks Available:
# +
tu = TrackIO()
for f in tu.get_tracks():
print(f)
# -
# Take the name from results above and paste below to load the key elements of the track and view the outline of it.
# +
track: Track = tu.load_track("reinvent_base")
l_track = track.center_line
l_outer_border = track.outer_border
l_inner_border = track.inner_border
pu.plot_trackpoints(track)
# -
# ## Get the logs
#
# Depending on which way you are training your model, you will need a slightly different way to load the data. The simplest way to read in training data is using the sim-trace files directly from S3.
#
# For other ways to read in data look at the [configuration examples](https://github.com/aws-deepracer-community/deepracer-utils/blob/master/docs/examples.md)
# + tags=["parameters"]
PREFIX='Demo-Reinvent' # Name of the model, without trailing '/'
BUCKET='deepracer-local' # Bucket name is default 'bucket' when training locally
PROFILE=None # The credentials profile in .aws - 'minio' for local training
S3_ENDPOINT_URL=None # Endpoint URL: None for AWS S3, 'http://minio:9000' for local training
# +
fh = S3FileHandler(bucket=BUCKET, prefix=PREFIX, profile=PROFILE, s3_endpoint_url=S3_ENDPOINT_URL)
log = DeepRacerLog(filehandler=fh)
log.load_training_trace()
try:
pprint(log.agent_and_network())
print("-------------")
pprint(log.hyperparameters())
print("-------------")
pprint(log.action_space())
except Exception:
print("Logs not available")
df = log.dataframe()
try:
EPISODES_PER_ITERATION=int(log.hyperparameters()['num_episodes_between_training']/(df.nunique(axis=0)['worker']))
except Exception:
print("Multiple workers not detected, assuming 1 worker")
EPISODES_PER_ITERATION=int(log.hyperparameters()['num_episodes_between_training'])
# -
# ## Load the trace training log
#
# Now that the data is downloaded, we need to load it into memory. We will first read it from file and then convert to data frames in Pandas. [Pandas](https://pandas.pydata.org/) is a Python library for handling and analysing large amounts of data series. Remember this name, you may want to learn more about how to use it to get more information that you would like to get from the logs. Examples below are hardly scratching the surface.
#
# One important information to enter is the setting of your Episodes per iteration hyperparameter. This is used to group the episodes into iterations. This information is valuable when later looking at graphs showing how the training progresses per iteration. You can use it to detect which iteration gave you better outcomes and, if in local training, you could move to that iteration's outcome for submissions in the AWS DeepRacer League or for continuing the training.
#
# The log files you have just gathered above have lines like this one:
# ```
# SIM_TRACE_LOG:799,111,1.7594,4.4353,3.0875,-0.26,2.50,2,1.0000,False,True,71.5802,49,17.67,1555554451.1110387
# ```
# * episode number
# * step number
# * x coordinate
# * y coordinate
# * yaw of the car (where the car is heading)
# * decision about turning (turn value from your action space)
# * decision about throttle (speed value from your action space)
# * decision index (value from your action space)
# * reward value
# * is the car going backwards
# * are all wheels on track?
# * progress in the lap
# * closest waypoint
# * track length
# * timestamp
# +
# Uncomment the line of code below to evaluate a different reward function
# nr.new_reward(df, l_center_line, 'reward.reward_sample') #, verbose=True)
# -
simulation_agg = au.simulation_agg(df)
try:
if df.nunique(axis=0)['worker'] > 1:
print("Multiple workers have been detected, reloading data with grouping by unique_episode")
simulation_agg = au.simulation_agg(df, secondgroup="unique_episode")
except:
print("Multiple workers not detected, assuming 1 worker")
au.analyze_training_progress(simulation_agg, title='Training progress')
au.scatter_aggregates(simulation_agg, 'Stats for all laps')
# +
complete_ones = simulation_agg[simulation_agg['progress']==100]
if complete_ones.shape[0] > 0:
au.scatter_aggregates(complete_ones, 'Stats for complete laps')
else:
print('No complete laps yet.')
# -
# View five best rewarded in completed laps (according to new_reward if you are using it)
complete_ones.nlargest(5, 'reward')
# View five most progressed episodes
simulation_agg.nlargest(5, 'progress')
# View information for a couple last episodes
simulation_agg.tail()
# +
# Set maximum quantity of rows to view for a dataframe display - without that
# the view below will just hide some of the steps
pd.set_option('display.max_rows', 500)
# View all steps data for episode 10
df[df['episode']==320]
# -
# # Extract Action Space List from LOG file
# +
# Extract Action Space List
dgr_norm = 1 # for degrees
if df['steering_angle'].max()<2: dgr_norm = 57.6923 # for radians
class act(object):
def __init__(self, index=None, steer=None, throttle=None, rel_thr=None, color=([0,0,0])):
self.index = index
self.steer = steer
self.throttle = throttle # relative throttle, max = 1
self.rel_thr = rel_thr
self.color = color
maxThrottle = df.speed.max()
AS = df[df['steps'] != 0].groupby(['action'], as_index=False)[['steering_angle','speed']].median()
asl = [None] * AS.shape[0]
for i in range(0,AS.shape[0]):
j = AS.action[i].astype(int)
#asl[AS.action[i].astype(int)] = [AS.action[i].astype(int), round(AS.steer[i]*dgr_norm,2), round(AS.throttle[i],2)]
asl[j] = act(j, round(AS.steering_angle[i]*dgr_norm,2), round(AS.speed[i],2))
asl[j].rel_thr = AS.speed[i] / maxThrottle
cr = 8*max(0,np.sign(asl[j].steer))*abs(asl[j].steer)/255
cg = (0+6*(30-abs(asl[j].steer)))/255
cb = -8*min(0,np.sign(asl[j].steer))*abs(asl[j].steer)/255
asl[AS.action[i].astype(int)].color = ([cr,cg,cb])
asMaxY = maxThrottle + 1
#########################################################
# define some constants for track graphs
trkFrame = 50
trkPlotXmin = df.x.min() - trkFrame
trkPlotXmax = df.x.max() + trkFrame
trkPlotYmin = df.y.min() - trkFrame
trkPlotYmax = df.y.max() + trkFrame
trkPlotXmin = min(l_outer_border[:,0]) - trkFrame
trkPlotXmax = max(l_outer_border[:,0]) + trkFrame
trkPlotYmin = min(l_outer_border[:,1]) - trkFrame
trkPlotYmax = max(l_outer_border[:,1]) + trkFrame
trkSizeX = int(trkPlotXmax - trkPlotXmin)
trkSizeY = int(trkPlotYmax - trkPlotYmin)
trkShiftX = int(trkSizeX - trkPlotXmax)
trkShiftY = int(trkSizeY - trkPlotYmax)
#print(trkSizeX,trkSizeY,trkPlotYmin,trkPlotYmax)
##########################################################
# define some constants for Action Space graphs
asPlotXmin = round(df.steering_angle.min()*dgr_norm,2)
asPlotXmax = round(df.steering_angle.max()*dgr_norm,2)
asPlotYmin = round(df.speed.min(),2)
asPlotYmax = round(df.speed.max(),2)
#df.throttle.min()
#print(asPlotXmin,asPlotXmax,asPlotYmin,asPlotYmax)
###############################################################
print("Actions: \nindex\t\tsteering\tthrottle")
for obj in asl:
print( obj.index, obj.steer, obj.throttle, sep ='\t\t' )
# -
# ## Function definitions
# +
## Action Index Map
def plot_index_map(actSpaceList):
fig = plt.figure(figsize=(7, 4))
ax = fig.add_subplot(111)
for obj in actSpaceList:
N=100
ax.set_title('Action Index Map')
ax.axis([-35, 35, 0, asMaxY])
ax.set(xlabel='Steering', ylabel='Speed', xlim=(35,-35))
scatter = ax.scatter((0.0 + obj.steer), (0.0 + obj.throttle),
color = obj.color,
s=1200 * obj.rel_thr,
alpha=0.85)
ax.text((0.5 - obj.steer/70), (0.0 + obj.throttle/asMaxY),
obj.index,verticalalignment='center',
horizontalalignment='center',
transform=ax.transAxes, color ="w",
fontsize=15)
plt.show()
### Action space histograms
# 4 in 1 Histograms
def plot_4_hist(df, itr=-1, E=-1):
if itr > -1 :
episode_data = df[df['iteration'] == itr]
print('Histograms for iteration:',itr)
else:
if E > -1 :
episode_data = df[df['episode'] == E]
print('Histograms for episode:',E)
else:
episode_data = df[:]
print('Histograms for all episodes:')
fig, axs = plt.subplots(2, 2, sharex='col',figsize=(14, 10), sharey='row', gridspec_kw={'hspace': 0, 'wspace': 0})
(ax1, ax2), (ax3, ax4) = axs
ax3.hist2d(episode_data['steering_angle']*(dgr_norm), episode_data['speed'], bins=(63, 56),range=[[-31,31],[0,asMaxY]])
ax3.set(xlabel='Steering', ylabel='Speed', xlim=(31,-31))
ax2 = plt.subplot(222, polar=True)
ax2.set_theta_zero_location("N")
ax2.hist2d(episode_data['steering_angle']*(dgr_norm/57.6923), episode_data['speed'], bins=(90, 23),range=[[-1.57,1.57],[0,asMaxY]])
# ax2.hist(episode_data['action']*dgr_norm, bins=60)
ax1.hist(episode_data['steering_angle']*dgr_norm, bins=60)
ax4.hist(episode_data['speed'], bins=50, orientation="horizontal")# steer - throttle - actions
for ax in fig.get_axes():
ax.label_outer()
## Big Polar 2D Histogram
def plot_polar_hist(df, itr=-1, E=-1):
if itr > -1 :
episode_data = df[df['iteration'] == itr]
print('Histograms for iteration:',itr)
else:
if E > -1 :
episode_data = df[df['episode'] == E]
print('Histograms for episode:',E)
else:
episode_data = df[:]
print('Histogram for all episodes:')
fig2 = plt.figure(1, figsize=(7, 7))
bx = fig2.add_subplot(111, polar=True)
bx.set_theta_zero_location("N")
bx.hist2d(episode_data['steering_angle']*(dgr_norm/57.6923), episode_data['speed'], bins=(90, 25),range=[[-1.57,1.57],[0,asMaxY]])
## Ploting steps in the episodes with red dots
def plot_episode_red(df, E): #, center_line, inner_border, outer_border):
fig = plt.figure(1, figsize=(trkSizeX/5, trkSizeY/5))
ax = fig.add_subplot(211)
ax.set_aspect(aspect=1)
pu.print_border(ax, track, color="WhiteSmoke") # center_line, inner_border, outer_border)
episode_data = df[df['episode'] == E]
for row in episode_data.iterrows():
x1,y1,action,reward = row[1]['x'], row[1]['y'], row[1]['action'], row[1]['reward']
car_x2, car_y2 = x1 - 0.02, y1
plt.plot([x1, car_x2], [y1, car_y2], 'r.')
## Ploting steps in the episodes with dots of different colors and sizes
def plot_episode_color(df, E): #, center_line, inner_border, outer_border):
fig = plt.figure(1, figsize=(trkSizeX/5, trkSizeY/5))
ax = fig.add_subplot(211)
ax.set_aspect(aspect=1)
pu.print_border(ax, track, color="WhiteSmoke") # center_line, inner_border, outer_border)
episode_data = df[df['episode'] == E]
for row in episode_data.iterrows():
x1,y1,action,reward = row[1]['x'], row[1]['y'], row[1]['action'], row[1]['reward']
actidx = int(action)
action_color = asl[int(action)].color
action_s = (asl[int(action)].throttle / maxThrottle)**2 * 50 # tune the size of the dots
#print(action_color)
#plt.scatter([x1, car_x2], [y1, car_y2], color=action_color, s=action_s, alpha=0.65)
plt.scatter(x1, y1, color=action_color, s=action_s, alpha=0.75)
# -
# # Action Space Visualization
plot_index_map(asl)
# # Analysing data from all episodes
tr_plot = pu.plot_track(df, track, value_field="reward")
plot_4_hist(df)
plot_polar_hist(df)
#
#
# # Analyzing specific iteration
#
#
#
#
# Set iteration id
#itr = 12 # iteration id
itr=df['iteration'].max()-10 # last iteration
for i in range((itr-1)*EPISODES_PER_ITERATION, (itr)*EPISODES_PER_ITERATION):
plot_episode_red(df,i) #,l_inner_border, l_inner_border, l_outer_border)
print('Iteration:',itr)
#plot_episode_as_hist(df, itr=25) # specific iteration
plot_4_hist(df, itr) # last iteration
plot_polar_hist(df, itr)
#
#
# # Analyzing specific episode
#
#
### choose episode id
EPZ = 210
# Plot Index Map to understand graph
plot_index_map(asl)
print("Every dot is one step. Dot size is proportional to the throttle")
print("Colors: Green = Straight, Red = Steering Left, Blue = Steering Right")
plot_episode_color(df,EPZ) #, l_inner_border, l_inner_border, l_outer_border) # arbitrary episode
plot_4_hist(df, E = EPZ)
plot_polar_hist(df, E = EPZ)
#This shows a histogram of actions per waypoint. Will let you spot potentially problematic places
episode = df[df['episode']==EPZ]
episode[:-1].plot.bar(x='closest_waypoint', y='reward',figsize=(16, 6))
# # Analyzing Actions
# ## You can analyze all actions or only set of actions with indexes defined in setActions
aslNum = len(asl)
setActions = range(aslNum) # show graphs for all Actions
#setActions = (0,1,6,8,9) # show graphs only for index set Actions
fig = plt.figure(aslNum)
for i in setActions:
a = asl[i]
print("\n\n Heatmap for action with index {}: steering: {}, throttle: {}".format(a.index, a.steer,a.throttle))
tr_plot = pu.plot_track(df[df['action'] == a.index], track, value_field="reward")
plt.show()