Paper:https://www.cnblogs.com/lucifer1997/p/14587182.html(Nature Machine Intelligence 2020)
NCP:https://github.com/mlech26l/keras-ncp/(TensorFlow/PyTorch)
NCP-RL:https://github.com/loldabigboi/cs-760-proj/(CartPole/HalfCheetah)
一、NCP (keras-ncp)
1、keras-ncp/wirings/wirings.py:
class NCP(Wiring): def __init__( self, inter_neurons, command_neurons, motor_neurons, sensory_fanout, inter_fanout, recurrent_command_synapses, motor_fanin, seed=22222, ): super(NCP, self).__init__(inter_neurons + command_neurons + motor_neurons) self.set_output_dim(motor_neurons) self._rng = np.random.RandomState(seed) self._num_inter_neurons = inter_neurons self._num_command_neurons = command_neurons self._num_motor_neurons = motor_neurons self._sensory_fanout = sensory_fanout self._inter_fanout = inter_fanout self._recurrent_command_synapses = recurrent_command_synapses self._motor_fanin = motor_fanin # Neuron IDs: [0..motor ... command ... inter] self._motor_neurons = list(range(0, self._num_motor_neurons)) self._command_neurons = list( range( self._num_motor_neurons, self._num_motor_neurons + self._num_command_neurons, ) ) self._inter_neurons = list( range( self._num_motor_neurons + self._num_command_neurons, self._num_motor_neurons + self._num_command_neurons + self._num_inter_neurons, ) ) if self._motor_fanin > self._num_command_neurons: raise ValueError( "Error: Motor fanin parameter is {} but there are only {} command neurons".format( self._motor_fanin, self._num_command_neurons ) ) if self._sensory_fanout > self._num_inter_neurons: raise ValueError( "Error: Sensory fanout parameter is {} but there are only {} inter neurons".format( self._sensory_fanout, self._num_inter_neurons ) ) if self._inter_fanout > self._num_command_neurons: raise ValueError( "Error:: Inter fanout parameter is {} but there are only {} command neurons".format( self._inter_fanout, self._num_command_neurons ) ) def get_type_of_neuron(self, neuron_id): if neuron_id < self._num_motor_neurons: return "motor" if neuron_id < self._num_motor_neurons + self._num_command_neurons: return "command" return "inter" def _build_sensory_to_inter_layer(self): unreachable_inter_neurons = [l for l in self._inter_neurons] # Randomly connects each sensory neuron to exactly _sensory_fanout number of interneurons for src in self._sensory_neurons: for dest in self._rng.choice( self._inter_neurons, size=self._sensory_fanout, replace=False ): if dest in unreachable_inter_neurons: unreachable_inter_neurons.remove(dest) polarity = self._rng.choice([-1, 1]) self.add_sensory_synapse(src, dest, polarity) # If it happens that some interneurons are not connected, connect them now mean_inter_neuron_fanin = int( self._num_sensory_neurons * self._sensory_fanout / self._num_inter_neurons ) # Connect "forgotten" inter neuron by at least 1 and at most all sensory neuron mean_inter_neuron_fanin = np.clip( mean_inter_neuron_fanin, 1, self._num_sensory_neurons ) for dest in unreachable_inter_neurons: for src in self._rng.choice( self._sensory_neurons, size=mean_inter_neuron_fanin, replace=False ): polarity = self._rng.choice([-1, 1]) self.add_sensory_synapse(src, dest, polarity) def _build_inter_to_command_layer(self): # Randomly connect interneurons to command neurons unreachable_command_neurons = [l for l in self._command_neurons] for src in self._inter_neurons: for dest in self._rng.choice( self._command_neurons, size=self._inter_fanout, replace=False ): if dest in unreachable_command_neurons: unreachable_command_neurons.remove(dest) polarity = self._rng.choice([-1, 1]) self.add_synapse(src, dest, polarity) # If it happens that some command neurons are not connected, connect them now mean_command_neurons_fanin = int( self._num_inter_neurons * self._inter_fanout / self._num_command_neurons ) # Connect "forgotten" command neuron by at least 1 and at most all inter neuron mean_command_neurons_fanin = np.clip( mean_command_neurons_fanin, 1, self._num_command_neurons ) for dest in unreachable_command_neurons: for src in self._rng.choice( self._inter_neurons, size=mean_command_neurons_fanin, replace=False ): polarity = self._rng.choice([-1, 1]) self.add_synapse(src, dest, polarity) def _build_recurrent_command_layer(self): # Add recurrency in command neurons for i in range(self._recurrent_command_synapses): src = self._rng.choice(self._command_neurons) dest = self._rng.choice(self._command_neurons) polarity = self._rng.choice([-1, 1]) self.add_synapse(src, dest, polarity) def _build_command__to_motor_layer(self): # Randomly connect command neurons to motor neurons unreachable_command_neurons = [l for l in self._command_neurons] for dest in self._motor_neurons: for src in self._rng.choice( self._command_neurons, size=self._motor_fanin, replace=False ): if src in unreachable_command_neurons: unreachable_command_neurons.remove(src) polarity = self._rng.choice([-1, 1]) self.add_synapse(src, dest, polarity) # If it happens that some commandneurons are not connected, connect them now mean_command_fanout = int( self._num_motor_neurons * self._motor_fanin / self._num_command_neurons ) # Connect "forgotten" command neuron to at least 1 and at most all motor neuron mean_command_fanout = np.clip(mean_command_fanout, 1, self._num_motor_neurons) for src in unreachable_command_neurons: for dest in self._rng.choice( self._motor_neurons, size=mean_command_fanout, replace=False ): polarity = self._rng.choice([-1, 1]) self.add_synapse(src, dest, polarity) def build(self, input_shape): super().build(input_shape) self._num_sensory_neurons = self.input_dim self._sensory_neurons = list(range(0, self._num_sensory_neurons)) self._build_sensory_to_inter_layer() self._build_inter_to_command_layer() self._build_recurrent_command_layer() self._build_command__to_motor_layer()
class NCP(Wiring): def __init__( self, inter_neurons, command_neurons, motor_neurons, sensory_fanout, inter_fanout, recurrent_command_synapses, motor_fanin, seed=22222, )
2、examples/stacking_ncp.py:
wiring = kncp.wirings.NCP( inter_neurons=12, # Number of inter neurons command_neurons=8, # Number of command neurons motor_neurons=1, # Number of motor neurons sensory_fanout=4, # How many outgoing synapses has each sensory neuron inter_fanout=4, # How many outgoing synapses has each inter neuron recurrent_command_synapses=4, # Now many recurrent synapses are in the command neuron layer motor_fanin=6, # How many incomming syanpses has each motor neuron ) rnn_cell = LTCCell(wiring)
二、NCP-RL (cs-760-proj)
1、cart-pole/main.py:
gym游戏环境:observation_space=4,action_space=2;
强化学习算法:DQN with target network,Motor神经元输出不同运动的Q值;