def generate_and_set_class_state(cls, config: CnnCtrnnCfg, input_space: Space, output_space: Space): cnn_output_space = Cnn.get_output_shape(config=config.cnn_conf, input_space=input_space) ContinuousTimeRNN.generate_and_set_class_state(config.ctrnn_conf, cnn_output_space, output_space)
def test_get_individual_size(self, ctrnn_config): in_space = Box(-1, 1, shape=[3]) out_space = Box(-1, 1, shape=[3]) ContinuousTimeRNN.generate_and_set_class_state(config=ctrnn_config, input_space=in_space, output_space=out_space, ) ind_size = ContinuousTimeRNN.get_individual_size(config=ctrnn_config, input_space=in_space, output_space=out_space, ) assert ind_size == 22
def test_wrong_size(self, ctrnn_config, box2d, brain_param_identity): ContinuousTimeRNN.generate_and_set_class_state(config=ctrnn_config, input_space=box2d, output_space=box2d, ) ind = self.param_to_genom(brain_param_identity) ContinuousTimeRNN(input_space=box2d, output_space=box2d, individual=np.append(ind[:-1], [1]), config=ctrnn_config) with pytest.raises(AssertionError): ContinuousTimeRNN(input_space=box2d, output_space=box2d, individual=ind[:-1], config=ctrnn_config)
def test_generating_masks_dense(self, ctrnn_config, box2d): ContinuousTimeRNN.set_masks_globally( config=evolve(ctrnn_config, v_mask="dense", t_mask="dense", w_mask="dense"), input_space=box2d, output_space=box2d, )
def test_generating_masks_random(self, ctrnn_config, box2d): ContinuousTimeRNN.set_masks_globally( config=evolve(ctrnn_config, v_mask="random", t_mask="random", w_mask="random", v_mask_param=0.5, w_mask_param=0.5, t_mask_param=0.5), input_space=box2d, output_space=box2d, )
def test_clipping_legacy(self, ctrnn_config, brain_param_identity, box2d): bp = brain_param_identity ContinuousTimeRNN.generate_and_set_class_state(config=ctrnn_config, input_space=box2d, output_space=Box(-1, 1, shape=[2]), ) brain = ContinuousTimeRNN(input_space=box2d, output_space=box2d, individual=self.param_to_genom(bp), config=ctrnn_config) ob = np.array([1, 1]) res = brain.step(ob * 1000) # due to tanh the maximum output is 1.0 assert np.allclose(res, np.ones(2)) # with legacy-clipping everything is clipped to the lowest max-value, which is 10 in this genome assert np.allclose(brain.y, np.ones(2) * 10)
def test_generating_masks_log(self, ctrnn_config, box2d): ContinuousTimeRNN.set_masks_globally( config=evolve(ctrnn_config, v_mask="logarithmic", w_mask="logarithmic", t_mask="logarithmic", v_mask_param=2.5, w_mask_param=5, t_mask_param=1.1), input_space=box2d, output_space=box2d, )
def test_individual(self, ctrnn_config, brain_param_simple, box2d): ctrnn_config = evolve(ctrnn_config, set_principle_diagonal_elements_of_W_negative=False) ContinuousTimeRNN.generate_and_set_class_state(config=ctrnn_config, input_space=box2d, output_space=Box(-1, 1, shape=[2]), ) bp = brain_param_simple brain = ContinuousTimeRNN(input_space=box2d, output_space=box2d, individual=self.param_to_genom(bp), config=ctrnn_config) assert np.array_equal(bp.V, brain.V.toarray()) assert np.array_equal(bp.W, brain.W.toarray()) assert np.array_equal(bp.T, brain.T.toarray()) assert np.array_equal(bp.y0, brain.y0) assert np.array_equal(bp.y0, brain.y)
def test_get_individual_size(self, ctrnn_config): in_space = Box(-1, 1, shape=[3]) out_space = Box(-1, 1, shape=[3]) ContinuousTimeRNN.set_masks_globally( config=ctrnn_config, input_space=in_space, output_space=out_space, ) ind_size = ContinuousTimeRNN.get_individual_size( config=ctrnn_config, input_space=in_space, output_space=out_space, ) assert ind_size == 22
def test_clipping_per_neuron(self, ctrnn_config, brain_param_identity, box2d): ctrnn_config = evolve(ctrnn_config, optimize_state_boundaries="per_neuron") bp = evolve(brain_param_identity, clip_max=np.array([2, 3]), clip_min=np.array([-4, -5])) ContinuousTimeRNN.generate_and_set_class_state(config=ctrnn_config, input_space=box2d, output_space=box2d, ) brain = ContinuousTimeRNN(input_space=box2d, output_space=box2d, individual=self.param_to_genom(bp), config=ctrnn_config) ob = np.array([1, 1]) brain.step(ob * 100000) assert np.allclose(brain.y, bp.clip_max) brain.step(ob * -100000) assert np.allclose(brain.y, bp.clip_min)
def __init__(self, input_space: Space, output_space: Space, individual: np.ndarray, config: CnnCtrnnCfg): super().__init__(input_space, output_space, individual, config) assert len(individual) == self.get_individual_size( config, input_space, output_space) paramter_usage_dict = self.get_free_parameter_usage( config, input_space, output_space) cnn_output_space = paramter_usage_dict[self._usage_key_cnn_output] cnn_size = Cnn.get_individual_size(config.cnn_conf, input_space, cnn_output_space) ctrnn_size = ContinuousTimeRNN.get_individual_size( config.ctrnn_conf, cnn_output_space, output_space) ind_cnn = individual[0:cnn_size] ind_ctrnn = individual[cnn_size:cnn_size + ctrnn_size] self.cnn = Cnn(input_space=input_space, output_space=cnn_output_space, config=config.cnn_conf, individual=ind_cnn) self.ctrnn = ContinuousTimeRNN(input_space=cnn_output_space, output_space=output_space, config=config.ctrnn_conf, individual=ind_ctrnn)
def test_step(self, ctrnn_config, brain_param_identity, box2d): ctrnn_config = evolve(ctrnn_config, set_principle_diagonal_elements_of_W_negative=False) bp = brain_param_identity ContinuousTimeRNN.generate_and_set_class_state(config=ctrnn_config, input_space=box2d, output_space=Box(-1, 1, shape=[2]), ) brain = ContinuousTimeRNN(input_space=box2d, output_space=box2d, individual=self.param_to_genom(bp), config=ctrnn_config) brain.delta_t = 1.0 ob = np.array([1, 1]) assert np.allclose(brain.y, np.zeros([2, 2])) res = brain.step(ob) # due to identity matrices after one iteration the internal state is now exactly the observersion assert np.allclose(brain.y, ob) # due to identity matrices after one iteration the output is just the input, but with tanh. assert np.allclose(res, np.tanh(ob)) brain.step(ob) assert np.allclose(brain.y, np.tanh(ob) + ob + ob)
def get_free_parameter_usage(cls, config: CnnCtrnnCfg, input_space: Space, output_space: Space): cnn_output_space = Cnn.get_output_shape(config=config.cnn_conf, input_space=input_space) cnn_paramter_usage = Cnn.get_free_parameter_usage( config=config.cnn_conf, input_space=input_space, output_space=cnn_output_space) ctrnn_paramter_usage = ContinuousTimeRNN.get_free_parameter_usage( config=config.ctrnn_conf, input_space=cnn_output_space, output_space=output_space) return { 'CNN': cnn_paramter_usage, 'CTRNN': ctrnn_paramter_usage, cls._usage_key_cnn_output: cnn_output_space }
def get_class_state(cls): return ContinuousTimeRNN.get_class_state()
class CnnCtrnn(IBrain[CnnCtrnnCfg]): _usage_key_cnn_output = "_cnn_output_space" def __init__(self, input_space: Space, output_space: Space, individual: np.ndarray, config: CnnCtrnnCfg): super().__init__(input_space, output_space, individual, config) assert len(individual) == self.get_individual_size( config, input_space, output_space) paramter_usage_dict = self.get_free_parameter_usage( config, input_space, output_space) cnn_output_space = paramter_usage_dict[self._usage_key_cnn_output] cnn_size = Cnn.get_individual_size(config.cnn_conf, input_space, cnn_output_space) ctrnn_size = ContinuousTimeRNN.get_individual_size( config.ctrnn_conf, cnn_output_space, output_space) ind_cnn = individual[0:cnn_size] ind_ctrnn = individual[cnn_size:cnn_size + ctrnn_size] self.cnn = Cnn(input_space=input_space, output_space=cnn_output_space, config=config.cnn_conf, individual=ind_cnn) self.ctrnn = ContinuousTimeRNN(input_space=cnn_output_space, output_space=output_space, config=config.ctrnn_conf, individual=ind_ctrnn) def brainstep(self, ob: np.ndarray) -> Union[np.ndarray, np.generic]: return self.ctrnn.brainstep(self.cnn.brainstep(ob)) @classmethod def get_free_parameter_usage(cls, config: CnnCtrnnCfg, input_space: Space, output_space: Space): cnn_output_space = Cnn.get_output_shape(config=config.cnn_conf, input_space=input_space) cnn_paramter_usage = Cnn.get_free_parameter_usage( config=config.cnn_conf, input_space=input_space, output_space=cnn_output_space) ctrnn_paramter_usage = ContinuousTimeRNN.get_free_parameter_usage( config=config.ctrnn_conf, input_space=cnn_output_space, output_space=output_space) return { 'CNN': cnn_paramter_usage, 'CTRNN': ctrnn_paramter_usage, cls._usage_key_cnn_output: cnn_output_space } @classmethod def generate_and_set_class_state(cls, config: CnnCtrnnCfg, input_space: Space, output_space: Space): cnn_output_space = Cnn.get_output_shape(config=config.cnn_conf, input_space=input_space) ContinuousTimeRNN.generate_and_set_class_state(config.ctrnn_conf, cnn_output_space, output_space) @classmethod def get_class_state(cls): return ContinuousTimeRNN.get_class_state() @classmethod def set_class_state(cls, v_mask, w_mask, t_mask): return ContinuousTimeRNN.set_class_state(v_mask, w_mask, t_mask)
def set_class_state(cls, v_mask, w_mask, t_mask): return ContinuousTimeRNN.set_class_state(v_mask, w_mask, t_mask)
[0, 0, 0, 1]]), W=np.array([[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 0, 0], [0, 0, 0, -1]]), T=np.array([[0, 0, 1, 0], [0, 0, -1, 1], [0, 0, -1, 1], [2, 2, 2, -3], [1, 0, 0, 0], [0, 1, 0, 0]]).flatten(order='F'), y0=np.array([]), clip_min=np.array([]), clip_max=np.array([])) ind = param_to_genom(param) env = experiment.env_template for i in range(1): brain = ContinuousTimeRNN(input_space=experiment.input_space, output_space=experiment.output_space, individual=ind, config=cfg_exp.brain) ob = env.reset() transformed_ob = transform(ob, coming_from_space=experiment.input_space, is_brain_input=True) env.unwrapped.input_data = [0, 1, 0, 1, 1] env.unwrapped.target = env.unwrapped.target_from_input_data( env.unwrapped.input_data) env.render() done = False fitness_current = 0 while not done: brain_output = brain.step(transformed_ob) action = transform(brain_output,
def test_generating_masks_dense(self, ctrnn_config, box2d): ContinuousTimeRNN.generate_and_set_class_state( config=evolve(ctrnn_config, v_mask="dense", t_mask="dense", w_mask="dense"), input_space=box2d, output_space=box2d, )