Data visualization¶
Individual frames¶
- Matplotlib 2D/3D : point cloud
Sequences¶
- Matplotlib 2D/3D : point cloud, with colored trace over time - Matplotlib 2D : all channels (xyz) vs time: curves - Matplotlib 2D : all channels (xyz) vs time: pixel-color coded
Model visualization¶
Parallel coordinates visualizations can be used to summarize model architecture configuration and performances:
import numpy import matplotlib.pyplot as plt from itertools import product def parallel_coordinates(columns_names, values, custom_ticks=None, space_ticks_evenly=False, cmap_name='plasma', figsize=(16.0, 10.0), save_as=None, return_fig=False, show=True): """Plot 2d array `values` using K parallel coordinates. Arguments: columns_names -- list of K strings with the coordinate names values -- numpy.ndarray of shape (N, K) where N is the nb of experiments custom_ticks -- list of K elements, each element is itself a list of strings with the names of the ticks for its own axis/dim. cmap_name -- matplotlib colormap name """ N, K = values.shape if space_ticks_evenly is True: raise Exception('TODO: this option is still to be implemented, please use space_ticks_evenly=False for now. :)') if custom_ticks is None: custom_ticks = [None for i in range(K)] # normalise data vmin, vmax = values.min(0), values.max(0) normed_values = (values - vmin) / (vmax - vmin) normed_custom_ticks_values = [None for i in range(K)] for i in range(K): if custom_ticks[i] is not None: axvmin, axvmax = numpy.array(custom_ticks[i]).min(), numpy.array(custom_ticks[i]).max() if space_ticks_evenly: normed_custom_ticks_values[i] = np.linspace(0, 1, num=len(custom_ticks[i])) else: normed_custom_ticks_values[i] = (custom_ticks[i] - axvmin) / (axvmax - axvmin) # font size plt.rcParams.update({'font.size': 16}) # create independent, attached axes fig, axes = plt.subplots(1, K-1, figsize=figsize) fig.subplots_adjust(wspace=0) # obtain colors cmap = plt.get_cmap(cmap_name) for i in range(K - 1): ax = axes[i] lines = ax.plot(normed_values.T) # set line colors for il, l in enumerate(lines): l.set_color(cmap(normed_values[il, -1])) # configure axes ax.spines['top'].set_visible(False) ax.spines['bottom'].set_position(('outward', 5)) ax.spines['bottom'].set_visible(False) ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks_position('none') # set limit to show only single line segment ax.set_xlim((i, i+1)) ax.set_xticks([i]) ax.set_xticklabels([columns_names[i]]) # set the scale if custom_ticks[i] is None: ax.set_yticks([0, 1]) ax.set_yticklabels([ numpy.round(vmin[i], 2), numpy.round(vmax[i], 2), ]) else: ax.set_yticks(normed_custom_ticks_values[i]) ax.set_yticklabels(custom_ticks[i]) if space_ticks_evenly: ax.set_yticks(np.linspace(0, 1, num=len(custom_ticks[i]))) # we have to deal with rightmost axis separately axes[-1].spines['top'].set_visible(False) axes[-1].spines['bottom'].set_position(('outward', 5)) axes[-1].spines['bottom'].set_visible(False) axes[-1].set_xticks([K-2, K-1]) axes[-1].set_xticklabels(columns_names[-2:]) ax = axes[-1].twinx() ax.tick_params(axis='y', direction='out') ax.xaxis.set_ticks_position('none') ax.set_yticks([0, 1]) ax.set_yticklabels([ numpy.round(vmin[-1], 2), numpy.round(vmax[-1], 2), ]) # added ax.spines['top'].set_visible(False) ax.spines['bottom'].set_position(('outward', 5)) ax.spines['bottom'].set_visible(False) # set leftmost axis as the default for labelling plt.sca(axes[0]) if save_as is not None: fig.savefig(save_as) if show is True: plt.show() if return_fig is True: return fig if __name__ == "__main__": # ------------------------------------- # Generate some results # ------------------------------------- n_layers = 2 experiments_configs = list(product([32, 64, 128, 256], repeat=n_layers)) experiments_configs = numpy.array(experiments_configs) # add a last column for the result experiments_configs = numpy.c_[experiments_configs, numpy.zeros(experiments_configs.shape[0])] # get the result of the experiment. here we add random results: experiments_configs[:, -1] = numpy.random.uniform(low=0., high=1., size=experiments_configs.shape[0]) # ------------------------------------- # Show the image # ------------------------------------- parallel_coordinates( columns_names = ['Neurons in layer {}'.format(i+1) for i in range(n_layers)] + ['Accuracy'], values = experiments_configs, custom_ticks = [[32, 64, 128, 256] for _ in range(experiments_configs.shape[1])], space_ticks_evenly=False, cmap_name='winter', return_fig=False, show=True, save_as='./image.png' )