Merge remote-tracking branch 'origin/journal' into journal

# Conflicts:
#	journal_soup_basins.py
This commit is contained in:
steffen-illium
2021-06-25 10:29:39 +02:00

View File

@@ -1,19 +1,23 @@
from pathlib import Path
import pickle import pickle
from tqdm import tqdm
import random import random
import copy import copy
from functionalities_test import is_identity_function, test_status, is_zero_fixpoint, is_divergent, is_secondary_fixpoint
from network import Net from pathlib import Path
from visualization import plot_loss, plot_3d_soup
import numpy as np import numpy as np
from tabulate import tabulate
from sklearn.metrics import mean_absolute_error as MAE
from sklearn.metrics import mean_squared_error as MSE
import pandas as pd import pandas as pd
import seaborn as sns import seaborn as sns
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
from sklearn.metrics import mean_absolute_error as MAE
from sklearn.metrics import mean_squared_error as MSE
from tabulate import tabulate
from tqdm import tqdm
from functionalities_test import is_identity_function, test_status, is_zero_fixpoint, is_divergent, \
is_secondary_fixpoint
from network import Net
from visualization import plot_loss, plot_3d_soup
def l1(tup): def l1(tup):
@@ -111,16 +115,16 @@ class SoupSpawnExperiment:
self.populate_environment() self.populate_environment()
self.spawn_and_continue() self.spawn_and_continue()
self.weights_evolution_3d_experiment(self.parents, "only_parents") # self.weights_evolution_3d_experiment(self.parents, "only_parents")
self.weights_evolution_3d_experiment(self.clones, "only_clones") self.weights_evolution_3d_experiment(self.clones, "only_clones")
self.weights_evolution_3d_experiment(self.parents_with_clones, "parents_with_clones") self.weights_evolution_3d_experiment(self.parents_with_clones, "parents_with_clones")
self.weights_evolution_3d_experiment(self.parents_clones_id_functions, "id_f_with_parents") # self.weights_evolution_3d_experiment(self.parents_clones_id_functions, "id_f_with_parents")
# self.visualize_loss() # self.visualize_loss()
self.distance_matrix = distance_matrix(self.parents_clones_id_functions, print_it=False) self.distance_matrix = distance_matrix(self.parents_clones_id_functions, print_it=False)
self.parent_clone_distances = distance_from_parent(self.parents_clones_id_functions, print_it=False) self.parent_clone_distances = distance_from_parent(self.parents_clones_id_functions, print_it=False)
self.save() # self.save()
def populate_environment(self): def populate_environment(self):
loop_population_size = tqdm(range(self.population_size)) loop_population_size = tqdm(range(self.population_size))
@@ -152,7 +156,7 @@ class SoupSpawnExperiment:
def evolve(self, population): def evolve(self, population):
print(f"Clone soup has a population of {len(population)} networks") print(f"Clone soup has a population of {len(population)} networks")
loop_epochs = tqdm(range(self.epochs-1)) loop_epochs = tqdm(range(self.epochs - 1))
for i in loop_epochs: for i in loop_epochs:
loop_epochs.set_description("\nEvolving clone soup %s" % i) loop_epochs.set_description("\nEvolving clone soup %s" % i)
@@ -175,7 +179,7 @@ class SoupSpawnExperiment:
number_clones = number_clones or self.nr_clones number_clones = number_clones or self.nr_clones
df = pd.DataFrame( df = pd.DataFrame(
columns=['parent', 'MAE_pre', 'MAE_post', 'MSE_pre', 'MSE_post', 'MIM_pre', 'MIM_post', 'noise', columns=['name', 'parent', 'MAE_pre', 'MAE_post', 'MSE_pre', 'MSE_post', 'MIM_pre', 'MIM_post', 'noise',
'status_post']) 'status_post'])
# MAE_pre, MSE_pre, MIM_pre = 0, 0, 0 # MAE_pre, MSE_pre, MIM_pre = 0, 0, 0
@@ -243,7 +247,12 @@ class SoupSpawnExperiment:
f"\nMIM({i},{j}): {MIM_post}\n") f"\nMIM({i},{j}): {MIM_post}\n")
self.parents_clones_id_functions.append(clone) self.parents_clones_id_functions.append(clone)
df.loc[df.name == clone.name, ["MAE_post", "MSE_post", "MIM_post", "status_post"]] = [MAE_post, MSE_post, MIM_post, clone.is_fixpoint] # df.loc[df.name == clone.name, ["MAE_post", "MSE_post", "MIM_post"]] = [MAE_pre, MSE_pre, MIM_pre]
df.loc[df.name == clone.name, ["MAE_post", "MSE_post", "MIM_post", "status_post"]] = [MAE_post,
MSE_post,
MIM_post,
clone.is_fixpoint]
# Finally take parent net {i} and finish it's training for comparison to clone development. # Finally take parent net {i} and finish it's training for comparison to clone development.
for _ in range(self.epochs - 1): for _ in range(self.epochs - 1):
@@ -268,22 +277,21 @@ class SoupSpawnExperiment:
plot_loss(self.loss_history, self.directory) plot_loss(self.loss_history, self.directory)
if __name__ == "__main__": if __name__ == "__main__":
NET_INPUT_SIZE = 4 NET_INPUT_SIZE = 4
NET_OUT_SIZE = 1 NET_OUT_SIZE = 1
# Define number of runs & name: # Define number of runs & name:
ST_runs = 1 ST_runs = 3
ST_runs_name = "test-27" ST_runs_name = "test-27"
soup_ST_steps = 2500 soup_ST_steps = 1500
soup_epochs = 2 soup_epochs = 2
soup_log_step_size = 10 soup_log_step_size = 10
# Define number of networks & their architecture # Define number of networks & their architecture
nr_clones = 3 nr_clones = 5
soup_population_size = 2 soup_population_size = 3
soup_net_hidden_size = 2 soup_net_hidden_size = 2
soup_net_learning_rate = 0.04 soup_net_learning_rate = 0.04
soup_attack_chance = 10 soup_attack_chance = 10
@@ -291,7 +299,7 @@ if __name__ == "__main__":
print(f"Running the Soup-Spawn experiment:") print(f"Running the Soup-Spawn experiment:")
exp_list = [] exp_list = []
for noise_factor in range(2, 3): for noise_factor in range(2, 5):
exp = SoupSpawnExperiment( exp = SoupSpawnExperiment(
population_size=soup_population_size, population_size=soup_population_size,
log_step_size=soup_log_step_size, log_step_size=soup_log_step_size,
@@ -312,15 +320,28 @@ if __name__ == "__main__":
pickle.dump(exp_list, open(f"{directory}/experiment_pickle_{soup_name_hash}.p", "wb")) pickle.dump(exp_list, open(f"{directory}/experiment_pickle_{soup_name_hash}.p", "wb"))
print(f"\nSaved experiment to {directory}.") print(f"\nSaved experiment to {directory}.")
# Boxplot with counts of nr_fixpoints, nr_other, nr_etc. on y-axis # Concat all dataframes, and add columns depending on where clone weights end up after training (rel. to parent)
df = pd.concat([exp.df for exp in exp_list]) df = pd.concat([exp.df for exp in exp_list])
sns.countplot(data=df, x="noise", hue="status_post") df = df.dropna().reset_index()
plt.savefig(f"output/soup_spawn_basin/{soup_name_hash}/fixpoint_status_countplot.png") df["relative_distance"] = [ (df.loc[i]["MAE_pre"] - df.loc[i]["MAE_post"]) for i in range(len(df))]
df["class"] = ["approaching" if df.loc[i]["relative_distance"] > 0 else "distancing" if df.loc[i]["relative_distance"] < 0 else "stationary" for i in range(len(df))]
# Countplot of all fixpoint clone after training per class. Uncomment and manually adjust xticklabels if x-ax size gets too small.
ax = sns.catplot(kind="count", data=df, x="noise", hue="class", height=5.27, aspect=12.7 / 5.27)
ax.set_axis_labels("Noise Levels", "Clone Fixpoints After Training Count ", fontsize=15)
# ax.set_xticklabels(labels=('10e-10', '10e-9', '10e-8', '10e-7', '10e-6', '10e-5', '10e-4', '10e-3', '10e-2', '10e-1'), fontsize=15)
plt.savefig(f"{directory}/clone_status_after_countplot_{soup_name_hash}.png")
plt.clf()
# Catplot (either kind="point" or "box") that shows before-after training distances to parent # Catplot (either kind="point" or "box") that shows before-after training distances to parent
mlt = df.melt(id_vars=["name", "noise"], value_vars=["MAE_pre", "MAE_post"], var_name="State", value_name="Distance") mlt = df.melt(id_vars=["name", "noise", "class"], value_vars=["MAE_pre", "MAE_post"], var_name="State",
ax = sns.catplot(data=mlt, x="State", y="Distance", col="noise", hue="name", kind="point", col_wrap=min(5, len(exp_list)), sharey=False, legend=False) value_name="Distance")
P = ["blue" if mlt.loc[i]["class"] == "approaching" else "orange" if mlt.loc[i]["class"] == "distancing" else "green" for i in range(len(mlt))]
# P = sns.color_palette(P, as_cmap=False)
ax = sns.catplot(data=mlt, x="State", y="Distance", col="noise", hue="name", kind="point", palette=P,
col_wrap=min(5, len(exp_list)), sharey=False, legend=False)
ax.map(sns.boxplot, "State", "Distance", "noise", linewidth=0.8, order=["MAE_pre", "MAE_post"], whis=[0, 100]) ax.map(sns.boxplot, "State", "Distance", "noise", linewidth=0.8, order=["MAE_pre", "MAE_post"], whis=[0, 100])
ax.set_axis_labels("", "Manhattan Distance To Parent Weights", fontsize=15) ax.set_axis_labels("", "Manhattan Distance To Parent Weights", fontsize=15)
ax.set_xticklabels(labels=('after noise application', 'after training'), fontsize=15) ax.set_xticklabels(labels=('after noise application', 'after training'), fontsize=15)
plt.savefig(f"output/soup_spawn_basin/{soup_name_hash}/clone_distance_catplot.png") plt.savefig(f"{directory}/before_after_distance_catplot_{soup_name_hash}.png")
plt.clf()