Commit 406953b0 authored by Michal Kravcenko's avatar Michal Kravcenko

- Added preliminary connection classes with neural network class able to...

- Added preliminary connection classes with neural network class able to evaluate inputs via the feed-forward method.
- Added a test case for validating feed-forward capabilities of our networks
parent 02707da1
......@@ -5,32 +5,32 @@
<usages-collector id="statistics.file.extensions.open">
<counts>
<entry key="Makefile" value="1" />
<entry key="cpp" value="37" />
<entry key="cpp" value="58" />
<entry key="f90" value="4" />
<entry key="h" value="45" />
<entry key="txt" value="4" />
<entry key="h" value="71" />
<entry key="txt" value="7" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.types.open">
<counts>
<entry key="CMakeLists.txt" value="4" />
<entry key="ObjectiveC" value="82" />
<entry key="CMakeLists.txt" value="7" />
<entry key="ObjectiveC" value="129" />
<entry key="PLAIN_TEXT" value="5" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.extensions.edit">
<counts>
<entry key="cpp" value="2761" />
<entry key="h" value="5108" />
<entry key="txt" value="451" />
<entry key="cpp" value="6278" />
<entry key="h" value="7184" />
<entry key="txt" value="704" />
</counts>
</usages-collector>
<usages-collector id="statistics.file.types.edit">
<counts>
<entry key="CMakeLists.txt" value="112" />
<entry key="Doxygen file" value="70" />
<entry key="ObjectiveC" value="7799" />
<entry key="PLAIN_TEXT" value="339" />
<entry key="CMakeLists.txt" value="139" />
<entry key="Doxygen file" value="104" />
<entry key="ObjectiveC" value="13358" />
<entry key="PLAIN_TEXT" value="565" />
</counts>
</usages-collector>
</session>
......
add_library(neuron SHARED Neuron/Neuron.cpp Neuron/Neuron.h Neuron/NeuronBinary.cpp Neuron/NeuronBinary.h Neuron/NeuronLinear.cpp Neuron/NeuronLinear.h Neuron/NeuronLogistic.cpp Neuron/NeuronLogistic.h Neuron/NeuronTanh.cpp Neuron/NeuronTanh.h constants.h NetConnection/Connection.cpp NetConnection/Connection.h Network/NeuralNetwork.cpp Network/NeuralNetwork.h Neuron/NeuronNeuralNet.cpp Neuron/NeuronNeuralNet.h)
add_library(neuron SHARED Neuron/Neuron.cpp Neuron/Neuron.h Neuron/NeuronBinary.cpp Neuron/NeuronBinary.h Neuron/NeuronLinear.cpp Neuron/NeuronLinear.h Neuron/NeuronLogistic.cpp Neuron/NeuronLogistic.h Neuron/NeuronTanh.cpp Neuron/NeuronTanh.h constants.h NetConnection/Connection.cpp NetConnection/Connection.h Network/NeuralNetwork.cpp Network/NeuralNetwork.h Neuron/NeuronNeuralNet.cpp Neuron/NeuronNeuralNet.h NetConnection/ConnectionWeight.cpp NetConnection/ConnectionWeight.h NetConnection/ConnectionWeightIdentity.cpp NetConnection/ConnectionWeightIdentity.h)
add_executable(test_cases main.cpp)
target_link_libraries(test_cases neuron)
\ No newline at end of file
......@@ -7,20 +7,22 @@
#include "Connection.h"
Connection::Connection(Neuron *n_in, Neuron *n_out, double edge_weight) {
Connection::Connection(Neuron *n_in, Neuron *n_out, ConnectionWeight* con) {
this->neuron_in = n_in;
this->neuron_out = n_out;
this->weight = edge_weight;
this->con = con;
}
//Connection::~Connection() {
//
//}
void Connection::adjust_weight(double value) {
this->weight += value;
void Connection::adjust_weights(double* values) {
this->con->adjust_weights(values);
}
Neuron* Connection::get_neuron_in() {
return this->neuron_in;
}
......@@ -29,14 +31,14 @@ Neuron* Connection::get_neuron_out() {
return this->neuron_out;
}
double Connection::get_weight() {
return this->weight;
}
//double Connection::get_weight() {
// return this->weight;
//}
void Connection::pass_signal() {
this->neuron_out->adjust_potential(this->neuron_in->get_state() * this->weight);
this->neuron_out->adjust_potential(this->neuron_in->get_state() * this->con->eval());
}
void Connection::set_weight(double value) {
this->weight = value;
void Connection::set_weights(double *values) {
this->con->set_weights(values);
}
......@@ -9,27 +9,31 @@
#define INC_4NEURO_CONNECTION_H
#include "../Neuron/Neuron.h"
#include "ConnectionWeight.h"
class Neuron;
class ConnectionWeight;
/**
*
*/
class Connection {
private:
/**
*
*/
Neuron *neuron_in = nullptr;
ConnectionWeight *con = nullptr;
/**
*
*/
Neuron *neuron_out = nullptr;
Neuron *neuron_in = nullptr;
/**
*
*/
double weight = 0.0;
Neuron *neuron_out = nullptr;
//TODO pridat gradient
......@@ -39,9 +43,8 @@ public:
*
* @param[in] n_in
* @param[in] n_out
* @param[in] edge_weight
*/
Connection(Neuron *n_in, Neuron *n_out, double edge_weight = 1.0);
Connection(Neuron *n_in, Neuron *n_out, ConnectionWeight* con);
// Connection(Neuron *n_in, Neuron *n_out, Connection* ref_con);
......@@ -52,21 +55,21 @@ public:
/**
*
* @param[in] value
* @param[in] values
*/
void adjust_weight(double value);
void adjust_weights(double *values);
/**
*
* @param[in] value
* @param[in] values
*/
void set_weight(double value);
void set_weights(double *values);
/**
*
* @return
*/
double get_weight();
// /**
// *
// * @return
// */
// double get_weight();
/**
......
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 14.6.18 -
*/
#include "ConnectionWeight.h"
ConnectionWeight::ConnectionWeight() {
}
ConnectionWeight::ConnectionWeight(int param_count, std::function<double(double **, int)> f) {
this->param_ptrs = new double*[param_count];
this->n_params = param_count;
this->weight_function = f;
}
ConnectionWeight::~ConnectionWeight() {
if(this->param_ptrs){
delete [] this->param_ptrs;
this->param_ptrs = nullptr;
}
}
void ConnectionWeight::adjust_weights(double *values) {
for(int i = 0; i < this->n_params; ++i){
(*this->param_ptrs[i]) += values[i];
}
}
void ConnectionWeight::set_weights(double *values) {
for(int i = 0; i < this->n_params; ++i){
(*this->param_ptrs[i]) = values[i];
}
}
void ConnectionWeight::SetParamPointer(double **param_ptr) {
for(int i = 0; i < this->n_params; ++i){
this->param_ptrs[i] = param_ptr[i];
}
}
void ConnectionWeight::SetParamPointer(double *param_ptr, int idx) {
this->param_ptrs[idx] = param_ptr;
}
double ConnectionWeight::eval() {
return this->weight_function(this->param_ptrs, this->n_params);
}
\ No newline at end of file
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 14.6.18 -
*/
#ifndef INC_4NEURO_CONNECTIONWEIGHT_H
#define INC_4NEURO_CONNECTIONWEIGHT_H
#include <functional>
class ConnectionWeight {
protected:
/**
*
*/
double ** param_ptrs = nullptr;
/**
*
*/
int n_params = 0;
/**
*
*/
std::function<double(double **, int)> weight_function;
public:
/**
*
*/
ConnectionWeight();
/**
*
* @param param_count
* @param f
*/
ConnectionWeight(int param_count, std::function<double(double **, int)> f);
/**
*
* @param param_ptr
* @param idx
*/
void SetParamPointer(double *param_ptr, int idx);
/**
*
* @param param_ptr
*/
void SetParamPointer(double **param_ptr);
/**
*
*/
~ConnectionWeight();
/**
*
* @return
*/
virtual double eval();
/**
*
* @param values
*/
void set_weights(double *values);
/**
*
* @param values
*/
void adjust_weights(double *values);
};
#endif //INC_4NEURO_CONNECTIONWEIGHT_H
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 14.6.18 -
*/
#include "ConnectionWeightIdentity.h"
ConnectionWeightIdentity::ConnectionWeightIdentity() {
this->n_params = 1;
this->param_ptrs = new double*[1];
}
double ConnectionWeightIdentity::eval() {
return (*this->param_ptrs[0]);
}
\ No newline at end of file
/**
* DESCRIPTION OF THE FILE
*
* @author Michal Kravčenko
* @date 14.6.18 -
*/
#ifndef INC_4NEURO_CONNECTIONWEIGHTIDENTITY_H
#define INC_4NEURO_CONNECTIONWEIGHTIDENTITY_H
#include "ConnectionWeight.h"
class ConnectionWeight;
/**
*
*/
class ConnectionWeightIdentity:public ConnectionWeight {
private:
public:
ConnectionWeightIdentity();
double eval() override;
};
#endif //INC_4NEURO_CONNECTIONWEIGHTIDENTITY_H
......@@ -6,3 +6,149 @@
*/
#include "NeuralNetwork.h"
NeuralNetwork::NeuralNetwork() {
this->neurons = new std::vector<Neuron*>(0);
}
NeuralNetwork::~NeuralNetwork() {
if(this->neurons){
delete this->neurons;
this->neurons = nullptr;
}
if(this->output_neurons){
delete this->output_neurons;
this->output_neurons = nullptr;
}
if(this->input_neurons){
delete this->input_neurons;
this->input_neurons = nullptr;
}
if(this->active_eval_set){
delete this->active_eval_set;
this->active_eval_set = nullptr;
}
}
void NeuralNetwork::add_neuron(Neuron *n) {
this->neurons->push_back(n);
this->in_out_determined = false;
}
void NeuralNetwork::determine_inputs_outputs() {
if(this->output_neurons){
delete this->output_neurons;
}
if(this->input_neurons){
delete this->input_neurons;
}
this->output_neurons = new std::vector<Neuron*>(0);
this->input_neurons = new std::vector<Neuron*>(0);
if(this->active_eval_set == nullptr){
this->active_eval_set = new std::vector<Neuron*>(this->neurons->size() * 2);
}
else{
this->active_eval_set->resize(this->neurons->size() * 2);
}
for(Neuron* neuron: *this->neurons){
if(neuron->get_connections_out()->empty()){
//this neuron has no outgoing connections, it is the output neuron
this->output_neurons->push_back(neuron);
}
else if(neuron->get_connections_in()->empty()){
//this neuron has no incoming connections, it is the input neuron
this->input_neurons->push_back(neuron);
}
}
this->n_inputs = (int)this->input_neurons->size();
this->n_outputs = (int)this->output_neurons->size();
this->in_out_determined = true;
}
void NeuralNetwork::eval_single(std::vector<double> &input, std::vector<double> &output) {
if(!this->in_out_determined){
this->determine_inputs_outputs();
}
if(this->n_inputs != input.size()){
printf("Error, input size != Network input size\n");
return;
}
if(this->n_outputs != output.size()){
printf("Error, output size != Network output size\n");
return;
}
std::fill(output.begin(), output.end(), 0.0);
//reset of the potentials
for(Neuron* neuron: *this->neurons){
neuron->set_potential(0.0);
neuron->set_saturation_in(0);
neuron->set_saturation_out(0);
}
int active_set_size[2];
active_set_size[0] = 0;
active_set_size[1] = 0;
int idx1 = 0, idx2 = 1;
active_set_size[0] = this->n_inputs;
int i = 0;
auto n = this->neurons->size();
for(Neuron* neuron: *this->input_neurons){
this->active_eval_set->at(i) = neuron;
neuron->set_potential(input[i]);
++i;
}
Neuron* active_neuron;
Neuron* target_neuron;
while(active_set_size[idx1] > 0){
//we iterate through the active neurons and propagate the signal
for(i = 0; i < active_set_size[idx1]; ++i){
active_neuron = this->active_eval_set->at(i + n * idx1);
active_neuron->activate();
for(Connection* connection: *(active_neuron->get_connections_out())){
connection->pass_signal();
target_neuron = connection->get_neuron_out();
target_neuron->adjust_saturation_in(1);
if(target_neuron->is_saturated_in()){
this->active_eval_set->at(active_set_size[idx2] + n * idx2) = target_neuron;
active_set_size[idx2]++;
}
}
}
idx1 = idx2;
idx2 = (idx1 + 1) % 2;
active_set_size[idx2] = 0;
}
i = 0;
for(Neuron* neuron: *this->output_neurons){
output[i] = neuron->get_state();
++i;
}
}
\ No newline at end of file
......@@ -5,10 +5,17 @@
* @date 13.6.18 -
*/
//TODO pouvazovat o pridani indexu k neuronum, abychom meli urcitou kontrolu nad poradim vstupu a vystupu?
#ifndef INC_4NEURO_NEURALNETWORK_H
#define INC_4NEURO_NEURALNETWORK_H
#include <vector>
#include "../Neuron/Neuron.h"
enum NET_TYPE{GENERAL};
/**
*
*/
......@@ -19,21 +26,72 @@ private:
*/
NET_TYPE network_type = GENERAL;
/**
*
*/
std::vector<Neuron*> *neurons = nullptr;
/**
*
*/
std::vector<Neuron*>* input_neurons = nullptr;
/**
*
*/
std::vector<Neuron*>* output_neurons = nullptr;
/**
*
*/
int n_inputs = -1;
/**
*
*/
int n_outputs = -1;
/**
*
*/
bool in_out_determined = false;
std::vector<Neuron*>* active_eval_set = nullptr;
/**
*
*/
int n_neurons = 0;
void determine_inputs_outputs();
public:
/**
*
* @param input
* @param expected_output
* @return
*/
//double get_error(DataSet &input, DataSet &expected_output);
NeuralNetwork();
/**
*
*/
~NeuralNetwork();
/**
*
* @param[in] input
* @param[in,out] output
*/
void eval_single(std::vector<double> &input, std::vector<double> &output);
/**
*
* @param n
*/
void add_neuron(Neuron* n);
};
......
......@@ -8,11 +8,6 @@ Neuron::~Neuron() {
}
if(this->edges_out){
for(auto& i: *this->edges_out){
delete i;
}
delete this->edges_out;
this->edges_out = nullptr;
}
......@@ -23,6 +18,40 @@ Neuron::~Neuron() {
}
}
void Neuron::set_saturation_in(int value) {
this->n_saturated_connections_in = value;
}
void Neuron::adjust_saturation_in(int value) {
this->n_saturated_connections_in += value;
}
bool Neuron::is_saturated_in() {
if(this->n_saturated_connections_in == this->edges_in->size()){
return true;
}
return false;
}
void Neuron::set_saturation_out(int value) {
this->n_saturated_connections_out = value;
}
void Neuron::adjust_saturation_out(int value) {
this->n_saturated_connections_out += value;
}
bool Neuron::is_saturated_out() {
if(this->n_saturated_connections_out == this->edges_out->size()){
return true;
}
return false;
}
void Neuron::adjust_potential(double input_signal) {
this->potential += input_signal;
}
......
......@@ -42,6 +42,16 @@ protected:
*/
int n_activation_function_parameters = 0;
/**
* Keeps track of the number of saturated INCOMING connections
*/
int n_saturated_connections_in = 0;
/**
* Keeps track of the number of saturated OUTGOING connections
*/
int n_saturated_connections_out = 0;
/**
* A pointer to a vector containing pointers to incoming connections
*/
......@@ -66,6 +76,42 @@ public:
*/
virtual void activate( ) = 0;
/**
* Sets the number of saturated INPUT connections to the prescribed value
* @param[in] value The number of saturated INCOMING connections
*/
virtual void set_saturation_in(int value) final;
/**
* Increases the saturation counter of the INCOMING connections by the specified amount
* @param value Amount to be added to the counter
*/
virtual void adjust_saturation_in(int value) final;
/**
* Returns true if the neuron is saturated via the INCOMING connections
* @return true/false
*/
virtual bool is_saturated_in() final;
/**
* Returns true if the neuron is saturated via the OUTGOING connections
* @return true/false
*/
virtual bool is_saturated_out() final;
/**
* Sets the number of saturated OUTPUT connections to the prescribed value
* @param[in] value The number of saturated OUTGOING connections
*/
virtual void set_saturation_out(int value) final;
/**
* Increases the saturation counter of the OUTGOING connections by the specified amount
* @param value Amount to be added to the counter
*/
virtual void adjust_saturation_out(int value) final;
/**
* Adds the input signal value to the current potential
* @param[in] input_signal Input value
......