Exemplo n.º 1
0
    def init(self, boot_spec):
        # TODO: do the 1D version
        shape = boot_spec.get_observations().shape()
        if len(shape) > 2:
            msg = 'BGDSagent only work with 2D or 1D signals.'
            raise UnsupportedSpec(msg)

        min_width = np.min(shape)
        if min_width <= 5:
            msg = ('BGDSagent thinks this shape is too'
                   'small to compute gradients: %s' % str(shape))
            raise UnsupportedSpec(msg)

        self.is2D = len(boot_spec.get_observations().shape()) == 2
        self.is1D = len(boot_spec.get_observations().shape()) == 1

        ExpSwitcher.init(self, boot_spec)
        self.count = 0
        self.y_deriv = DerivativeBox()
        self.bgds_estimator = BGDSEstimator()

        self.model = None
        self.y_disag = Expectation()
        self.y_disag_s = Expectation()
        self.u_stats = []
        self.last_y0 = None
        self.last_y = None

        self.rd = RemoveDoubles(0.5)
Exemplo n.º 2
0
 def __init__(self, importance, explorer):
     """ importance: spec to instantiate """
     self.importance = instantiate_spec(importance)
     self.explorer = explorer  
     self.y_deriv = DerivativeBox()
     self.rd = RemoveDoubles(0.5)  # XXX
     self.count = 0
Exemplo n.º 3
0
    def init(self, boot_spec):
        ExpSwitcher.init(self, boot_spec)
        if len(boot_spec.get_observations().shape()) != 1:
            raise UnsupportedSpec('I assume 1D signals.')

        self.y_stats = MeanCovariance()
        self.y_dot_stats = MeanCovariance()
        self.y_dot_sgn_stats = MeanCovariance()
        self.y_dot_abs_stats = MeanCovariance()

        self.count = 0
        self.y_deriv = DerivativeBox()
Exemplo n.º 4
0
    def init(self, boot_spec):
        self.boot_spec = boot_spec
        
        if len(boot_spec.get_observations().shape()) != 1:
            raise UnsupportedSpec('This agent can only work with 1D signals.')

        self.count = 0
        self.rd = RemoveDoubles(self.change_fraction)
        self.y_deriv = DerivativeBox()

        self.bdse_estimator = instantiate_spec(self.estimator_spec)
        if not isinstance(self.bdse_estimator, BDSEEstimatorInterface):
            msg = ('Expected a BDSEEstimatorInterface, got %s' 
                   % describe_type(self.estimator))
            raise ValueError(msg)

    
        self.y_stats = MeanCovariance()

        self.explorer.init(boot_spec)
        self.commands_spec = boot_spec.get_commands()

        # All the rest are only statistics
        self.stats = MiscStatistics()
