3 @brief Chaotic Neural Network
4 @details Implementation based on paper @cite article::nnet::cnn::1, @cite inproceedings::nnet::cnn::1.
6 @authors Andrei Novikov (pyclustering@yandex.ru)
8 @copyright BSD-3-Clause
16 import matplotlib.pyplot
as plt
17 from matplotlib
import rcParams
18 from matplotlib.font_manager
import FontProperties
20 from enum
import IntEnum
22 from scipy.spatial
import Delaunay
24 from pyclustering.utils import euclidean_distance_square, average_neighbor_distance, heaviside, draw_dynamics
29 @brief Enumeration of connection types for Chaotic Neural Network.
39 TRIANGULATION_DELAUNAY = 1,
44 @brief Container of output dynamic of the chaotic neural network where states of each neuron during simulation are stored.
52 @brief Costructor of the chaotic neural network output dynamic.
54 @param[in] output (list): Dynamic of oscillators on each step of simulation.
55 @param[in] time (list): Simulation time.
68 @brief (uint) Returns amount of simulation steps that are stored.
76 @brief Allocates observation matrix in line with output dynamic of the network.
77 @details Matrix where state of each neuron is denoted by zero/one in line with Heaviside function on each iteration.
79 @return (list) Observation matrix of the network dynamic.
82 number_neurons = len(self.
output[0])
83 observation_matrix = []
85 for iteration
in range(len(self.
output)):
86 obervation_column = []
87 for index_neuron
in range(number_neurons):
88 obervation_column.append(heaviside(self.
output[iteration][index_neuron]))
90 observation_matrix.append(obervation_column)
92 return observation_matrix
95 def __allocate_neuron_patterns(self, start_iteration, stop_iteration):
97 @brief Allocates observation transposed matrix of neurons that is limited by specified periods of simulation.
98 @details Matrix where state of each neuron is denoted by zero/one in line with Heaviside function on each iteration.
100 @return (list) Transposed observation matrix that is limited by specified periods of simulation.
105 for index_neuron
in range(len(self.
output[0])):
107 for iteration
in range(start_iteration, stop_iteration):
108 pattern_neuron.append(heaviside(self.
output[iteration][index_neuron]))
110 pattern_matrix.append(pattern_neuron)
112 return pattern_matrix
117 @brief Allocate clusters in line with ensembles of synchronous neurons where each synchronous ensemble corresponds to only one cluster.
119 @param[in] steps (double): Amount of steps from the end that is used for analysis. During specified period chaotic neural network should have stable output
120 otherwise inccorect results are allocated.
122 @return (list) Grours (lists) of indexes of synchronous oscillators.
123 For example [ [index_osc1, index_osc3], [index_osc2], [index_osc4, index_osc5] ].
128 if iterations >= len(self.
output):
129 iterations = len(self.
output)
133 start_iteration = len(self.
output) - iterations
134 end_iteration = len(self.
output)
138 ensembles.append( [0] )
140 for index_neuron
in range(1, len(self.
output[0])):
141 neuron_pattern = pattern_matrix[index_neuron][:]
143 neuron_assigned =
False
145 for ensemble
in ensembles:
146 ensemble_pattern = pattern_matrix[ensemble[0]][:]
148 if neuron_pattern == ensemble_pattern:
149 ensemble.append(index_neuron)
150 neuron_assigned =
True
153 if neuron_assigned
is False:
154 ensembles.append( [index_neuron] )
161 @brief Visualizer of output dynamic of chaotic neural network (CNN).
168 @brief Shows output dynamic (output of each neuron) during simulation.
170 @param[in] cnn_output_dynamic (cnn_dynamic): Output dynamic of the chaotic neural network.
172 @see show_dynamic_matrix
173 @see show_observation_matrix
177 draw_dynamics(cnn_output_dynamic.time, cnn_output_dynamic.output, x_title=
"t", y_title=
"x")
183 @brief Shows output dynamic as matrix in grey colors.
184 @details This type of visualization is convenient for observing allocated clusters.
186 @param[in] cnn_output_dynamic (cnn_dynamic): Output dynamic of the chaotic neural network.
188 @see show_output_dynamic
189 @see show_observation_matrix
193 network_dynamic = numpy.array(cnn_output_dynamic.output)
195 plt.imshow(network_dynamic.T, cmap=plt.get_cmap(
'gray'), interpolation=
'None', vmin=0.0, vmax=1.0)
202 @brief Shows observation matrix as black/white blocks.
203 @details This type of visualization is convenient for observing allocated clusters.
205 @param[in] cnn_output_dynamic (cnn_dynamic): Output dynamic of the chaotic neural network.
207 @see show_output_dynamic
208 @see show_dynamic_matrix
212 observation_matrix = numpy.array(cnn_output_dynamic.allocate_observation_matrix())
213 plt.imshow(observation_matrix.T, cmap = plt.get_cmap(
'gray'), interpolation=
'None', vmin = 0.0, vmax = 1.0)
219 @brief Chaotic neural network based on system of logistic map where clustering phenomenon can be observed.
220 @details Here is an example how to perform cluster analysis using chaotic neural network:
222 from pyclustering.cluster import cluster_visualizer
223 from pyclustering.samples.definitions import SIMPLE_SAMPLES
224 from pyclustering.utils import read_sample
225 from pyclustering.nnet.cnn import cnn_network, cnn_visualizer
227 # Load stimulus from file.
228 stimulus = read_sample(SIMPLE_SAMPLES.SAMPLE_SIMPLE3)
230 # Create chaotic neural network, amount of neurons should be equal to amount of stimulus.
231 network_instance = cnn_network(len(stimulus))
233 # Perform simulation during 100 steps.
235 output_dynamic = network_instance.simulate(steps, stimulus)
237 # Display output dynamic of the network.
238 cnn_visualizer.show_output_dynamic(output_dynamic)
240 # Display dynamic matrix and observation matrix to show clustering phenomenon.
241 cnn_visualizer.show_dynamic_matrix(output_dynamic)
242 cnn_visualizer.show_observation_matrix(output_dynamic)
244 # Visualize clustering results.
245 clusters = output_dynamic.allocate_sync_ensembles(10)
246 visualizer = cluster_visualizer()
247 visualizer.append_clusters(clusters, stimulus)
253 def __init__(self, num_osc, conn_type = type_conn.ALL_TO_ALL, amount_neighbors = 3):
255 @brief Constructor of chaotic neural network.
257 @param[in] num_osc (uint): Amount of neurons in the chaotic neural network.
258 @param[in] conn_type (type_conn): CNN type connection for the network.
259 @param[in] amount_neighbors (uint): k-nearest neighbors for calculation scaling constant of weights.
274 self.
__output = [ random.random()
for _
in range(num_osc) ]
279 @brief Returns size of the chaotic neural network that is defined by amount of neurons.
287 @brief Simulates chaotic neural network with extrnal stimulus during specified steps.
288 @details Stimulus are considered as a coordinates of neurons and in line with that weights
291 @param[in] steps (uint): Amount of steps for simulation.
292 @param[in] stimulus (list): Stimulus that are used for simulation.
294 @return (cnn_dynamic) Output dynamic of the chaotic neural network.
302 dynamic.output.append(self.
__output)
303 dynamic.time.append(0)
305 for step
in range(1, steps, 1):
308 dynamic.output.append(self.
__output)
309 dynamic.time.append(step)
314 def __calculate_states(self):
316 @brief Calculates new state of each neuron.
317 @detail There is no any assignment.
319 @return (list) Returns new states (output).
323 output = [ 0.0
for _
in range(self.
__num_osc) ]
331 def __neuron_evolution(self, index):
333 @brief Calculates state of the neuron with specified index.
335 @param[in] index (uint): Index of neuron in the network.
337 @return (double) New output of the specified neuron.
342 for index_neighbor
in range(self.
__num_osc):
343 value += self.
__weights[index][index_neighbor] * (1.0 - 2.0 * (self.
__output[index_neighbor] ** 2))
348 def __create_weights(self, stimulus):
350 @brief Create weights between neurons in line with stimulus.
352 @param[in] stimulus (list): External stimulus for the chaotic neural network.
358 self.
__weights = [ [ 0.0
for _
in range(len(stimulus)) ]
for _
in range(len(stimulus)) ]
364 elif self.
__conn_type == type_conn.TRIANGULATION_DELAUNAY:
368 def __create_weights_all_to_all(self, stimulus):
370 @brief Create weight all-to-all structure between neurons in line with stimulus.
372 @param[in] stimulus (list): External stimulus for the chaotic neural network.
376 for i
in range(len(stimulus)):
377 for j
in range(i + 1, len(stimulus)):
387 def __create_weights_delaunay_triangulation(self, stimulus):
389 @brief Create weight Denlauny triangulation structure between neurons in line with stimulus.
391 @param[in] stimulus (list): External stimulus for the chaotic neural network.
395 points = numpy.array(stimulus)
396 triangulation = Delaunay(points)
398 for triangle
in triangulation.simplices:
399 for index_tri_point1
in range(len(triangle)):
400 for index_tri_point2
in range(index_tri_point1 + 1, len(triangle)):
401 index_point1 = triangle[index_tri_point1]
402 index_point2 = triangle[index_tri_point2]
406 self.
__weights[index_point1][index_point2] = weight
407 self.
__weights[index_point2][index_point1] = weight
413 def __calculate_weight(self, stimulus1, stimulus2):
415 @brief Calculate weight between neurons that have external stimulus1 and stimulus2.
417 @param[in] stimulus1 (list): External stimulus of the first neuron.
418 @param[in] stimulus2 (list): External stimulus of the second neuron.
420 @return (double) Weight between neurons that are under specified stimulus.
424 distance = euclidean_distance_square(stimulus1, stimulus2)
430 @brief Shows structure of the network: neurons and connections between them.
435 if (dimension != 3)
and (dimension != 2):
436 raise NameError(
'Network that is located in different from 2-d and 3-d dimensions can not be represented')
458 def __create_surface(self, dimension):
460 @brief Prepares surface for showing network structure in line with specified dimension.
462 @param[in] dimension (uint): Dimension of processed data (external stimulus).
464 @return (tuple) Description of surface for drawing network structure.
468 rcParams[
'font.sans-serif'] = [
'Arial']
469 rcParams[
'font.size'] = 12
474 axes = fig.add_subplot(111)
476 axes = fig.gca(projection=
'3d')
478 surface_font = FontProperties()
479 surface_font.set_name(
'Arial')
480 surface_font.set_size(
'12')