Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/CyberBattleSim
Path: blob/main/cyberbattle/agents/baseline/plotting.py
597 views
1
# Copyright (c) Microsoft Corporation.
2
# Licensed under the MIT License.
3
4
"""Plotting helpers for agent banchmarking"""
5
6
import matplotlib.pyplot as plt # type:ignore
7
import numpy as np
8
9
import matplotlib # type: ignore
10
11
matplotlib.use("Agg")
12
13
14
def new_plot(title):
15
"""Prepare a new plot of cumulative rewards"""
16
plt.figure(figsize=(10, 8))
17
plt.ylabel("cumulative reward", fontsize=20)
18
plt.xlabel("step", fontsize=20)
19
plt.xticks(size=20)
20
plt.yticks(size=20)
21
plt.title(title, fontsize=12)
22
23
24
def pad(array, length):
25
"""Pad an array with 0s to make it of desired length"""
26
padding = np.zeros((length,))
27
padding[: len(array)] = array
28
return padding
29
30
31
def plot_episodes_rewards_averaged(results):
32
"""Plot cumulative rewards for a given set of specified episodes"""
33
max_iteration_count = np.max([len(r) for r in results["all_episodes_rewards"]])
34
35
all_episodes_rewards_padded = [pad(rewards, max_iteration_count) for rewards in results["all_episodes_rewards"]]
36
cumrewards = np.cumsum(all_episodes_rewards_padded, axis=1)
37
avg = np.average(cumrewards, axis=0)
38
std = np.std(cumrewards, axis=0)
39
x = [i for i in range(len(std))]
40
plt.plot(x, avg, label=results["title"])
41
plt.fill_between(x, avg - std, avg + std, alpha=0.5)
42
43
44
def fill_with_latest_value(array, length):
45
pad = length - len(array)
46
if pad > 0:
47
return np.pad(array, (0, pad), mode="edge")
48
else:
49
return array
50
51
52
def plot_episodes_availability_averaged(results):
53
"""Plot availability for a given set of specified episodes"""
54
data = results["all_episodes_availability"]
55
longest_episode_length = np.max([len(r) for r in data])
56
57
all_episodes_padded = [fill_with_latest_value(av, longest_episode_length) for av in data]
58
avg = np.average(all_episodes_padded, axis=0)
59
std = np.std(all_episodes_padded, axis=0)
60
x = [i for i in range(len(std))]
61
plt.plot(x, avg, label=results["title"])
62
plt.fill_between(x, avg - std, avg + std, alpha=0.5)
63
64
65
def plot_episodes_length(learning_results):
66
"""Plot length of every episode"""
67
plt.figure(figsize=(10, 8))
68
plt.ylabel("#iterations", fontsize=20)
69
plt.xlabel("episode", fontsize=20)
70
plt.xticks(size=20)
71
plt.yticks(size=20)
72
plt.title("Length of each episode", fontsize=12)
73
74
for results in learning_results:
75
iterations = [len(e) for e in results["all_episodes_rewards"]]
76
episode = [i for i in range(len(results["all_episodes_rewards"]))]
77
plt.plot(episode, iterations, label=f"{results['title']}")
78
79
plt.legend(loc="upper right")
80
plt.show()
81
82
83
def plot_each_episode(results):
84
"""Plot cumulative rewards for each episode"""
85
for i, episode in enumerate(results["all_episodes_rewards"]):
86
cumrewards = np.cumsum(episode)
87
x = [i for i in range(len(cumrewards))]
88
plt.plot(x, cumrewards, label=f"Episode {i}")
89
90
91
def plot_all_episodes(r):
92
"""Plot cumulative rewards for every episode"""
93
new_plot(r["title"])
94
plot_each_episode(r)
95
plt.legend(loc="lower right")
96
plt.show()
97
98
99
def plot_averaged_cummulative_rewards(title, all_runs, show=True, save_at=None):
100
"""Plot averaged cumulative rewards"""
101
new_plot(title)
102
for r in all_runs:
103
plot_episodes_rewards_averaged(r)
104
plt.legend(loc="lower right")
105
if save_at:
106
plt.savefig(save_at)
107
if show:
108
plt.show()
109
110
111
def plot_averaged_availability(title, all_runs, show=False):
112
"""Plot averaged network availability"""
113
plt.figure(figsize=(10, 8))
114
plt.ylabel("network availability", fontsize=20)
115
plt.xlabel("step", fontsize=20)
116
plt.xticks(size=20)
117
plt.yticks(size=20)
118
plt.title(title, fontsize=12)
119
for r in all_runs:
120
plot_episodes_availability_averaged(r)
121
plt.legend(loc="lower right")
122
if show:
123
plt.show()
124
125
126
def new_plot_loss():
127
"""Plot MSE loss averaged over all episodes"""
128
plt.figure(figsize=(10, 8))
129
plt.ylabel("loss", fontsize=20)
130
plt.xlabel("episodes", fontsize=20)
131
plt.xticks(size=12)
132
plt.yticks(size=20)
133
plt.title("Loss", fontsize=12)
134
135
136
def plot_all_episodes_loss(all_episodes_losses, name, label):
137
"""Plot loss for one learning episode"""
138
x = [i for i in range(len(all_episodes_losses))]
139
plt.plot(x, all_episodes_losses, label=f"{name} {label}")
140
141
142
def running_mean(x: np.ndarray, size):
143
"""return moving average of x for a window of lenght 'size'"""
144
cumsum = np.cumsum(np.insert(x, 0, 0))
145
return np.subtract(cumsum[size:], cumsum[:-size]) / float(size)
146
147
148
class PlotTraining:
149
"""Plot training-related stats"""
150
151
def __init__(self, title, render_each_episode):
152
self.episode_durations = []
153
self.title = title
154
self.render_each_episode = render_each_episode
155
156
def plot_durations(self, average_window=5):
157
# plt.figure(2)
158
plt.figure()
159
# plt.clf()
160
durations_t = np.array(self.episode_durations, dtype=np.float32)
161
plt.title("Training...")
162
plt.xlabel("Episode")
163
plt.ylabel("Duration")
164
plt.title(self.title, fontsize=12)
165
166
episodes = [i + 1 for i in range(len(self.episode_durations))]
167
plt.plot(episodes, durations_t)
168
# plot episode running averages
169
if len(durations_t) >= average_window:
170
means = running_mean(durations_t, average_window)
171
means = np.concatenate((np.zeros(average_window - 1), means))
172
plt.plot(episodes, means)
173
174
# display.display(plt.gcf())
175
plt.show()
176
177
def episode_done(self, length):
178
self.episode_durations.append(length)
179
if self.render_each_episode:
180
self.plot_durations()
181
182
def plot_end(self):
183
self.plot_durations()
184
plt.ioff() # type: ignore
185
# plt.show()
186
187
188
def length_of_all_episodes(run):
189
"""Get the length of every episode"""
190
return [len(e) for e in run["all_episodes_rewards"]]
191
192
193
def reduce(x, desired_width):
194
return [np.average(c) for c in np.array_split(x, desired_width)]
195
196
197
def episodes_rewards_averaged(run):
198
"""Plot cumulative rewards for a given set of specified episodes"""
199
max_iteration_count = np.max([len(r) for r in run["all_episodes_rewards"]])
200
all_episodes_rewards_padded = [pad(rewards, max_iteration_count) for rewards in run["all_episodes_rewards"]]
201
cumrewards = np.cumsum(all_episodes_rewards_padded, axis=1)
202
avg = np.average(cumrewards, axis=0)
203
return list(avg)
204
205
206
def episodes_lengths_for_all_runs(all_runs):
207
return [length_of_all_episodes(run) for run in all_runs]
208
209
210
def averaged_cummulative_rewards(all_runs, width):
211
return [reduce(episodes_rewards_averaged(run), width) for run in all_runs]
212
213