Exemplo n.º 5
0
class BGDSAgent(ExpSwitcher):
    '''
        Skip: only consider every $skip observations.
        
        scales: list of floats, represents the scales at which the 
                sensels are analyzed. 0=raw data, 1= convolved with sigma=1.
    '''
    @contract(scales='list[>=1](number,>=0)')
    def __init__(self, beta, skip=1, scales=[0], fixed_dt=0):
        ExpSwitcher.__init__(self, beta)
        self.skip = skip
        self.scales = scales
        self.fixed_dt = fixed_dt

    def init(self, boot_spec):
        # TODO: do the 1D version
        shape = boot_spec.get_observations().shape()
        if len(shape) > 2:
            msg = 'BGDSagent only work with 2D or 1D signals.'
            raise UnsupportedSpec(msg)

        min_width = np.min(shape)
        if min_width <= 5:
            msg = ('BGDSagent thinks this shape is too'
                   'small to compute gradients: %s' % str(shape))
            raise UnsupportedSpec(msg)

        self.is2D = len(boot_spec.get_observations().shape()) == 2
        self.is1D = len(boot_spec.get_observations().shape()) == 1

        ExpSwitcher.init(self, boot_spec)
        self.count = 0
        self.y_deriv = DerivativeBox()
        self.bgds_estimator = BGDSEstimator()

        self.model = None
        self.y_disag = Expectation()
        self.y_disag_s = Expectation()
        self.u_stats = []
        self.last_y0 = None
        self.last_y = None

        self.rd = RemoveDoubles(0.5)

    def process_observations(self, obs):
        dt = float(obs['dt'])
        u = obs['commands']
        y0 = obs['observations']
        episode_start = obs['episode_start']

        self.count += 1
        if self.count % self.skip != 0:
            return

        if self.fixed_dt:
            # dt is not reliable sometime
            # you don't want to give high weight to higher dt samples.
            dt = 1  # XXX: add in constants

        self.rd.update(y0)
        if not self.rd.ready():
            return

        if self.is2D:
            y = create_scales(y0, self.scales)
        else:
            y = y0

        if episode_start:
            self.y_deriv.reset()
            return

        self.y_deriv.update(y, dt)

        if not self.y_deriv.ready():
            return

        y_sync, y_dot_sync = self.y_deriv.get_value()

        self.bgds_estimator.update(u=u.astype('float32'),
                                   y=y_sync.astype('float32'),
                                   y_dot=y_dot_sync.astype('float32'),
                                   dt=dt)
        self.last_y0 = y0
        self.last_y = y

        # TODO: implement this separately
        if False and self.is2D and self.count > MINIMUM_FOR_PREDICTION:
            # TODO: do for 1D
            if self.count % 200 == 0 or self.model is None:
                self.info('Updating BGDS model.')
                self.model = self.bgds_estimator.get_model()

            gy = self.bgds_estimator.last_gy
            y_dot_est = self.model.estimate_y_dot(y, u, gy=gy)
            y_dot_corr = y_dot_est * y_dot_sync
            self.y_disag.update(np.maximum(-y_dot_corr, 0))
            self.y_disag_s.update(np.sign(y_dot_corr))

            u_est = self.model.estimate_u(y, y_dot_sync, gy=gy)

            data = {'u': u,
                    'u_est': u_est,
                    'timestamp': obs.time,
                    'id_episode': obs.id_episode
            }
            self.u_stats.append(data)

#          u_est = self.model.estimate_u(y, y_dot_sync, gy=self.bgds_estimator)
#          self.u_stats.append()
#            
    def publish(self, pub):
        if self.count < 10:
            self.info('Skipping publishing as count=%d' % self.count)
            return

        self.bgds_estimator.publish(pub.section('model'))

        if False and self.is2D:  # TODO: implement separately
            sec = pub.section('preprocessing')
            sec.array_as_image('last_y0', self.last_y0, filter='scale')
            sec.array_as_image('last_y', self.last_y, filter='scale')
            example = np.zeros(self.last_y.shape)
            example.flat[150] = 1
            example_smooth = create_scales(example, self.scales)
            sec.array_as_image('example_smooth', example_smooth)

            if self.count > MINIMUM_FOR_PREDICTION:
                sec = pub.section('reliability')
                sec.array_as_image('y_disag',
                                   self.y_disag.get_value(), filter='posneg')
                sec.array_as_image('y_disag_s',
                                   self.y_disag_s.get_value(), filter='posneg')

        if False:  # XXX
            self.publish_u_stats(pub.section('u_stats'))

    def publish_u_stats(self, pub):
        T = len(self.u_stats)
        print('Obtained %d obs' % T)
        K = 2  # FIXME: change this
        u_act = np.zeros((T, K))
        u_est = np.zeros((T, K))
        u_mis = np.zeros((T, K))
        u_suc = np.zeros((T, K))
        time = np.zeros(T)
        num_episode = np.zeros(T, 'int')
        id_episode2num = {}
        num2id_episode = {}
        id_episode2start = {}
        # cmd2faults = {}
        for t, stats in enumerate(self.u_stats):
            u_act[t, :] = stats['u']
            u_est[t, :] = stats['u_est']
            time[t] = stats['timestamp']
            id_ep = stats['id_episode']
            if not id_ep in id_episode2num:
                id_episode2num[id_ep] = len(id_episode2num)
                id_episode2start[id_ep] = time[t]
                num2id_episode[id_episode2num[id_ep]] = id_ep
            num_episode[t] = id_episode2num[id_ep]

        s = ""
        for k, v in id_episode2num.items():
            s += '%s: %s\n' % (k, v)
        pub.text('episodes', s)
        with pub.plot('num_episode') as pylab:
            pylab.plot(num_episode, '-')
            pylab.xlabel('index')
            pylab.ylabel('num\_episode')

        for id_episode, num in id_episode2num.items():
            print id_episode
            S = pub.section('Episode:%s' % id_episode)
            # times for this episode
            et = num_episode == num
            # normalize from 0
            e_timestamps = time[et]
            log_start = e_timestamps[0]
            e_timestamps -= log_start
            cmd2color = {0: 'g', 1: 'b'}

            episode_bounds = (18, 60)
            markersize = 2
            with S.plot('mis', figsize=(8, 2), mime=MIME_PDF) as pylab:
                for k in range(K):
