Completed
Push — master ( 5c451b...ca5347 )
by Andrei
01:46
created

cnn_network   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 182
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 182
rs 10
c 0
b 0
f 0
wmc 21

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __calculate_weight() 0 13 1
A __create_weights_all_to_all() 0 18 3
A __init__() 0 20 2
A __len__() 0 6 1
B simulate() 0 26 2
A __calculate_states() 0 15 3
A __neuron_evolution() 0 15 2
B __create_weights() 0 18 6
A __create_weights_delaunay_triangulation() 0 9 1
1
"""!
2
3
@brief Chaotic Neural Network
4
@details Based on article description:
5
         - E.N.Benderskaya, S.V.Zhukova. Large-dimension image clustering by means of fragmentary synchronization in chaotic systems. 2007.
6
         - E.N.Benderskaya, S.V.Zhukova. Clustering by Chaotic Neural Networks with Mean Field Calculated Via Delaunay Triangulation. 2008.
7
8
@authors Andrei Novikov ([email protected])
9
@date 2014-2016
10
@copyright GNU Public License
11
12
@cond GNU_PUBLIC_LICENSE
13
    PyClustering is free software: you can redistribute it and/or modify
14
    it under the terms of the GNU General Public License as published by
15
    the Free Software Foundation, either version 3 of the License, or
16
    (at your option) any later version.
17
    
18
    PyClustering is distributed in the hope that it will be useful,
19
    but WITHOUT ANY WARRANTY; without even the implied warranty of
20
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
    GNU General Public License for more details.
22
    
23
    You should have received a copy of the GNU General Public License
24
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
25
@endcond
26
27
"""
28
29
import matplotlib.pyplot as plt;
0 ignored issues
show
Configuration introduced by
The import matplotlib.pyplot could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
30
import matplotlib.animation as animation;
0 ignored issues
show
Configuration introduced by
The import matplotlib.animation could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
Unused Code introduced by
Unused matplotlib.animation imported as animation
Loading history...
31
32
import math;
33
import random;
34
35
from enum import IntEnum;
36
37
from pyclustering.utils import euclidean_distance_sqrt, average_neighbor_distance, heaviside, draw_dynamics;
38
39
40
class type_conn(IntEnum):
41
    """!
42
    @brief Enumeration of connection types for Chaotic Neural Network.
43
    
44
    @see cnn_network
45
    
46
    """
47
    
48
    ## All oscillators have connection with each other.
49
    ALL_TO_ALL  = 0,
50
    
51
    ## Connections between oscillators are created in line with Delaunay triangulation.
52
    TRIANGULATION_DELAUNAY = 1,
53
54
55
class cnn_dynamic:
56
    """!
57
    @brief Container of output dynamic of the chaotic neural network where states of each neuron during simulation are stored.
58
    
59
    @see cnn_network
60
    
61
    """
62
    
63
    def __init__(self, output = [], time = []):
0 ignored issues
show
Bug Best Practice introduced by
The default value [] might cause unintended side-effects.

Objects as default values are only created once in Python and not on each invocation of the function. If the default object is modified, this modification is carried over to the next invocation of the method.

# Bad:
# If array_param is modified inside the function, the next invocation will
# receive the modified object.
def some_function(array_param=[]):
    # ...

# Better: Create an array on each invocation
def some_function(array_param=None):
    array_param = array_param or []
    # ...
Loading history...
64
        """!
65
        @brief Costructor of the chaotic neural network output dynamic.
66
67
        @param[in] phase (list): Dynamic of oscillators on each step of simulation.
68
        @param[in] time (list): Simulation time.
69
        
70
        """
71
        
72
        ## Output value of each neuron on each iteration.
73
        self.output = output;
74
        
75
        ## Sequence of simulation steps of the network.
76
        self.time = time;
77
78
79
    def __len__(self):
80
        """!
81
        @brief (uint) Returns amount of simulation steps that are stored.
82
        
83
        """
84
        return len(self.output);
85
86
87
    def allocate_observation_matrix(self):
88
        """!
89
        @brief Allocates observation matrix in line with output dynamic of the network.
90
        @details Matrix where state of each neuron is denoted by zero/one in line with Heaviside function on each iteration.
91
        
92
        @return (list) Observation matrix of the network dynamic.
93
        
94
        """
95
        number_neurons = len(self.output[0]);
96
        observation_matrix = [];
97
        
98
        for iteration in range(len(self.output)):
99
            obervation_column = [];
100
            for index_neuron in range(number_neurons):
