Discretization of Continuous Network Dynamics¶
Historically, continuous-time recurrent neural networks (CTRNN) have been used in robotics and other fields to model systems that interact with their environment over continuous time. In that case, the translation of the dynamics into the output is trivial as the network’s state evolves continuously in response to inputs, and the output is typically read at specific time intervals. Therefore, one of biggest questions when working with continuous-time recurrent neural networks (CTRNN) is how to convert their continuous dynamics as a response to a given input into a discrete output.
One of the possible approaches, implemented in CT-NEAT, is one consistent with the scientific consensus on the way biological brains work. In this approach, an output of a network is loosely associated with a stable attractor (or lack of thereof) which the system falls into as a response to a given input. In some cases, it is interesting to observe the dynamics not of a network as a whole, but rather of a specific neuron or a group of neurons within the network, however, this requires many additional considerations and is not yet implemented in CT-NEAT. In other words, in this approach, the output of a network is not its state at a specific time, but rather a meta-analysis of the network’s behavior over a period of time.
The disretizer module provides such functionality to convert a continuous-time recurrent neural
network’s (CTRNN) dynamics into a discrete output.
The discretizer class works as follows:
When initialized, it takes any CTRNN network, a set of input values on which the network will be evaluated, a set of expected output values corresponding to the inputs, and parameters controlling the discretization process and any other controllable part of the network’s dynamics (e.g., simulation time, time step, etc.).
For each input value, the network is simulated over a specified period of time, and its dynamics are recorded.
The recorded dynamics are then analyzed to identify stable attractors or patterns in the network’s behavior. This step uses the functions defined in the
iznn.dynamic_attractorsmodule, which returns a vector encoding the attractor (if one is found).Over the space of the identified attractors, a clustering algorithm is applied to group similar attractors together. Either fixed number of clusters can be specified, or the algorithm can determine the optimal number of clusters based on the data.
Once each input has been associated with a cluster, the Hungarian (or Munkres) algorithm is used to optimally match the identified clusters with the expected output values, minimizing the overall discrepancy between the network’s outputs and the expected outputs.
The final output of the discretizer is a mapping from each input to its corresponding discrete output, based on the identified attractors and the optimal matching process.
Here are the docstrings for the module:
This module contains the class which is used to discretize continuous network dymamics.
- class ctneat.discretizer.Discretizer(network, inputs: Collection[Collection], outputs: Collection[Collection | int | float], max_time: float = 20.0, dt: float = 0.05, force_cluster_num: bool = False, epsilon: float = 0.5, min_samples: int = 1, random_state: int | None = 3, verbose: bool = False, printouts: bool = True, advance_args: Dict | None = None, resample_data_args: Dict | None = None, dynamics_args: Dict | None = None, kmeans_args: Dict | None = None, dbscan_args: Dict | None = None)[source]¶
This class is used to discretize continuous network dynamics.
- __init__(network, inputs: Collection[Collection], outputs: Collection[Collection | int | float], max_time: float = 20.0, dt: float = 0.05, force_cluster_num: bool = False, epsilon: float = 0.5, min_samples: int = 1, random_state: int | None = 3, verbose: bool = False, printouts: bool = True, advance_args: Dict | None = None, resample_data_args: Dict | None = None, dynamics_args: Dict | None = None, kmeans_args: Dict | None = None, dbscan_args: Dict | None = None)[source]¶
Initializes the Discretizer with the given parameters.
- Parameters:
network – The continuous network to be discretized. The type is not strictly defined here, however, any object passed here must have an advance method and a time_ms attribute.
inputs (List[Union[Tuple, List]]) – List of input vectors to the network.
outputs (List[Union[int, float]]) – List of expected output values corresponding to the inputs.
max_time (float) – Maximum time to run the network for each input (in ms).
dt (float) – Time step for the simulation (in ms).
force_cluster_num (bool) – If True, forces KMeans clustering with number of clusters equal to number of unique outputs.
epsilon (float) – Epsilon parameter for DBSCAN clustering. This is the maximum distance between two samples for one to be considered as in the neighborhood of the other.
min_samples (int) – Minimum samples parameter for DBSCAN clustering. This is the number of samples in a neighborhood for a point to be considered as a core point.
random_state (Optional[int]) – Random state for reproducibility. If None, randomness is not controlled.
verbose (bool) – If True, prints detailed logs during processing.
printouts (bool) – If True, prints summary information after processing.
advance_args (Optional[Dict]) – Additional arguments for the network’s advance method. For reference, see the advance method of the network being used.
resample_data_args (Optional[Dict]) – Additional arguments for the resample_data function. For reference, see the resample_data function in ctneat.iznn.dynamic_attractors.
dynamics_args (Optional[Dict]) – Additional arguments for the network’s dynamics method. For reference, see the dynamic_attractors_pipeline function in ctneat.iznn.dynamic_attractors.
kmeans_args (Optional[Dict]) – Additional arguments for KMeans clustering. For reference, see sklearn.cluster.KMeans.
dbscan_args (Optional[Dict]) – Additional arguments for DBSCAN clustering. For reference, see sklearn.cluster.DBSCAN.
- cluster_attractors() Dict[int, int][source]¶
Cluster the attractor states using either KMeans or DBSCAN. If force_cluster_num is True, KMeans is used with number of clusters equal to number of unique outputs. Otherwise, DBSCAN is used.
- Returns:
A dictionary mapping input index to cluster label.
- discretize() Dict[int, int | float | None][source]¶
Run the full discretization pipeline: run the network, cluster attractors, and map clusters to outputs.
- Returns:
A dictionary mapping input index to predicted output value.