#                    scale = 7
#                    u_mis_smooth = scipy.signal.convolve(u_mis[et, k], 
#                     np.ones(scale) / scale,
#                                                         mode='same')
                    pylab.plot(e_timestamps, u_mis[et, k],  # u_mis_smooth,
                               '%s-' % cmd2color[k], label='u[%d]' % k,
                               markersize=markersize)
                x_axis_set(pylab, episode_bounds[0], episode_bounds[1])

            with S.plot('success', figsize=(8, 2), mime=MIME_PDF) as pylab:
                pylab.plot(e_timestamps, e_timestamps * 0, 'k--')
                pylab.plot(e_timestamps, np.ones(len(e_timestamps)), 'k--')
                for k in range(K):
                    pylab.plot(e_timestamps, u_suc[et, k],
                               '%s-' % cmd2color[k], label='cmd #%d' % k)
                y_axis_set(pylab, -0.05, 1.05)
                x_axis_set(pylab, episode_bounds[0], episode_bounds[1])
                pylab.legend(loc='lower right')

            for k in range(K):
                with S.plot('commands_%d' % k, figsize=(8, 2),
                            mime=MIME_PDF) as pylab:
                    pylab.plot(e_timestamps, u_act[et, k], 'y.',
                               label='actual', markersize=3)
                    plot_with_colors(pylab, e_timestamps,
                                     u_est[et, k], u_act[et, k],
                                     markersize=markersize)
                    y_axis_set(pylab, -2, 2)
                    x_axis_set(pylab, episode_bounds[0], episode_bounds[1])

    def get_predictor(self):
        model = self.bgds_estimator.get_model()
        return BGDSPredictor(model)
Exemplo n.º 6
0
class DerivAgentRobust(AgentInterface):
    """ 
        Generic agent that looks at the derivative,
        and knows how to compute the importance 
    """
    
    def __init__(self, importance, explorer):
        """ importance: spec to instantiate """
        self.importance = instantiate_spec(importance)
        self.explorer = explorer  
        self.y_deriv = DerivativeBox()
        self.rd = RemoveDoubles(0.5)  # XXX
        self.count = 0
        
    def init(self, boot_spec):
        warnings.warn('Must do this properly')
        # self.explorer.init(boot_spec)
        self.boot_spec = boot_spec
        self.commands_spec = boot_spec.get_commands()

    def process_observations(self, obs):
        dt = float(obs['dt'])
        u = obs['commands']
        y0 = obs['observations']
        episode_start = obs['episode_start']
        self.count += 1 
        self.rd.update(y0)
        if not self.rd.ready():
            return

        if episode_start:
            self.y_deriv.reset()
            return

        self.y_deriv.update(y0, dt)

        if not self.y_deriv.ready():
            return

        y_sync, y_dot_sync = self.y_deriv.get_value()

        y_dot = y_dot_sync.astype('float32')
        y = y_sync.astype('float32')
        u = u.astype('float32')
        
        w = self.importance.get_importance(y, y_dot).astype('float32')
        
        self.process_observations_robust(y=y, y_dot=y_dot, u=u, w=w)

        self.last_y = y_sync

    @abstractmethod    
    def process_observations_robust(self, y, y_dot, u, w):
        pass
    
    def publish(self, pub):
        self.importance.publish(pub.section('importance'))


    def choose_commands(self):
        return self.explorer.choose_commands()