101
                obervation_column.append(heaviside(self.output[iteration][index_neuron]));
102
            
103
            observation_matrix.append(obervation_column);
104
        
105
        return observation_matrix;
106
107
108
class cnn_visualizer:
109
    """!
110
    @brief Visualizer of output dynamic of chaotic neural network (CNN).
111
    
112
    """
113
    
114
    @staticmethod
115
    def show_output_dynamic(cnn_output_dynamic):
116
        """!
117
        @brief Shows output dynamic (output of each neuron) during simulation.
118
        
119
        @param[in] cnn_output_dynamic (cnn_dynamic): Output dynamic of the chaotic neural network.
120
        
121
        @see show_dynamic_matrix
122
        @see show_observation_matrix
123
        
124
        """
125
        
126
        draw_dynamics(cnn_output_dynamic.time, cnn_output_dynamic.output, x_title = "t", y_title = "x");
127
    
128
    
129
    @staticmethod
130
    def show_dynamic_matrix(cnn_output_dynamic):
131
        """!
132
        @brief Shows output dynamic as matrix in grey colors.
133
        @details This type of visualization is convenient for observing allocated clusters.
134
        
135
        @param[in] cnn_output_dynamic (cnn_dynamic): Output dynamic of the chaotic neural network.
136
        
137
        @see show_output_dynamic
138
        @see show_observation_matrix
139
        
140
        """
141
        
142
        plt.imshow(cnn_output_dynamic.output, cmap = plt.get_cmap('gray'), interpolation='None', vmin = 0.0, vmax = 1.0); 
143
        plt.show();
144
    
145
    
146
    @staticmethod
147
    def show_observation_matrix(cnn_output_dynamic):
148
        """!
149
        @brief Shows observation matrix as black/white blocks.
150
        @details This type of visualization is convenient for observing allocated clusters.
151
        
152
        @param[in] cnn_output_dynamic (cnn_dynamic): Output dynamic of the chaotic neural network.
153
        
154
        @see show_output_dynamic
155
        @see show_dynamic_matrix
156
        
157
        """
158
        
159
        observation_matrix = cnn_output_dynamic.allocate_observation_matrix();
160
        plt.imshow(observation_matrix, cmap = plt.get_cmap('gray'), interpolation='None', vmin = 0.0, vmax = 1.0); 
161
        plt.show();
162
163
164
class cnn_network:
165
    """!
166
    @brief Chaotic neural network based on system of logistic map where clustering phenomenon can be observed.
167
    
168
    Example:
169
    @code
170
        # load stimulus from file
171
        stimulus = read_sample(SIMPLE_SAMPLES.SAMPLE_SIMPLE1);
172
        
173
        # create chaotic neural network, amount of neurons should be equal to amout of stimulus
174
        network_instance = cnn_network(len(stimulus));
175
        
176
        # simulate it during 100 steps
177
        output_dynamic = network_instance.simulate(steps, stimulus);
178
        
179
        # display output dynamic of the network
180
        cnn_visualizer.show_output_dynamic(output_dynamic);
181
        
182
        # dysplay dynamic matrix and observation matrix to show clustering
183
        # phenomenon.
184
        cnn_visualizer.show_dynamic_matrix(output_dynamic);
185
        cnn_visualizer.show_observation_matrix(output_dynamic);
186
    @endcode
187
    
188
    """
189
    
190
    def __init__(self, num_osc, conn_type = type_conn.ALL_TO_ALL, amount_neighbors = 3):
191
        """!
192
        @brief Constructor of chaotic neural network.
193
        
194
        @param[in] num_osc (uint): Amount of neurons in the chaotic neural network.
195
        @param[in] conn_type (type_conn): CNN type connection for the network.
196
        @param[in] amount_neighbors (uint): k-nearest neighbors for calculation scaling constant of weights.
197
        
198
        """
199
        
200
        self.__num_osc = num_osc;
201
        self.__conn_type = conn_type;
202
        self.__amount_neighbors = amount_neighbors;
203
        
204
        self.__average_distance = 0.0;
205
        self.__weights = None;
206
        self.__weights_summary = None;
207
        
208
        random.seed();
209
        self.__output = [ random.random() for _ in range(num_osc) ];
210
    
211
    
212
    def __len__(self):
213
        """!
214
        @brief Returns size of the chaotic neural network that is defined by amount of neurons.
215
        
216
        """
217
        return self.__num_osc;
218
    
219
    
220
    def simulate(self, steps, stimulus):
