Newer
Older

Michal Kravcenko
committed
/**
* This file contains the header for the NeuralNetwork class representing a function in the form of a directed graph,
* in which the vertices are called Neurons (with activation functions) and the edges Connections (with transfer functions)

Michal Kravcenko
committed
*
* @author Michal Kravčenko
* @date 13.6.18 -
*/
//TODO preprocess the feed-forward and backward passes for more efficient parallelism

Michal Kravcenko
committed

Michal Kravcenko
committed
#ifndef INC_4NEURO_NEURALNETWORK_H
#define INC_4NEURO_NEURALNETWORK_H

Michal Kravcenko
committed
#include <vector>

Michal Kravcenko
committed
Martin Beseda
committed
#include "../settings.h"
#include "../Neuron/Neuron.h"
#include "../Neuron/NeuronConstant.h"
#include "../Neuron/NeuronBinary.h"
#include "../Neuron/NeuronLinear.h"
#include "../Neuron/NeuronLogistic.h"
#include "../NetConnection/ConnectionFunctionGeneral.h"
#include "../NetConnection/ConnectionFunctionIdentity.h"
#include "../NormalizationStrategy/NormalizationStrategy.h"
Martin Beseda
committed
namespace lib4neuro {
/**
*
*/
Martin Beseda
committed
enum class BIAS_TYPE {
NEXT_BIAS, NO_BIAS, EXISTING_BIAS
};
/**
*
*/
Martin Beseda
committed
enum class SIMPLE_CONNECTION_TYPE {
NEXT_WEIGHT, UNITARY_WEIGHT, EXISTING_WEIGHT
};
/**
*
*/
Martin Beseda
committed
class NeuralNetwork {

Michal Kravcenko
committed
protected:
Martin Beseda
committed
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
*
*/
std::vector<Neuron *> *neurons = nullptr;
/**
*
*/
std::vector<size_t> *input_neuron_indices = nullptr;
/**
*
*/
std::vector<size_t> *output_neuron_indices = nullptr;
/**
*
*/
std::vector<double> *connection_weights = nullptr;
/**
*
*/
std::vector<double> *neuron_biases = nullptr;
/**
*
*/
std::vector<int> *neuron_bias_indices = nullptr;
/**
*
*/
std::vector<double> *neuron_potentials = nullptr;
/**
*
*/
std::vector<ConnectionFunctionGeneral *> *connection_list = nullptr;
/**
*
*/
std::vector<std::vector<std::pair<size_t, size_t>> *> *inward_adjacency = nullptr;
/**
*
*/
std::vector<std::vector<std::pair<size_t, size_t>> *> *outward_adjacency = nullptr;
/**
*
*/
std::vector<std::vector<size_t> *> *neuron_layers_feedforward = nullptr;
/**
*
*/
std::vector<std::vector<size_t> *> *neuron_layers_feedbackward = nullptr;
/**
*
*/
bool layers_analyzed = false;
/**
*
*/
bool delete_weights = true;
/**
*
*/
bool delete_biases = true;
/**
*
*/
NormalizationStrategy* normalization_strategy = nullptr;
Martin Beseda
committed
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/**
* Adds a new connection to the local list of connections
* @param con Connection object to be added
* @return Returns the index of the added connection among all the connections
*/
size_t add_new_connection_to_list(ConnectionFunctionGeneral *con);
/**
* Adds a new entry (oriented edge s -> t) to the adjacency list of this network
* @param s Index of the source neuron
* @param t Index of the target neuron
* @param con_idx Index of the connection representing the edge
*/
void add_outward_connection(size_t s, size_t t, size_t con_idx);
/**
* Adds a new entry (oriented edge s <- t) to the adjacency list of this network
* @param s Index of the source neuron
* @param t Index of the target neuron
* @param con_idx Index of the connection representing the edge
*/
void add_inward_connection(size_t s, size_t t, size_t con_idx);
/**
* Performs one feedforward pass and feedbackward pass during which determines the layers of this neural network
* for simpler use during evaluation and learning
*/
void analyze_layer_structure();
public:
/**
* Runs @data through the network and then computes partial derivatives with respect to each output function and adds them
* to seperate vectors in @jacobian. Also computes the out error and stores in the vector @error
* @param[out] jacobian
* @param[in] data
* @param[out] error
*/
LIB4NEURO_API virtual void
get_jacobian(std::vector<std::vector<double>> &jacobian, std::pair<std::vector<double>, std::vector<double>> &data, std::vector<double> &error);
/**
*
* @param input
* @param output
* @param custom_weights_and_biases
*/
LIB4NEURO_API virtual void eval_single_debug(std::vector<double> &input, std::vector<double> &output,
std::vector<double> *custom_weights_and_biases = nullptr);
/**
*
* @param error_derivative
* @param gradient
*/
LIB4NEURO_API virtual void
add_to_gradient_single_debug(std::vector<double> &input, std::vector<double> &error_derivative, double error_scaling,
std::vector<double> &gradient);
Martin Beseda
committed
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/**
* Struct used to access private properties from
* the serialization function
*/
struct access;
/**
*
*/
LIB4NEURO_API explicit NeuralNetwork();
/**
*
*/
LIB4NEURO_API explicit NeuralNetwork(std::string filepath);
/**
*
*/
LIB4NEURO_API virtual ~NeuralNetwork();
/**
* If possible, returns a neural net with 'input_neuron_indices' neurons as inputs and 'output_neuron_indices' as
* outputs, otherwise returns nullptr. The returned object shares adjustable weights with this network. All
* neurons are coppied (new instances), edges also. Uses a breadth-first search as the underlying algorithm.
* @param input_neuron_indices
* @param output_neuron_indices
* @return
*/
LIB4NEURO_API NeuralNetwork *
get_subnet(std::vector<size_t> &input_neuron_indices, std::vector<size_t> &output_neuron_indices);
/**
* Replaces the values in @{this->connection_weights} and @{this->neuron_biases} by the provided values
* @param parameters
*/
LIB4NEURO_API virtual void copy_parameter_space(std::vector<double> *parameters);
/**
* Copies the pointers @{this->connection_weights} and @{this->neuron_biases} from the parental network, sets
* flags to not delete the vectors in this object
* @param parent_network
*/
LIB4NEURO_API virtual void set_parameter_space_pointers(NeuralNetwork &parent_network);
/**
*
* @param input
* @param output
* @param custom_weights_and_biases
*/
LIB4NEURO_API virtual void eval_single(std::vector<double> &input, std::vector<double> &output,
std::vector<double> *custom_weights_and_biases = nullptr);
/**
*
* @param error_derivative
* @param gradient
*/
LIB4NEURO_API virtual void
add_to_gradient_single(std::vector<double> &input, std::vector<double> &error_derivative, double error_scaling,
std::vector<double> &gradient);
Martin Beseda
committed
/**
* Adds a new neuron to the list of neurons. Also assigns a valid bias value to its activation function
* @param[in] n
* @return
*/
LIB4NEURO_API size_t add_neuron(Neuron *n, BIAS_TYPE bt = BIAS_TYPE::NEXT_BIAS, size_t bias_idx = 0);
/**
*
* @param n1_idx
* @param n2_idx
* @return
*/
LIB4NEURO_API size_t add_connection_simple(size_t n1_idx, size_t n2_idx,
SIMPLE_CONNECTION_TYPE sct = SIMPLE_CONNECTION_TYPE::NEXT_WEIGHT,
size_t weight_idx = 0);
/**
* Adds a connection with constant weight value, will not be altered during any learning process
* @param n1_idx
* @param n2_idx
* @param weight
*/
LIB4NEURO_API size_t add_connection_constant(size_t n1_idx, size_t n2_idx, double weight);
Martin Beseda
committed
/**
* Take the existing connection with index 'connection_idx' in 'parent_network' and adds it to the structure of this
* object
* @param n1_idx
* @param n2_idx
* @param connection_idx
* @param parent_network
*/
LIB4NEURO_API void
add_existing_connection(size_t n1_idx, size_t n2_idx, size_t connection_idx, NeuralNetwork &parent_network);
/**
*
*/
LIB4NEURO_API virtual void randomize_weights();
Martin Beseda
committed
/**
*
*/
LIB4NEURO_API virtual void randomize_biases();
Martin Beseda
committed
/**
*
*/
LIB4NEURO_API virtual void randomize_parameters();
Martin Beseda
committed
/**
*
*/
LIB4NEURO_API virtual void scale_biases(double alpha);
/**
*
*/
LIB4NEURO_API virtual void scale_weights(double alpha);
/**
*
*/
LIB4NEURO_API virtual void scale_parameters(double alpha);
Martin Beseda
committed
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
/**
*
* @return
*/
LIB4NEURO_API virtual size_t get_n_inputs();
/**
*
* @return
*/
LIB4NEURO_API virtual size_t get_n_outputs();
/**
*
* @return
*/
LIB4NEURO_API virtual size_t get_n_weights();
/**
*
* @return
*/
LIB4NEURO_API virtual size_t get_n_biases();
/**
*
* @return
*/
LIB4NEURO_API virtual int get_neuron_bias_index(size_t neuron_idx);
/**
*
* @return
*/
LIB4NEURO_API virtual size_t get_n_neurons();
/**
*
* @param input_neurons_indices
*/
LIB4NEURO_API void specify_input_neurons(std::vector<size_t> &input_neurons_indices);
/**
*
* @param output_neurons_indices
*/
LIB4NEURO_API void specify_output_neurons(std::vector<size_t> &output_neurons_indices);
/**
*
*/
LIB4NEURO_API void write_weights();
Martin Beseda
committed
/**
*
*/
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
LIB4NEURO_API void write_weights(std::string file_path);
/**
*
* @param file_path
*/
LIB4NEURO_API void write_weights(std::ofstream* file_path);
/**
*
*/
LIB4NEURO_API void write_biases();
/**
*
* @param file_name
*/
LIB4NEURO_API void write_biases(std::string file_path);
/**
*
* @param file_path
*/
LIB4NEURO_API void write_biases(std::ofstream* file_path);
/**
*
*/
LIB4NEURO_API void write_stats();
/**
*
* @param file_path
*/
LIB4NEURO_API void write_stats(std::string file_path);
/**
*
* @param file_path
*/
LIB4NEURO_API void write_stats(std::ofstream* file_path);
Martin Beseda
committed
/**
*
* @return
*/
LIB4NEURO_API virtual std::vector<double> *get_parameter_ptr_weights();
Martin Beseda
committed
/**
*
* @return
*/
LIB4NEURO_API virtual std::vector<double> *get_parameter_ptr_biases();
Martin Beseda
committed
/**
*
* @param filepath
*/
LIB4NEURO_API void save_text(std::string filepath);
/**
*
* @return
*/
LIB4NEURO_API NormalizationStrategy* get_normalization_strategy_instance();
/**
*
* @param ns
*/
LIB4NEURO_API void set_normalization_strategy_instance(NormalizationStrategy* ns);
}; // class NeuralNetwork
class FullyConnectedFFN: public NeuralNetwork {
public:
/**
* Constructs a fully connected feed-forward neural network
* @param neuron_numbers Pointer to vector containing number of vectors in every layer (from input to output)
* @param hidden_layer_neuron_type
*/
Martin Beseda
committed
LIB4NEURO_API explicit FullyConnectedFFN(std::vector<unsigned int>* neuron_numbers,
NEURON_TYPE hidden_layer_neuron_type,
std::ofstream* ofs = nullptr);
Martin Beseda
committed
/**
*
* @param neuron_numbers
* @param hidden_layer_neuron_types
*/
Martin Beseda
committed
LIB4NEURO_API explicit FullyConnectedFFN(std::vector<unsigned int>* neuron_numbers,
std::vector<NEURON_TYPE>* hidden_layer_neuron_types,
std::ofstream* ofs = nullptr);
Martin Beseda
committed
Martin Beseda
committed
private:
Martin Beseda
committed
void init(std::vector<unsigned int>* neuron_numbers,
std::vector<NEURON_TYPE>* hidden_layer_neuron_types,
std::ofstream* ofs = nullptr);
Martin Beseda
committed
};
}

Michal Kravcenko
committed
#endif //INC_4NEURO_NEURALNETWORK_H