Commit bbdcff15 authored by Michal Kravcenko's avatar Michal Kravcenko

-added a support for multi-network systems sharing edge weights

-added an example testing multi-network error function
parent dfaf4073
......@@ -41,4 +41,31 @@ double MSE::eval(double *weights) {
}
return error/n_elements;
}
MSE_SUM::MSE_SUM() {
this->summand = nullptr;
}
MSE_SUM::~MSE_SUM(){
if( this->summand ){
delete this->summand;
}
}
double MSE_SUM::eval(double *weights) {
double output = 0.0;
for(ErrorFunction *f: *this->summand){
output += f->eval( weights );
}
return output;
}
void MSE_SUM::add_error_function(ErrorFunction *F) {
if(!this->summand){
this->summand = new std::vector<ErrorFunction*>(0);
}
this->summand->push_back(F);
}
\ No newline at end of file
......@@ -42,12 +42,6 @@ public:
*/
MSE(NeuralNetwork* net, DataSet* ds);
/**
* Constructor for multiple error functions, which will get summed up
* @param func_vec
*/
//MSE(std::vector<ErrorFunction> func_vec);
/**
*
* @param weights
......@@ -61,5 +55,34 @@ private:
DataSet* ds;
};
class MSE_SUM : ErrorFunction{
public:
/**
*
*/
MSE_SUM();
/**
*
*/
~MSE_SUM();
/**
*
* @param weights
* @return
*/
virtual double eval(double* weights);
/**
*
* @param F
*/
void add_error_function(ErrorFunction *F);
private:
std::vector<ErrorFunction*> *summand;
};
#endif //INC_4NEURO_ERRORFUNCTION_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "FunctionBase.h"
FunctionBase::FunctionBase() {}
FunctionBase::~FunctionBase() {
}
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_FUNCTIONBASE_H
#define INC_4NEURO_FUNCTIONBASE_H
class FunctionBase {
public:
FunctionBase();
virtual ~FunctionBase();
virtual double eval(double x) = 0;
virtual FunctionBase* get_derivative() = 0;
protected:
FunctionBase* derivative = nullptr;
private:
};
#endif //INC_4NEURO_FUNCTIONBASE_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "FunctionCosine.h"
FunctionCosine::FunctionCosine(double period, double bias) {
this->period = period;
this->bias = bias;
}
double FunctionCosine::eval(double x) {
return std::cos(x * this->period + this->bias);
}
FunctionBase* FunctionCosine::get_derivative() {
if(!this->derivative){
this->derivative = new FunctionSine();
}
return this->derivative;
}
\ No newline at end of file
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_FUNCTIONCOSINE_H
#define INC_4NEURO_FUNCTIONCOSINE_H
#include <cmath>
#include "FunctionBase.h"
#include "FunctionSine.h"
class FunctionCosine: FunctionBase {
public:
FunctionCosine(double period, double bias);
double eval(double x);
FunctionBase* get_derivative();
private:
double period = 0.0;
double bias = 0.0;
};
#endif //INC_4NEURO_FUNCTIONCOSINE_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "FunctionExponential.h"
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_FUNCTIONEXPONENTIAL_H
#define INC_4NEURO_FUNCTIONEXPONENTIAL_H
#include "FunctionBase.h"
class FunctionExponential: FunctionBase {
};
#endif //INC_4NEURO_FUNCTIONEXPONENTIAL_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "FunctionLogarithm.h"
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_FUNCTIONLOGARITHM_H
#define INC_4NEURO_FUNCTIONLOGARITHM_H
#include "FunctionBase.h"
class FunctionLogarithm: FunctionBase {
};
#endif //INC_4NEURO_FUNCTIONLOGARITHM_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "FunctionPolynomial.h"
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_FUNCTIONPOLYNOMIAL_H
#define INC_4NEURO_FUNCTIONPOLYNOMIAL_H
#include "FunctionBase.h"
class FunctionPolynomial: FunctionBase {
};
#endif //INC_4NEURO_FUNCTIONPOLYNOMIAL_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "FunctionSine.h"
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_FUNCTIONSINE_H
#define INC_4NEURO_FUNCTIONSINE_H
#include "FunctionBase.h"
class FunctionSine: FunctionBase {
};
#endif //INC_4NEURO_FUNCTIONSINE_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "Graph.h"
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_GRAPH_H
#define INC_4NEURO_GRAPH_H
//TODO verification of decision making (for each input determine the magnitude of its influence over the output)
//TODO form a graph of the inverse function
class Graph {
};
#endif //INC_4NEURO_GRAPH_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "VertexBase.h"
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_VERTEXBASE_H
#define INC_4NEURO_VERTEXBASE_H
class VertexBase {
};
#endif //INC_4NEURO_VERTEXBASE_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "VertexCompound.h"
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_VERTEXCOMPOUND_H
#define INC_4NEURO_VERTEXCOMPOUND_H
class VertexCompound {
};
#endif //INC_4NEURO_VERTEXCOMPOUND_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "VertexConstant.h"
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_VERTEXCONSTANT_H
#define INC_4NEURO_VERTEXCONSTANT_H
class VertexConstant {
};
#endif //INC_4NEURO_VERTEXCONSTANT_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#include "VertexSum.h"
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 4.7.18 -
*/
#ifndef INC_4NEURO_VERTEXSUM_H
#define INC_4NEURO_VERTEXSUM_H
class VertexSum {
};
#endif //INC_4NEURO_VERTEXSUM_H
......@@ -7,15 +7,21 @@
#include "Connection.h"
Connection::Connection(Neuron *n_in, Neuron *n_out, ConnectionWeight* con) {
Connection* Connection::get_copy(Neuron *n_in, Neuron *n_out){
Connection *output = new Connection(n_in, n_out, this->con, false);
return output;
}
Connection::Connection(Neuron *n_in, Neuron *n_out, ConnectionWeight* con, bool del_weight) {
this->neuron_in = n_in;
this->neuron_out = n_out;
this->con = con;
this->delete_connection = del_weight;
}
Connection::~Connection() {
if(this->con){
if(this->con && this->delete_connection ){
delete this->con;
this->con = nullptr;
}
......
......@@ -34,18 +34,32 @@ private:
*/
Neuron *neuron_out = nullptr;
/**
*
*/
bool delete_connection = true;
//TODO pridat gradient pro ucely backpropagation
public:
/**
* Returns a new object reprresenting an edge using the same weight function as this one
* @param n_in
* @param n_out
* @return
*/
virtual Connection* get_copy(Neuron *n_in, Neuron *n_out) final;
/**
* Constructor
* @param[in] n_in Pointer to the Neuron on the receiving end of this connection
* @param[in] n_out Pointer to the Neuron on the signaling end of this connection
* @param[in] con Pointer to an object evaluating the weight function
*
* @param n_in
* @param n_out
* @param con
* @param delete_weight
*/
Connection(Neuron *n_in, Neuron *n_out, ConnectionWeight* con);
Connection(Neuron *n_in, Neuron *n_out, ConnectionWeight* con, bool delete_weight = true);
/**
* Destructor, deletes the 'con' object
......
......@@ -58,7 +58,7 @@ public:
/**
*
*/
~ConnectionWeight();
virtual ~ConnectionWeight();
/**
*
......
......@@ -15,8 +15,224 @@ NeuralNetwork::NeuralNetwork() {
this->connection_weights = new std::vector<double>(0);
this->connection_weights->reserve(0);
this->delete_weights = true;
}
NeuralNetwork* NeuralNetwork::get_subnet(std::vector<size_t> &input_neuron_indices, std::vector<size_t> &output_neuron_indices){
NeuralNetwork *output_net = nullptr;
Neuron * active_neuron, * target_neuron;
size_t n = this->neurons->size();
bool *part_of_subnetwork = new bool[n];
std::fill(part_of_subnetwork, part_of_subnetwork + n, false);
bool *is_reachable_from_source = new bool[n];
bool *is_reachable_from_destination = new bool[n];
std::fill(is_reachable_from_source, is_reachable_from_source + n, false);
std::fill(is_reachable_from_destination, is_reachable_from_destination + n, false);
bool *visited_neurons = new bool[n];
std::fill(visited_neurons, visited_neurons + n, false);
size_t active_set_size[2];
active_set_size[0] = 0;
active_set_size[1] = 0;
size_t * active_neuron_set = new size_t[2 * n];
size_t idx1 = 0, idx2 = 1;
/* MAPPING BETWEEN NEURONS AND THEIR INDICES */
size_t idx = 0, idx_target;
for(Neuron *v: *this->neurons){
v->set_idx( idx );
idx++;
}
/* INITIAL STATE FOR THE FORWARD PASS */
for(size_t i: input_neuron_indices ){
if( i < 0 || i >= n){
//invalid index
continue;
}
active_neuron_set[idx1 * n + active_set_size[idx1]] = i;
active_set_size[idx1]++;
visited_neurons[i] = true;
}
/* FORWARD PASS */
while(active_set_size[idx1] > 0){
//we iterate through the active neurons and propagate the signal
for(int i = 0; i < active_set_size[idx1]; ++i){
idx = active_neuron_set[i];
is_reachable_from_source[ idx ] = true;
active_neuron = this->neurons->at( idx );
for(Connection* connection: *(active_neuron->get_connections_out())){
target_neuron = connection->get_neuron_out( );
idx_target = target_neuron->get_idx( );
if( visited_neurons[idx_target] ){
//this neuron was already analyzed
continue;
}
visited_neurons[idx_target] = true;
active_neuron_set[active_set_size[idx2] + n * idx2] = idx_target;
active_set_size[idx2]++;
}
}
idx1 = idx2;
idx2 = (idx1 + 1) % 2;
active_set_size[idx2] = 0;
}
/* INITIAL STATE FOR THE FORWARD PASS */
active_set_size[0] = active_set_size[1] = 0;
std::fill(visited_neurons, visited_neurons + n, false);
for(size_t i: output_neuron_indices ){
if( i < 0 || i >= n){
//invalid index
continue;
}
active_neuron_set[idx1 * n + active_set_size[idx1]] = i;
active_set_size[idx1]++;
visited_neurons[i] = true;
}
/* BACKWARD PASS */
size_t n_new_neurons = 0;
while(active_set_size[idx1] > 0){
//we iterate through the active neurons and propagate the signal
for(int i = 0; i < active_set_size[idx1]; ++i){
idx = active_neuron_set[i];
is_reachable_from_destination[ idx ] = true;
active_neuron = this->neurons->at( idx );
if(is_reachable_from_source[ idx ]){
n_new_neurons++;
}
for(Connection* connection: *(active_neuron->get_connections_in())){
target_neuron = connection->get_neuron_in( );
idx_target = target_neuron->get_idx( );
if( visited_neurons[idx_target] ){
//this neuron was already analyzed