221
        """!
222
        @brief Simulates chaotic neural network with extrnal stimulus during specified steps.
223
        @details Stimulus are considered as a coordinates of neurons and in line with that weights
224
                 are initialized.
225
        
226
        @param[in] steps (uint): Amount of steps for simulation.
227
        @param[in] stimulus (list): Stimulus that are used for simulation.
228
        
229
        @return (cnn_dynamic) Output dynamic of the chaotic neural network.
230
        
231
        """
232
        
233
        self.__create_weights(stimulus);
234
        
235
        dynamic = cnn_dynamic([], []);
236
        dynamic.output.append(self.__output);
237
        dynamic.time.append(0);
238
        
239
        for step in range(1, steps, 1):
240
            self.__output = self.__calculate_states();
241
            
242
            dynamic.output.append(self.__output);
243
            dynamic.time.append(step);
244
            
245
        return dynamic;
246
    
247
    
248
    def __calculate_states(self):
249
        """!
250
        @brief Calculates new state of each neuron.
251
        @detail There is no any assignment.
252
        
253
        @return (list) Returns new states (output).
254
        
255
        """
256
        
257
        output = [ 0.0 for _ in range(self.__num_osc) ];
258
        
259
        for i in range(self.__num_osc):
260
            output[i] = self.__neuron_evolution(i);
261
        
262
        return output;
263
    
264
    
265
    def __neuron_evolution(self, index):
266
        """!
267
        @brief Calculates state of the neuron with specified index.
268
        
269
        @param[in] index (uint): Index of neuron in the network.
270
        
271
        @return (double) New output of the specified neuron.
272
        
273
        """
274
        value = 0.0;
275
        
276
        for index_neighbor in range(self.__num_osc):
277
            value += self.__weights[index][index_neighbor] * (1.0 - 2.0 * (self.__output[index_neighbor] ** 2));
278
        
279
        return value / self.__weights_summary[index];
280
    
281
    
282
    def __create_weights(self, stimulus):
283
        """!
284
        @brief Create weights between neurons in line with stimulus.
285
        
286
        @param[in] stimulus (list): External stimulus for the chaotic neural network.
287
        
288
        """
289
        
290
        self.__average_distance = average_neighbor_distance(stimulus, self.__amount_neighbors);
291
        
292
        self.__weights = [ [ 0.0 for _ in range(len(stimulus)) ] for _ in range(len(stimulus)) ];
293
        self.__weights_summary = [ 0.0 for _ in range(self.__num_osc) ];
294
        
295
        if (self.__conn_type == type_conn.ALL_TO_ALL):
296
            self.__create_weights_all_to_all(stimulus);
297
        
298
        elif (self.__conn_type == type_conn.TRIANGULATION_DELAUNAY):
299
            self.__create_weights_delaunay_triangulation(stimulus);
300
    
301
    
302
    def __create_weights_all_to_all(self, stimulus):
303
        """!
304
        @brief Create weight all-to-all structure between neurons in line with stimulus.
305
        
306
        @param[in] stimulus (list): External stimulus for the chaotic neural network.
307
        
308
        """
309
        
310
        for i in range(len(stimulus)):
311
            for j in range(i + 1, len(stimulus)):
312
                weight = self.__calculate_weight(stimulus[i], stimulus[j]);
313
                print(i, j, weight, stimulus[i], stimulus[j]);
314
                
315
                self.__weights[i][j] = weight;
316
                self.__weights[j][i] = weight;
317
                
318
                self.__weights_summary[i] += weight;
319
                self.__weights_summary[j] += weight;
320
    
321
    
322
    def __create_weights_delaunay_triangulation(self, stimulus):
323
        """!
324
        @brief Create weight Denlauny triangulation structure between neurons in line with stimulus.
325
        
326
        @param[in] stimulus (list): External stimulus for the chaotic neural network.
327
        
328
        """
329
        
330
        pass;
331
    
332
    
333
    def __calculate_weight(self, stimulus1, stimulus2):
334
        """!
335
        @brief Calculate weight between neurons that have external stimulus1 and stimulus2.
336
        
337
        @param[in] stimulus1 (list): External stimulus of the first neuron.
338
        @param[in] stimulus2 (list): External stimulus of the second neuron.
339
        
340
        @return (double) Weight between neurons that are under specified stimulus.
341
        
342
        """
343
        
344
        distance = euclidean_distance_sqrt(stimulus1, stimulus2);
345
        return math.exp(-distance / (2.0 * self.__average_distance));
346