|
|
import numpy as np
|
|
|
import matplotlib.pyplot as plt
|
|
|
import os
|
|
|
from matplotlib.colors import LinearSegmentedColormap
|
|
|
from collections import Counter
|
|
|
import seaborn as sns
|
|
|
|
|
|
def plot_each_feature_alpha(alpha, size, feature_list):
|
|
|
cumsum = 0
|
|
|
fig, ax = plt.subplots(2, 4, figsize=(18, 10))
|
|
|
fig.tight_layout(pad=3.0)
|
|
|
color = ['purple', 'orange', 'green', 'pink']
|
|
|
for id, column in enumerate(feature_list):
|
|
|
bars = np.arange(size[id])
|
|
|
ax[id//4][id%4].bar(bars, alpha[cumsum:cumsum+size[id]], color=color[:size[id]])
|
|
|
ax[id//4][id%4].set_xticks(bars, bars)
|
|
|
ax[id//4][id%4].set_title(column)
|
|
|
cumsum += size[id]
|
|
|
plt.legend()
|
|
|
plt.show()
|
|
|
|
|
|
def plot_feature_alpha(alpha, size, feature_list, title, course_id='dsp_001'):
|
|
|
cumsum = 0
|
|
|
fig, ax = plt.subplots(figsize=(16, 8))
|
|
|
color = ['lightblue', 'dodgerblue', 'blue', 'navy']
|
|
|
group = {}
|
|
|
|
|
|
feature_list = [x.replace('_', ' ') for x in feature_list]
|
|
|
for i in range(len(size)):
|
|
|
for j in range(max(size)):
|
|
|
if j not in group:
|
|
|
group[j] = []
|
|
|
if j < size[i]:
|
|
|
group[j].append(alpha[cumsum+j])
|
|
|
else:
|
|
|
group[j].append(0)
|
|
|
cumsum += size[i]
|
|
|
bar = np.arange(len(feature_list))
|
|
|
width = 0.18
|
|
|
for i in range(max(size)):
|
|
|
plt.bar(bar + width*i, group[i], color=color[i], width=width, edgecolor='black', label=i)
|
|
|
ax.spines['top'].set_visible(False)
|
|
|
ax.spines['right'].set_visible(False)
|
|
|
ax.spines['left'].set_visible(False)
|
|
|
ax.spines['bottom'].set_visible(False)
|
|
|
plt.axhline(alpha[-1], color='black', linestyle='--', label='bias')
|
|
|
plt.xlabel("Metric")
|
|
|
plt.ylabel("Value of alpha")
|
|
|
plt.title(title)
|
|
|
plt.grid(axis='y', linestyle='-', alpha=0.6)
|
|
|
plt.xticks(bar, feature_list, rotation=45)
|
|
|
plt.legend()
|
|
|
title = title.split(' ')
|
|
|
title = '-'.join(title)
|
|
|
if not os.path.exists(f'results/features/{course_id}'):
|
|
|
os.makedirs(f'results/features/{course_id}')
|
|
|
plt.savefig(f'results/features/{course_id}/{title}alpha.png')
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def plot_alpha(alpha, dict_event, dict_action, title=""):
|
|
|
fig, ax = plt.subplots(1, 2, figsize=(10, 4))
|
|
|
alpha = alpha
|
|
|
ax[0].bar(list(dict_event.values()), alpha[:len(dict_event)], align='center',
|
|
|
color=['red' if v < 0 else 'green' for v in alpha[:len(dict_event)]])
|
|
|
ax[0].set_title(title + 'Event weight')
|
|
|
|
|
|
ax[1].bar(list(dict_action.values()), alpha[len(dict_event):len(dict_event)+len(dict_action)], align='center',
|
|
|
color=['red' if v < 0 else 'green' for v in alpha[len(dict_event):]])
|
|
|
ax[1].set_xticklabels(labels=list(dict_action.values()), rotation = 90)
|
|
|
ax[1].set_title(title + 'Action weight')
|
|
|
plt.show()
|
|
|
|
|
|
def plot_all_weeks_alpha(history, dict_event, dict_action,
|
|
|
unique_week=np.arange(10), path=None, title="", whatif=False, topics=[], schedule=None):
|
|
|
|
|
|
lines = 2
|
|
|
cols = len(history)//lines + (len(history)%2!=0)
|
|
|
fig1, ax = plt.subplots(lines, cols, figsize=(5*cols, 4*lines))
|
|
|
if lines == 1:
|
|
|
ax = np.array([ax]).flatten()
|
|
|
for i in range(len(history)):
|
|
|
alpha = history[i]['alpha']
|
|
|
if (len(alpha)==0):
|
|
|
continue
|
|
|
subtitle = f'Week {i + 1}'
|
|
|
axis = ax[i // cols, i % cols] if lines > 1 else ax[i]
|
|
|
|
|
|
if whatif:
|
|
|
axis.bar(np.arange(len(alpha)), alpha, align='center',
|
|
|
color=['red' if v < 0 else 'green' for v in alpha])
|
|
|
labels = list(['Chapter_'+str(x) for x in topics.keys()])
|
|
|
labels.extend(['Chapter Complex', 'Values Prob', 'Value Video', 'Is problem', 'Is video'])
|
|
|
labels.extend(['Action' + str(x) for x in list(dict_action.keys())])
|
|
|
axis.set_xticks(np.arange(len(alpha)), labels=labels)
|
|
|
axis.set_xticklabels(labels=labels, rotation = 90)
|
|
|
else:
|
|
|
axis.bar(np.arange(len(dict_event)), alpha[:len(dict_event)], align='center',
|
|
|
color=['red' if v < 0 else 'green' for v in alpha[:len(dict_event)]], label='Event')
|
|
|
n_event_action = len(dict_event) + len(dict_action)
|
|
|
axis.bar(np.arange(len(dict_event), len(dict_event) + len(dict_action)), alpha[len(dict_event):n_event_action], align='center',
|
|
|
color=['violet' if v < 0 else 'cyan' for v in alpha[len(dict_event):]], label='Action')
|
|
|
if (len(alpha) > n_event_action):
|
|
|
axis.bar(len(alpha), alpha[-1], align='center', color='black', linewidth=2, label='Intercept')
|
|
|
axis.axhline(y=alpha[-1], color='black', linestyle='--')
|
|
|
axis.set_title(subtitle)
|
|
|
fig1.suptitle(title + 'Event & action weight', weight='bold')
|
|
|
fig1.tight_layout()
|
|
|
fig2, ax = plt.subplots(lines, cols, figsize=(20, 4*lines))
|
|
|
if lines == 1:
|
|
|
ax = np.array([ax]).flatten()
|
|
|
for i in range(len(history)):
|
|
|
train_loss = history[i]['train loss']
|
|
|
if (len(train_loss)==0):
|
|
|
continue
|
|
|
subtitle = f'Week {i + 1}'
|
|
|
axis = ax[i // cols, i % cols] if lines > 1 else ax[i]
|
|
|
axis.plot(np.arange(len(train_loss)), train_loss)
|
|
|
axis.set_title(subtitle)
|
|
|
fig2.suptitle(title + 'Train loss', weight='bold')
|
|
|
if path is not None:
|
|
|
if not os.path.exists(path):
|
|
|
os.makedirs(path)
|
|
|
save_title = title.split(' ')
|
|
|
save_title = '-'.join(save_title)
|
|
|
fig1.savefig(os.path.join(path, save_title + 'alpha.jpg'))
|
|
|
fig2.savefig(os.path.join(path, save_title +'train_loss.jpg'))
|
|
|
fig2.tight_layout()
|
|
|
plt.legend()
|
|
|
plt.tight_layout()
|
|
|
plt.show()
|
|
|
plt.close('all')
|
|
|
|
|
|
def plot_all_weeks_reward(history, dict_event, dict_action,
|
|
|
unique_week=np.arange(10), main_title="", path=None, schedule=None):
|
|
|
"""
|
|
|
Plot reward for all weeks
|
|
|
return heatmap of reward
|
|
|
"""
|
|
|
map_label_event = list(dict_event.keys())
|
|
|
if schedule is not None:
|
|
|
map_label_event = [schedule.iloc[x]['chapter'] for x in dict_event.keys()]
|
|
|
|
|
|
|
|
|
lines = 2
|
|
|
cols = len(history) // lines + (len(history) % 2 != 0)
|
|
|
|
|
|
fig, ax = plt.subplots(lines, cols, figsize=(8 * cols, 10 * lines))
|
|
|
if lines == 1:
|
|
|
ax = np.array([ax]).flatten()
|
|
|
|
|
|
|
|
|
colors = ['#fa8072', 'white', '#00a86b']
|
|
|
cmap = LinearSegmentedColormap.from_list('custom', list(zip(np.linspace(0, 1, len(colors)), colors)))
|
|
|
|
|
|
|
|
|
for i in range(len(history)):
|
|
|
reward = history[i]['reward']
|
|
|
if (len(reward)==0):
|
|
|
continue
|
|
|
title = f'Week {i + 1}'
|
|
|
axis = ax[i // cols, i % cols] if lines > 1 else ax[i]
|
|
|
if schedule is not None:
|
|
|
sorted_indices = np.argsort(map_label_event)
|
|
|
sorted_map_event = np.sort(map_label_event)
|
|
|
sorted_reward = reward[sorted_indices]
|
|
|
im = axis.imshow(sorted_reward, cmap=cmap, aspect='auto', interpolation='nearest')
|
|
|
_, unique_indices = np.unique(sorted_map_event, return_index=True)
|
|
|
|
|
|
axis.set_yticks(np.arange(len(sorted_map_event)))
|
|
|
axis.set_yticklabels(['W' + str(sorted_map_event[x]) if x in unique_indices else None
|
|
|
for x in range(len(sorted_map_event))], fontsize=23)
|
|
|
axis.set_ylabel('Chapters in Week', fontsize=23)
|
|
|
|
|
|
else:
|
|
|
im = axis.imshow(reward, cmap=cmap, aspect='auto', interpolation='nearest', vmin=-1, vmax=1)
|
|
|
|
|
|
|
|
|
|
|
|
axis.set_xticks(np.arange(len(list(dict_action.values()))), labels=list(dict_action.values()))
|
|
|
axis.set_xticklabels(labels=list(dict_action.values()), rotation = 90, fontsize=23)
|
|
|
axis.set_title(title, fontsize=30)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fig.colorbar(im, ax=axis, orientation='vertical', fraction=0.04, pad=0.04)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
|
|
|
if path is not None:
|
|
|
if not os.path.exists(path):
|
|
|
os.makedirs(path)
|
|
|
save_title = main_title.split(' ')
|
|
|
save_title = '-'.join(save_title)
|
|
|
fig.savefig(os.path.join(path, save_title+'reward.jpg'), dpi=500)
|
|
|
fig.savefig(os.path.join(path, save_title+'reward.svg'), dpi=500)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def plot_problem_event_alpha(history, dict_event, dict_action, problem_event, unique_week=np.arange(10)):
|
|
|
cols=5
|
|
|
lines = len(history)//cols + (1 if len(history)%cols != 0 else 0)
|
|
|
cols = min(cols, len(history))
|
|
|
fig, ax = plt.subplots(lines, cols, figsize=(10, 8))
|
|
|
if lines == 1:
|
|
|
ax = np.array([ax]).flatten()
|
|
|
fig.tight_layout(pad=3.0)
|
|
|
for i in range(len(history)):
|
|
|
color = ['blue' if dict_event[i] in problem_event else 'orange' for i in range(len(dict_event))]
|
|
|
alpha = history[i]['alpha']
|
|
|
if len(alpha) == 0:
|
|
|
continue
|
|
|
title = f'Week {unique_week[i] + 1}'
|
|
|
axis = ax[i // cols, i % cols] if lines > 1 else ax[i]
|
|
|
axis.bar(list(dict_event.keys()), alpha[:len(dict_event)], align='center', color=color)
|
|
|
axis.set_title(title)
|
|
|
plt.show()
|
|
|
|
|
|
def plot_problem_event_reward(history, map_problem_id, map_video_id, dict_action):
|
|
|
colors = ['red', 'white', 'green']
|
|
|
_, ax = plt.subplots(1, 2, figsize=(16, 5))
|
|
|
cmap = LinearSegmentedColormap.from_list('custom', list(zip(np.linspace(0, 1, len(colors)), colors)))
|
|
|
reward = history['reward']
|
|
|
print(reward.shape)
|
|
|
im1 = ax[0].imshow(reward[map_problem_id, :], cmap=cmap, aspect='auto', interpolation='nearest', vmin=-1, vmax=1)
|
|
|
im2 = ax[1].imshow(reward[map_video_id, :], cmap=cmap, aspect='auto', interpolation='nearest', vmin=-1, vmax=1)
|
|
|
ax[0].set_title('Problem Reward')
|
|
|
ax[0].set_xticks(np.arange(len(list(dict_action.values()))), labels=list(dict_action.values()))
|
|
|
ax[0].set_xticklabels(labels=list(dict_action.values()), rotation = 90)
|
|
|
ax[1].set_title('Video Reward')
|
|
|
ax[1].set_xticks(np.arange(len(list(dict_action.values()))), labels=list(dict_action.values()))
|
|
|
ax[1].set_xticklabels(labels=list(dict_action.values()), rotation = 90)
|
|
|
plt.tight_layout()
|
|
|
plt.show()
|
|
|
|
|
|
def distribution_skillset(trajectories_each_week, world, columns=['topic']):
|
|
|
fig, ax = plt.subplots(2, 5, figsize=(20, 10))
|
|
|
for i, trajectories in enumerate(trajectories_each_week):
|
|
|
data = []
|
|
|
for trajectory in trajectories:
|
|
|
for state, action, _ in trajectory:
|
|
|
topic = world.get_features(state, action)['topic']
|
|
|
data.extend(topic)
|
|
|
word_counts = Counter(data)
|
|
|
print(word_counts)
|
|
|
unique_words = list(word_counts.keys())
|
|
|
word_counts_values = list(word_counts.values())
|
|
|
ax[i//5, i%5].bar(unique_words, word_counts_values, color='skyblue')
|
|
|
ax[i//5, i%5].set_title(f'Week {i + 1}')
|
|
|
plt.xticks(rotation=90)
|
|
|
plt.grid(axis='y')
|
|
|
plt.show()
|
|
|
|
|
|
def plot_accuracy_synthesize(accs_training, accs_full_synthesize, accs_personalized_syn, weeks):
|
|
|
plt.figure(figsize=(12, 6))
|
|
|
ax = plt.gca()
|
|
|
ax.spines['top'].set_visible(False)
|
|
|
ax.spines['right'].set_visible(False)
|
|
|
ax.spines['left'].set_visible(False)
|
|
|
ax.spines['bottom'].set_visible(False)
|
|
|
sns.lineplot(data=accs_training, x='Week', y='Accuracy', label='Prediction Model')
|
|
|
sns.lineplot(data=accs_full_synthesize, x='Week', y='Accuracy', label='Synthesized Classrooms')
|
|
|
sns.lineplot(data=accs_personalized_syn, x='Week', y='Accuracy', label='Personalized Trajectories')
|
|
|
plt.xlabel('Number of Weeks')
|
|
|
plt.xticks(weeks)
|
|
|
plt.ylabel('Accuracy')
|
|
|
plt.legend()
|
|
|
plt.grid(axis='y')
|
|
|
plt.show()
|
|
|
|
|
|
def plot_a_week_whatif(week_data, week, course):
|
|
|
plt.figure(figsize=(12, 8))
|
|
|
sns.barplot(
|
|
|
x='Chapter',
|
|
|
y='Mean Average Impact',
|
|
|
data=week_data,
|
|
|
errorbar="sd",
|
|
|
legend=False
|
|
|
)
|
|
|
plt.grid(axis='y', linestyle='-', alpha=0.6)
|
|
|
ax = plt.gca()
|
|
|
ax.spines['top'].set_visible(False)
|
|
|
ax.spines['right'].set_visible(False)
|
|
|
ax.spines['left'].set_visible(False)
|
|
|
ax.spines['bottom'].set_visible(False)
|
|
|
plt.xlabel("Topic")
|
|
|
plt.ylabel('Mean Average Effectiveness')
|
|
|
plt.title(f'What-if Classroom in Week {week}')
|
|
|
plt.savefig(f'results/whatif/{course}/whatif-analysis/whatif_results_week_{week}.png')
|
|
|
plt.show()
|
|
|
plt.close()
|
|
|
|
|
|
def plot_heatmap_whatif(whatif_results, course):
|
|
|
heatmap_data = whatif_results.pivot_table(
|
|
|
index='Week',
|
|
|
columns='Chapter',
|
|
|
values='SD Average Impact',
|
|
|
aggfunc='mean'
|
|
|
)
|
|
|
plt.figure(figsize=(15, 8))
|
|
|
sns.heatmap(heatmap_data, annot=False, cmap='Blues', linewidths=.5)
|
|
|
plt.ylabel('Week')
|
|
|
plt.xlabel("Week")
|
|
|
plt.savefig(f'results/whatif/{course}/whatif-analysis/whatif_results_heatmap.png')
|
|
|
plt.show()
|
|
|
|