3 @brief Cluster analysis algorithm: SYNC-SOM
4 @details Implementation based on paper @cite article::syncsom::1.
6 @authors Andrei Novikov (pyclustering@yandex.ru)
8 @copyright BSD-3-Clause
24 @brief Class represents clustering algorithm SYNC-SOM. SYNC-SOM is bio-inspired algorithm that is based on oscillatory network
25 that uses self-organized feature map as the first layer.
29 # read sample for clustering
30 sample = read_sample(file);
32 # create oscillatory network for cluster analysis where the first layer has
33 # size 10x10 and connectivity radius for objects 1.0.
34 network = syncsom(sample, 10, 10, 1.0);
36 # simulate network (perform cluster analysis) and collect output dynamic
37 (dyn_time, dyn_phase) = network.process(True, 0.998);
39 # obtain encoded clusters
40 encoded_clusters = network.get_som_clusters();
42 # obtain real clusters
43 clusters = network.get_clusters();
45 # show the first layer of the network
46 network.show_som_layer();
48 # show the second layer of the network
49 network.show_sync_layer();
57 @brief The first layer of the oscillatory network - self-organized feature map.
66 @brief The second layer of the oscillatory network based on Kuramoto model.
74 @brief Constructor of the double layer oscillatory network SYNC-SOM.
76 @param[in] data (list): Input data that is presented as list of points (objects), each point should be represented by list or tuple.
77 @param[in] rows (uint): Rows of neurons (number of neurons in column) in the input layer (self-organized feature map).
78 @param[in] cols (uint): Columns of neurons (number of neurons in row) in the input later (self-organized feature map).
79 @param[in] radius (double): Connectivity radius between objects that defines connection between oscillators in the second layer.
86 self.
_som =
som(rows, cols, conn_type=type_conn.grid_four, ccore=
False)
96 def process(self, collect_dynamic=False, order=0.999):
98 @brief Performs simulation of the oscillatory network.
100 @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.
101 @param[in] order (double): Order of process synchronization that should be considered as end of clustering, destributed 0..1.
103 @return (tuple) Dynamic of oscillatory network. If argument 'collect_dynamic' = True, than return dynamic for the whole simulation time,
104 otherwise returns only last values (last step of simulation) of dynamic.
106 @see get_som_clusters()
116 for i
in range(self.
_som.size):
117 if self.
_som.awards[i] > 0:
118 weights.append(self.
_som.weights[i])
128 def __create_sync_layer(self, weights):
130 @brief Creates second layer of the network.
132 @param[in] weights (list): List of weights of SOM neurons.
134 @return (syncnet) Second layer of the network.
137 sync_layer =
syncnet(weights, 0.0, initial_phases = initial_type.RANDOM_GAUSSIAN, ccore=
False)
139 for oscillator_index1
in range(0, len(sync_layer)):
140 for oscillator_index2
in range(oscillator_index1 + 1, len(sync_layer)):
142 sync_layer.set_connection(oscillator_index1, oscillator_index2)
147 def __has_object_connection(self, oscillator_index1, oscillator_index2):
149 @brief Searches for pair of objects that are encoded by specified neurons and that are connected in line with connectivity radius.
151 @param[in] oscillator_index1 (uint): Index of the first oscillator in the second layer.
152 @param[in] oscillator_index2 (uint): Index of the second oscillator in the second layer.
154 @return (bool) True - if there is pair of connected objects encoded by specified oscillators.
160 for index_object1
in self.
_som.capture_objects[som_neuron_index1]:
161 for index_object2
in self.
_som.capture_objects[som_neuron_index2]:
162 distance = euclidean_distance_square(self.
_data[index_object1], self.
_data[index_object2])
171 @brief Returns clusters with SOM neurons that encode input features in line with result of synchronization in the second (Sync) layer.
173 @return (list) List of clusters that are represented by lists of indexes of neurons that encode input data.
180 sync_clusters = self.
_analyser.allocate_clusters()
183 som_clusters = list()
184 for oscillators
in sync_clusters:
186 for index_oscillator
in oscillators:
188 cluster.append(index_neuron)
190 som_clusters.append(cluster)
197 @brief Returns clusters in line with ensembles of synchronous oscillators where each synchronous ensemble corresponds to only one cluster.
199 @param[in] eps (double): Maximum error for allocation of synchronous ensemble oscillators.
201 @return (list) List of grours (lists) of indexes of synchronous oscillators that corresponds to index of objects.
204 @see get_som_clusters()
208 sync_clusters = self.
_analyser.allocate_clusters(eps)
211 for oscillators
in sync_clusters:
213 for index_oscillator
in oscillators:
216 cluster += self.
_som.capture_objects[index_neuron]
218 clusters.append(cluster)
225 @brief Returns clustering result representation type that indicate how clusters are encoded.
227 @return (type_encoding) Clustering result representation.
233 return type_encoding.CLUSTER_INDEX_LIST_SEPARATION
238 @brief Shows visual representation of the first (SOM) layer.
242 self.
_som.show_network()
247 @brief Shows visual representation of the second (Sync) layer.
251 self.
_sync.show_network()