Exemplo n.º 7
0
class Embed(ExpSwitcher):

    def __init__(self, statistic='y_corr', scale_score=False, **kwargs):  # @UnusedVariable
        ExpSwitcher.__init__(self, **kwargs)
        self.statistic = statistic
        self.scale_score = False

    def init(self, boot_spec):
        ExpSwitcher.init(self, boot_spec)
        if len(boot_spec.get_observations().shape()) != 1:
            raise UnsupportedSpec('I assume 1D signals.')

        self.y_stats = MeanCovariance()
        self.y_dot_stats = MeanCovariance()
        self.y_dot_sgn_stats = MeanCovariance()
        self.y_dot_abs_stats = MeanCovariance()

        self.count = 0
        self.y_deriv = DerivativeBox()

    def get_similarity(self, which):
        if which == 'y_corr':
            return self.y_stats.get_correlation()
        if which == 'y_dot_corr':
            return self.y_dot_stats.get_correlation()
        if which == 'y_dot_sgn_corr':
            return self.y_dot_sgn_stats.get_correlation()
        if which == 'y_dot_abs_corr':
            return self.y_dot_abs_stats.get_correlation()

        raise ValueError()
        # check_contained(statistic, self.statistics, 'statistic')

    def process_observations(self, obs):
        y = obs['observations']
        dt = obs['dt'].item()

        self.y_deriv.update(y, dt)
        if self.y_deriv.ready():
            y, y_dot = self.y_deriv.get_value()
            self.y_stats.update(y, dt)
            self.y_dot_stats.update(y_dot, dt)
            self.y_dot_sgn_stats.update(np.sign(y_dot), dt)
            self.y_dot_abs_stats.update(np.abs(y_dot), dt)
            self.count += 1

    def get_S(self, dimensions=2, pub=None):
        similarity = self.get_similarity(self.statistic)
        if pub is not None:
            pub.array_as_image('similarity', similarity,
                               caption='Similarity statistic')
            plot_spectrum(pub, 'similarity', similarity)

        if self.scale_score:
            R = scale_score(similarity).astype('float32')
            R = R / R.max()
            if pub is not None:
                pub.array_as_image('scale_score', R)

        else:
            R = similarity

        D = 1 - R
        D = D * np.pi / D.max()
        np.fill_diagonal(D, 0)

        if pub is not None:
            #            pub.array_as_image('D', D)
            P = D * D
            B = double_center(P)
            #            plot_spectrum(pub, 'D', D)
            #            plot_spectrum(pub, 'P', P)
            plot_spectrum(pub, 'B', B)

        S = mds(D, ndim=dimensions)
#        S = inner_product_embedding(similarity, 3)
#        S = S[1:3, :]
        return S

    def get_S_discrete(self, dimensions=2, pub=None):
        R = self.y_dot_abs_stats.get_correlation()
        Dis = discretize(-R, 2)
        np.fill_diagonal(Dis, 0)
        R = R * R
        C = np.maximum(R, 0)

        if pub is not None:
            pub.array_as_image('Dis', Dis)
            pub.array_as_image('R', R)
            pub.array_as_image('C', C)

        S = inner_product_embedding(Dis, dimensions)
