Source code for explauto.experiment.log

from collections import defaultdict
from numpy import array, mean, std
from ..utils.density_image import density_image


[docs]class ExperimentLog(object): def __init__(self, conf, expl_dims, inf_dims): self._logs = defaultdict(list) self.counts = defaultdict(int) self.eval_errors = [] self.conf = conf self.expl_dims = expl_dims self.inf_dims = inf_dims @property
[docs] def logs(self): return {key: array(val) for key, val in self._logs.iteritems()}
[docs] def add(self, topic, message): self._logs[topic].append(message) self.counts[topic] += 1
[docs] def pack(self, topic_dims, t): """ Packs selected logs into a numpy array :param list topic_dims: list of (topic, dims) tuples, where topic is a string and dims a list dimensions to be packed for that topic :param int t: time indexes to be packed """ data = [] for topic, dims in topic_dims: for d in dims: data.append(self.logs[topic][t, d]) return array(data).T
[docs] def axes_limits(self, topic_dims): bounds = [] for topic, dims in topic_dims: if topic == 'motor': bounds.extend(list(self.conf.m_bounds[:, dims].T.flatten())) elif topic in ['testcases', 'sensori']: bounds.extend(list(self.conf.s_bounds[:, dims].T.flatten())) elif topic == 'choice': bounds.extend(list(self.conf.bounds[:, [self.expl_dims[d] for d in dims]].T.flatten())) elif topic == 'inference': bounds.extend(list(self.conf.bounds[:, [self.inf_dims[d] for d in dims]].T.flatten())) else: raise ValueError("Only valid for 'motor', 'sensori', 'choice' and 'inference' topics") return bounds
[docs] def data_t(self, topic_dims, t): t_bound = float('inf') if t is None: for topic, _ in topic_dims: t_bound = min(t_bound, self.counts[topic]) t = range(t_bound) data = self.pack(topic_dims, t) return data
[docs] def scatter_plot(self, ax, topic_dims, t=None, ms_limits=True, **kwargs_plot): """ 2D or 3D scatter plot. :param axes ax: matplotlib axes (use Axes3D if 3D data) :param tuple topic_dims: list of (topic, dims) tuples, where topic is a string and dims is a list of dimensions to be plotted for that topic. :param int t: time indexes to be plotted :param dict kwargs_plot: argument to be passed to matplotlib's plot function, e.g. the style of the plotted points 'or' :param bool ms_limits: if set to True, automatically set axes boundaries to the sensorimotor boundaries (default: True) """ plot_specs = {'marker': 'o', 'linestyle': 'None'} plot_specs.update(kwargs_plot) # t_bound = float('inf') # if t is None: # for topic, _ in topic_dims: # t_bound = min(t_bound, self.counts[topic]) # t = range(t_bound) # data = self.pack(topic_dims, t) data = self.data_t(topic_dims, t) ax.plot(*(data.T), **plot_specs) if ms_limits: ax.axis(self.axes_limits(topic_dims))
[docs] def plot_learning_curve(self, ax, squared_errors=False): if not hasattr(self, 'eval_at'): raise UserWarning('No evaluation available, ' 'you need to specify the evaluate_at argument' ' when constructing the experiment') errors = array(self.eval_errors) if squared_errors: errors = errors ** 2 avg_err = mean(errors, axis=1) std_err = std(errors, axis=1) ax.errorbar(self.eval_at, avg_err, yerr=std_err) axis = ax.axis() ax.axis([self.eval_at[0] * 0.9, self.eval_at[-1] * 1.1, axis[2], axis[3]]) ax.set_title('Test on ' + str(errors.shape[1]) + ' sensory goals') ax.set_xlabel('Number of sensorimotor experiments') ax.set_ylabel('Mean ' + ('squared' if squared_errors else '') + 'error')
[docs] def density_plot(self, ax, topic_dims, t=None, res_x=40, res_y=40, width_x=4, width_y=4): data = self.data_t(topic_dims, t) if data.shape[1] != 2: raise ValueError('Density plot only possible on 2D data') bounds = self.axes_limits(topic_dims) kde = density_image(data[:, 0], data[:, 1], res_x, res_y, width_x, width_y, bounds, False) # print kde.min(), kde.max() #FIXME vmin, vmax ax.imshow(kde.T[::-1, :], extent=bounds, vmin=0., vmax=kde.max())