journal linspace basins

This commit is contained in:
steffen-illium
2021-06-14 11:55:11 +02:00
parent e156540e2c
commit 0ba109c083
3 changed files with 154 additions and 14 deletions
+142
View File
@@ -0,0 +1,142 @@
import copy
import itertools
from pathlib import Path
import random
import pandas as pd
import numpy as np
from functionalities_test import is_identity_function, test_status
from journal_basins import SpawnExperiment, prng, mean_invariate_manhattan_distance
from network import Net
from sklearn.metrics import mean_absolute_error as MAE
from sklearn.metrics import mean_squared_error as MSE
import seaborn as sns
from matplotlib import pyplot as plt
class SpawnLinspaceExperiment(SpawnExperiment):
def spawn_and_continue(self, number_clones: int = None):
number_clones = number_clones or self.nr_clones
df = pd.DataFrame(
columns=['parent', 'MAE_pre', 'MAE_post', 'MSE_pre', 'MSE_post', 'MIM_pre', 'MIM_post', 'noise',
'status_post'])
# For every initial net {i} after populating (that is fixpoint after first epoch);
pairwise_net_list = itertools.permutations(self.nets, 2)
for net1, net2 in pairwise_net_list:
# We set parent start_time to just before this epoch ended, so plotting is zoomed in. Comment out to
# to see full trajectory (but the clones will be very hard to see).
# Make one target to compare distances to clones later when they have trained.
net1.start_time = self.ST_steps - 150
net1_input_data = net1.input_weight_matrix()
net1_target_data = net1.create_target_weights(net1_input_data)
net2.start_time = self.ST_steps - 150
net2_input_data = net2.input_weight_matrix()
net2_target_data = net2.create_target_weights(net2_input_data)
if is_identity_function(net1) and is_identity_function(net2):
# Clone the fixpoint x times and add (+-)self.noise to weight-sets randomly;
# To plot clones starting after first epoch (z=ST_steps), set that as start_time!
# To make sure PCA will plot the same trajectory up until this point, we clone the
# parent-net's weight history as well.
in_between_weights = np.linspace(net2_target_data, net2_target_data, number_clones)
for in_between_weight in in_between_weights:
clone = Net(net1.input_size, net1.hidden_size, net1.out_size, start_time=self.ST_steps)
clone.apply_weights(in_between_weight)
clone.s_train_weights_history = copy.deepcopy(net1.s_train_weights_history)
clone.number_trained = copy.deepcopy(net1.number_trained)
# Pre Training distances (after noise application of course)
clone_pre_weights = clone.create_target_weights(clone.input_weight_matrix())
MAE_pre = MAE(net1_target_data, clone_pre_weights)
MSE_pre = MSE(net1_target_data, clone_pre_weights)
MIM_pre = mean_invariate_manhattan_distance(net1_target_data, clone_pre_weights)
# Then finish training each clone {j} (for remaining epoch-1 * ST_steps) ..
for _ in range(self.epochs - 1):
for _ in range(self.ST_steps):
clone.self_train(1, self.log_step_size, self.net_learning_rate)
# Post Training distances for comparison
clone_post_weights = clone.create_target_weights(clone.input_weight_matrix())
MAE_post = MAE(net1_target_data, clone_post_weights)
MSE_post = MSE(net1_target_data, clone_post_weights)
MIM_post = mean_invariate_manhattan_distance(net1_target_data, clone_post_weights)
# .. log to data-frame and add to nets for 3d plotting if they are fixpoints themselves.
test_status(clone)
if is_identity_function(clone):
#print(f"Clone {j} (of net_{i}) is fixpoint."
# f"\nMSE({i},{j}): {MSE_post}"
# f"\nMAE({i},{j}): {MAE_post}"
# f"\nMIM({i},{j}): {MIM_post}\n")
self.nets.append(clone)
df.loc[clone.name] = [net1.name, MAE_pre, MAE_post, MSE_pre, MSE_post, MIM_pre, MIM_post, self.noise,
clone.is_fixpoint]
# 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.ST_steps):
net1.self_train(1, self.log_step_size, self.net_learning_rate)
net_weights_after = net1.create_target_weights(net1.input_weight_matrix())
print(f"Parent net's distance to original position."
f"\nMSE(OG,new): {MAE(net1_target_data, net_weights_after)}"
f"\nMAE(OG,new): {MSE(net1_target_data, net_weights_after)}"
f"\nMIM(OG,new): {mean_invariate_manhattan_distance(net1_target_data, net_weights_after)}\n")
self.df = df
if __name__ == '__main__':
NET_INPUT_SIZE = 4
NET_OUT_SIZE = 1
# Define number of runs & name:
ST_runs = 1
ST_runs_name = "test-27"
ST_steps = 2000
ST_epochs = 2
ST_log_step_size = 10
# Define number of networks & their architecture
nr_clones = 5
ST_population_size = 2
ST_net_hidden_size = 2
ST_net_learning_rate = 0.04
ST_name_hash = random.getrandbits(32)
print(f"Running the Spawn experiment:")
exp_list = []
for noise_factor in range(2, 5):
exp = SpawnExperiment(
population_size=ST_population_size,
log_step_size=ST_log_step_size,
net_input_size=NET_INPUT_SIZE,
net_hidden_size=ST_net_hidden_size,
net_out_size=NET_OUT_SIZE,
net_learning_rate=ST_net_learning_rate,
epochs=ST_epochs,
st_steps=ST_steps,
nr_clones=nr_clones,
noise=pow(10, -noise_factor),
directory=Path('output') / 'spawn_basin' / f'{ST_name_hash}' / f'10e-{noise_factor}'
)
exp_list.append(exp)
# Boxplot with counts of nr_fixpoints, nr_other, nr_etc. on y-axis
df = pd.concat([exp.df for exp in exp_list])
sns.countplot(data=df, x="noise", hue="status_post")
plt.savefig(f"output/spawn_basin/{ST_name_hash}/fixpoint_status_countplot.png")
# Catplot (either kind="point" or "box") that shows before-after training distances to parent
mlt = df[["MIM_pre", "MIM_post", "noise"]].melt("noise", var_name="time", value_name='Average Distance')
sns.catplot(data=mlt, x="time", y="Average Distance", col="noise", kind="point", col_wrap=5, sharey=False)
plt.savefig(f"output/spawn_basin/{ST_name_hash}/clone_distance_catplot.png")
-4
View File
@@ -1,8 +1,6 @@
import os import os
from pathlib import Path from pathlib import Path
import pickle import pickle
from torch import mean
from tqdm import tqdm from tqdm import tqdm
import random import random
import copy import copy
@@ -17,11 +15,9 @@ import pandas as pd
import seaborn as sns import seaborn as sns
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
def prng(): def prng():
return random.random() return random.random()
def l1(tup): def l1(tup):
a, b = tup a, b = tup
return abs(a - b) return abs(a - b)
+12 -10
View File
@@ -126,7 +126,8 @@ class RobustnessComparisonExperiment:
# This checks wether to use synthetic setting with multiple seeds # This checks wether to use synthetic setting with multiple seeds
# or multi network settings with a singlee seed # or multi network settings with a singlee seed
df = pd.DataFrame(columns=['setting', 'noise_level', 'steps', 'absolute_loss', 'time_to_vergence', 'time_as_fixpoint']) df = pd.DataFrame(columns=['setting', 'Noise Level', 'steps', 'absolute_loss',
'time_to_vergence', 'time_as_fixpoint'])
with tqdm(total=max(len(self.id_functions), seeds)) as pbar: with tqdm(total=max(len(self.id_functions), seeds)) as pbar:
for i, fixpoint in enumerate(self.id_functions): # 1 / n for i, fixpoint in enumerate(self.id_functions): # 1 / n
row_headers.append(fixpoint.name) row_headers.append(fixpoint.name)
@@ -160,21 +161,22 @@ class RobustnessComparisonExperiment:
# When this raises a Type Error, we found a second order fixpoint! # When this raises a Type Error, we found a second order fixpoint!
steps += 1 steps += 1
df.loc[df.shape[0]] = [setting, noise_level, steps, absolute_loss, df.loc[df.shape[0]] = [setting, f'10e-{noise_level}', steps, absolute_loss,
time_to_vergence[setting][noise_level], time_to_vergence[setting][noise_level],
time_as_fixpoint[setting][noise_level]] time_as_fixpoint[setting][noise_level]]
pbar.update(1) pbar.update(1)
# Get the measuremts at the highest time_time_to_vergence # Get the measuremts at the highest time_time_to_vergence
df_sorted = df.sort_values('steps', ascending=False).drop_duplicates(['setting', 'noise_level']) df_sorted = df.sort_values('Steps', ascending=False).drop_duplicates(['setting', 'Noise Level'])
df_melted = df_sorted.reset_index().melt(id_vars=['setting', 'noise_level', 'steps'], df_melted = df_sorted.reset_index().melt(id_vars=['setting', 'Noise Level', 'Steps'],
value_vars=['time_to_vergence', 'time_as_fixpoint'], value_vars=['Time to vergence', 'Time as fixpoint'],
var_name="Measurement", var_name="Measurement",
value_name="Steps") value_name="Steps")
# Plotting # Plotting
sns.set(style='whitegrid') sns.set(style='whitegrid', font_scale=2)
bf = sns.boxplot(data=df_melted, y='Steps', x='noise_level', hue='Measurement', palette=PALETTE) bf = sns.boxplot(data=df_melted, y='Steps', x='Noise Level', hue='Measurement', palette=PALETTE)
bf.set_title('Robustness as self application steps per noise level') synthetic = 'synthetic' if self.is_synthetic else 'natural'
bf.set_title(f'Robustness as self application steps per noise level for {synthetic} fixpoints.')
plt.tight_layout() plt.tight_layout()
# sns.set(rc={'figure.figsize': (10, 50)}) # sns.set(rc={'figure.figsize': (10, 50)})
@@ -221,9 +223,9 @@ if __name__ == "__main__":
ST_steps = 1000 ST_steps = 1000
ST_epochs = 5 ST_epochs = 5
ST_log_step_size = 10 ST_log_step_size = 10
ST_population_size = 100 ST_population_size = 2
ST_net_hidden_size = 2 ST_net_hidden_size = 2
ST_net_learning_rate = 0.04 ST_net_learning_rate = 0.004
ST_name_hash = random.getrandbits(32) ST_name_hash = random.getrandbits(32)
ST_synthetic = True ST_synthetic = True