#        for i in range(R.shape[0]):
#            R[i, i] = np.NaN
#            C[i, i] = np.NaN
        return S

    def publish(self, pub):
        if self.count < 10:
            pub.text('warning', 'Too early to publish anything.')
            return

        pub.text('info', 'Using statistics: %s' % self.statistic)

        if False:  # TODO: make option
            S = self.get_S_discrete(2, pub=pub.section('computation'))
        else:
            S = self.get_S(2, pub=pub.section('computation'))

        with pub.plot('S') as pylab:
            style_ieee_halfcol_xy(pylab)
            pylab.plot(S[0, :], S[1, :], 's')

        with pub.plot('S_joined') as pylab:
            style_ieee_halfcol_xy(pylab)
            pylab.plot(S[0, :], S[1, :], '-')

        self.y_stats.publish(pub.section('y_stats'))
        self.y_dot_stats.publish(pub.section('y_dot_stats'))
        self.y_dot_sgn_stats.publish(pub.section('y_dot_sgn_stats'))
        self.y_dot_abs_stats.publish(pub.section('y_dot_abs_stats'))
Exemplo n.º 8
0
class BDSEAgent(AgentInterface):
    '''
        An agent that uses a BDS model.
    '''
    
    @contract(servo='code_spec', estimator='code_spec')
    def __init__(self, explorer, servo, estimator, skip=1,
                 change_fraction=0.0):
        """
            :param explorer: ID of the explorer agent.
            :param servo: extra parameters for servo; if string, the ID of an agent.
                
            :param skip: only used one every skip observations.
        """
        boot_config = get_boot_config()
        _, self.explorer = boot_config.agents.instance_smarter(explorer)  # @UndefinedVariable
        
        self.skip = skip
        self.change_fraction = change_fraction
        self.servo = servo
        self.estimator_spec = estimator

    def init(self, boot_spec):
        self.boot_spec = boot_spec
        
        if len(boot_spec.get_observations().shape()) != 1:
            raise UnsupportedSpec('This agent can only work with 1D signals.')

        self.count = 0
        self.rd = RemoveDoubles(self.change_fraction)
        self.y_deriv = DerivativeBox()

        self.bdse_estimator = instantiate_spec(self.estimator_spec)
        if not isinstance(self.bdse_estimator, BDSEEstimatorInterface):
            msg = ('Expected a BDSEEstimatorInterface, got %s' 
                   % describe_type(self.estimator))
            raise ValueError(msg)

    
        self.y_stats = MeanCovariance()

        self.explorer.init(boot_spec)
        self.commands_spec = boot_spec.get_commands()

        # All the rest are only statistics
        self.stats = MiscStatistics()
    
    def choose_commands(self):
        return self.explorer.choose_commands()

    def process_observations(self, obs):
        self.explorer.process_observations(obs)

        self.count += 1
        if self.count % self.skip != 0:
            return

        dt = float(obs['dt'])
        y = obs['observations']
        u = obs['commands']

        # TODO: abstract away
        self.rd.update(y)
        if not self.rd.ready():
            return

        # XXX: this is not `dt` anymore FiXME:
        self.y_stats.update(y, dt)

        if obs['episode_start']:
            # self.info('episode_changed: %s' % obs['id_episode'])
            self.y_deriv.reset()
            return

        self.y_deriv.update(y, dt)

        if not self.y_deriv.ready():
            return

        y_sync, y_dot_sync = self.y_deriv.get_value()

        self.bdse_estimator.update(u=u.astype('float32'),
                                   y=y_sync.astype('float32'),
                                   y_dot=y_dot_sync.astype('float32'),
                                   w=dt)

        # Just other statistics
        self.stats.update(y_sync, y_dot_sync, u, dt)

    def publish(self, pub):
        if self.count < 10:
            self.info('Skipping publishing as count=%d' % self.count)
            return
        
        with pub.subsection('estimator') as sub:
            self.bdse_estimator.publish(sub)
            
        with pub.subsection('stats') as sub:
            self.stats.publish(sub)

    def get_predictor(self):
        model = self.bdse_estimator.get_model()
        return BDSEPredictor(model)

    def get_servo(self):
        servo_agent = instantiate_spec(self.servo)
        servo_agent.init(self.boot_spec)
        assert isinstance(servo_agent, BDSEServoInterface)
        model = self.bdse_estimator.get_model()
        servo_agent.set_model(model)
        return servo_agent

    def merge(self, agent2):
        assert isinstance(agent2, BDSEAgent)
        self.bdse_estimator.merge(agent2.bdse_estimator)