From bae997feab0d1db59b99f8015f6ddd948077c984 Mon Sep 17 00:00:00 2001 From: Si11ium Date: Wed, 6 Mar 2019 19:21:19 +0100 Subject: [PATCH] plotting --- code/network.py | 7 ++-- code/soup.py | 27 +++++++++------ code/visualization.py | 78 ++++++++++++++++++++++++++----------------- 3 files changed, 69 insertions(+), 43 deletions(-) diff --git a/code/network.py b/code/network.py index 5f70823..48c9b92 100644 --- a/code/network.py +++ b/code/network.py @@ -1,7 +1,6 @@ import math import copy import numpy as np -from tqdm import tqdm from keras.models import Sequential from keras.layers import SimpleRNN, Dense @@ -43,6 +42,7 @@ class NeuralNetwork(PrintingObject): for layer_id, layer in enumerate(network_weights): for cell_id, cell in enumerate(layer): for weight_id, weight in enumerate(cell): + # could be a chain comparission "lower_bound <= weight <= upper_bound" if not (lower_bound <= weight and weight <= upper_bound): return False return True @@ -538,6 +538,7 @@ class LearningNeuralNetwork(NeuralNetwork): self.depth = depth self.features = features self.compile_params = dict(loss='mse', optimizer='sgd') + self.model = Sequential() self.model.add(Dense(units=self.width, input_dim=self.features, **self.keras_params)) for _ in range(self.depth-1): self.model.add(Dense(units=self.width, **self.keras_params)) @@ -591,7 +592,7 @@ class TrainingNeuralNetworkDecorator(): def compile_model(self, **kwargs): compile_params = copy.deepcopy(self.compile_params) compile_params.update(kwargs) - return self.get_model().compile(**compile_params) + return self.net.model.compile(**compile_params) def compiled(self, **kwargs): if not self.model_compiled: @@ -617,7 +618,7 @@ if __name__ == '__main__': if False: with FixpointExperiment() as exp: for run_id in tqdm(range(100)): - # net = WeightwiseNeuralNetwork(width=2, depth=2).with_keras_params(activation='linear') + net = WeightwiseNeuralNetwork(width=2, depth=2).with_keras_params(activation='linear') # net = AggregatingNeuralNetwork(aggregates=4, width=2, depth=2)\ # net = FFTNeuralNetwork(aggregates=4, width=2, depth=2) \ # .with_params(print_all_weight_updates=False, use_bias=False) diff --git a/code/soup.py b/code/soup.py index 8f4e435..1f51e71 100644 --- a/code/soup.py +++ b/code/soup.py @@ -1,9 +1,5 @@ import random -import copy -from tqdm import tqdm - -from experiment import * from network import * @@ -21,7 +17,19 @@ class Soup: self.params = dict(attacking_rate=0.1, train_other_rate=0.1, train=0) self.params.update(kwargs) self.time = 0 - + + def __copy__(self): + copy_ = Soup(self.size, self.generator, **self.params) + copy_.__dict__ = {attr: self.__dict__[attr] for attr in self.__dict__ if + attr not in ['particles', 'historical_particles']} + return copy_ + + def without_particles(self): + self_copy = copy.copy(self) + # self_copy.particles = [particle.states for particle in self.particles] + self_copy.historical_particles = {key: val.states for key, val in self.historical_particles.items()} + return self_copy + def with_params(self, **kwargs): self.params.update(kwargs) return self @@ -94,6 +102,7 @@ class Soup: particle.print_weights() print(particle.is_fixpoint()) + class ParticleDecorator: next_uid = 0 @@ -131,7 +140,6 @@ class ParticleDecorator: return self.states - if __name__ == '__main__': if False: with SoupExperiment() as exp: @@ -155,12 +163,11 @@ if __name__ == '__main__': # net_generator = lambda: AggregatingNeuralNetwork(4, 2, 2).with_keras_params(activation='sigmoid')\ # .with_params(shuffler=AggregatingNeuralNetwork.shuffle_random) # net_generator = lambda: RecurrentNeuralNetwork(2, 2).with_keras_params(activation='linear').with_params() - soup = Soup(10, net_generator).with_params(remove_divergent=True, remove_zero=True, train=200) + soup = Soup(10, net_generator).with_params(remove_divergent=True, remove_zero=True, train=10) soup.seed() - for _ in tqdm(range(10)): + for _ in tqdm(range(100)): soup.evolve() soup.print_all() exp.log(soup.count()) - exp.save(soup=soup) # you can access soup.historical_particles[particle_uid].states[time_step]['loss'] + exp.save(soup=soup.without_particles()) # you can access soup.historical_particles[particle_uid].states[time_step]['loss'] # or soup.historical_particles[particle_uid].states[time_step]['weights'] from soup.dill - diff --git a/code/visualization.py b/code/visualization.py index a83eaae..773b67a 100644 --- a/code/visualization.py +++ b/code/visualization.py @@ -1,7 +1,8 @@ import os -from typing import Union -from experiment import Experiment, SoupExperiment +from experiment import Experiment +# noinspection PyUnresolvedReferences +from soup import Soup from argparse import ArgumentParser import numpy as np @@ -23,29 +24,42 @@ def build_args(): return arg_parser.parse_args() +def build_from_soup(soup): + particles = soup.historical_particles + particle_dict = [dict(trajectory=[timestamp['weights'] for timestamp in particle], + fitted=[timestamp['fitted'] for timestamp in particle], + loss=[timestamp['loss'] for timestamp in particle], + time=[timestamp['time'] for timestamp in particle]) for particle in particles.values()] + return particle_dict + + def plot_latent_trajectories(soup_or_experiment, filename='latent_trajectory_plot'): - assert isinstance(soup_or_experiment, Union[Experiment, SoupExperiment]) - bupu = cl.scales['9']['seq']['BuPu'] - data_dict = soup_or_experiment.data_storage + assert isinstance(soup_or_experiment, (Experiment, Soup)) + bupu = cl.scales['11']['div']['RdYlGn'] + data_dict = soup_or_experiment.data_storage if isinstance(soup_or_experiment, Experiment) \ + else build_from_soup(soup_or_experiment) scale = cl.interp(bupu, len(data_dict)+1) # Map color scale to N bins # Fit the mebedding space transformer = TSNE() - for trajectory_id in data_dict: - transformer.fit(np.asarray(data_dict[trajectory_id])) + for particle_dict in data_dict: + array = np.asarray([np.hstack([x.flatten() for x in timestamp]).flatten() + for timestamp in particle_dict['trajectory']]) + particle_dict['trajectory'] = array + transformer.fit(array) # Transform data accordingly and plot it data = [] - for trajectory_id in data_dict: - transformed = transformer._fit(np.asarray(data_dict[trajectory_id])) + for p_id, particle_dict in enumerate(data_dict): + transformed = transformer._fit(np.asarray(particle_dict['trajectory'])) line_trace = go.Scatter( x=transformed[:, 0], y=transformed[:, 1], text='Hovertext goes here'.format(), - line=dict(color=scale[trajectory_id]), + line=dict(color=scale[p_id]), # legendgroup='Position -{}'.format(pos), - # name='Position -{}'.format(pos), - showlegend=False, + name='Particle - {}'.format(p_id), + showlegend=True, # hoverinfo='text', mode='lines') line_start = go.Scatter(mode='markers', x=[transformed[0, 0]], y=[transformed[0, 1]], @@ -73,34 +87,38 @@ def plot_latent_trajectories(soup_or_experiment, filename='latent_trajectory_plo pass -def plot_latent_trajectories_3D(data_dict, filename='plot'): +def plot_latent_trajectories_3D(soup_or_experiment, filename='plot'): def norm(val, a=0, b=0.25): return (val - a) / (b - a) - bupu = cl.scales['9']['seq']['BuPu'] + data_dict = soup_or_experiment.data_storage if isinstance(soup_or_experiment, Experiment) \ + else build_from_soup(soup_or_experiment) + + bupu = cl.scales['11']['div']['RdYlGn'] scale = cl.interp(bupu, len(data_dict)+1) # Map color scale to N bins - max_len = max([len(trajectory) for trajectory in data_dict.values()]) - - # Fit the mebedding space + # Fit the embedding space transformer = TSNE() - for trajectory_id in data_dict: - transformer.fit(data_dict[trajectory_id]) + for particle_dict in data_dict: + array = np.asarray([np.hstack([x.flatten() for x in timestamp]).flatten() + for timestamp in particle_dict['trajectory']]) + particle_dict['trajectory'] = array + transformer.fit(array) # Transform data accordingly and plot it data = [] - for trajectory_id in data_dict: - transformed = transformer._fit(np.asarray(data_dict[trajectory_id])) + for p_id, particle_dict in enumerate(data_dict): + transformed = transformer._fit(particle_dict['trajectory']) trace = go.Scatter3d( x=transformed[:, 0], y=transformed[:, 1], - z=np.arange(transformed.shape[0]), - text='Hovertext goes here'.format(), - line=dict(color=scale[trajectory_id]), - # legendgroup='Position -{}'.format(pos), - # name='Position -{}'.format(pos), - showlegend=False, - # hoverinfo='text', + z=np.asarray(particle_dict['time']), + text='Particle: {}
It had {} lifes.'.format(p_id, len(particle_dict['trajectory'])), + line=dict(color=scale[p_id]), + # legendgroup='Particle - {}'.format(p_id), + name='Particle -{}'.format(p_id), + # showlegend=True, + hoverinfo='text', mode='lines') data.append(trace) @@ -109,7 +127,7 @@ def plot_latent_trajectories_3D(data_dict, filename='plot'): yaxis=dict(tickwidth=1, title='transformed Y'), zaxis=dict(tickwidth=1, title='Epoch')), title='{} - Latent Trajectory Movement'.format('Penis'), - width=800, height=800, + # width=0, height=0, margin=dict(l=0, r=0, b=0, t=0)) fig = go.Figure(data=data, layout=layout) @@ -213,4 +231,4 @@ if __name__ == '__main__': in_file = args.in_file[0] out_file = args.out_file - search_and_apply(in_file, plot_latent_trajectories) + search_and_apply(in_file, plot_latent_trajectories_3D)