neuron.cpp
#include <iostream> #include <cassert> #include "neuron.h" #include "connection.h" Neuron::Neuron() { #ifdef DEBUG std::cout << "Neuron::Neuron" << std::endl; #endif index = -1; gradient = 0; value = 0; connections_in.reserve(10); connections_out.reserve(10); pActivationX tmp(new Activation()); //pActivationX tmp(new Activation(ACTIVATION_SQRT)); this->activation = tmp; //activation_type = ACTIVATION_SIGMOID; randomizeValue(); } bool Neuron::operator==(Neuron& rhs) const { //cout << "operator overloaded == " << rhs.name; if (this->index==rhs.index) //if (*this == rhs) return true; return false; } double Neuron::getGradient(void) { #ifdef DEBUG std::cout << "Neuron::getGradient" << std::endl; #endif return gradient; } void Neuron::setGradient(const double& gradient) { #ifdef DEBUG std::cout << "Neuron::setGradient" << std::endl; #endif this->gradient = gradient; } int Neuron::getIndex(void) { #ifdef DEBUG std::cout << "Neuron::getIndex" << std::endl; #endif return index; } void Neuron::setIndex(const int& index) { #ifdef DEBUG std::cout << "Neuron::setIndex" << std::endl; #endif this->index = index; } unsigned int Neuron::getSizeIn(void) { #ifdef DEBUG std::cout << "Neuron::getSizeIn" << std::endl; #endif return connections_in.size(); } unsigned int Neuron::getSizeOut(void) { #ifdef DEBUG std::cout << "Neuron::getSizeOut" << std::endl; #endif return connections_out.size(); } double Neuron::getValue(void) { #ifdef DEBUG std::cout << "Neuron::getValue" << std::endl; #endif return value; } void Neuron::setValue(const double& v) { #ifdef DEBUG std::cout << "Neuron::setValue" << std::endl; #endif value = v; } void Neuron::addConnectionIn(const pConnectionX& c) { #ifdef DEBUG std::cout << "Neuron::addConnectionIn" << std::endl; #endif connections_in.push_back(c); //index++; } //void Neuron::addConnectionOut(const shared_ptr<Connection>& c) void Neuron::addConnectionOut(const pConnectionX& c) { #ifdef DEBUG std::cout << "Neuron::addConnectionOut" << std::endl; #endif connections_out.push_back(c); //index++; } // Returns a specific input connection. pConnectionX &Neuron::getConnectionIn(const unsigned int& idx) { #ifdef DEBUG std::cout << "Neuron::getConnectionIn" << std::endl; #endif assert(connections_in.size() >= idx); return connections_in[idx]; } // Returns a specific output connection. pConnectionX &Neuron::getConnectionOut(const unsigned int& idx) { #ifdef DEBUG std::cout << "Neuron::getConnectionOut" << std::endl; #endif assert(connections_out.size() >= idx); return connections_out[idx]; } // Remove all connections with a value below the indicated threshold. // // TODO: Should we consider abs value? void Neuron::pruneConnectionIn(const double& threshold) { for (unsigned i = connections_in.size()-1; i > 0; i--) { if (connections_in[i]->getWeight() < threshold) { // TODO. Do we need to also remove the "From" and "To" elements of Neurons manually or will these auto remove? // TODO. Does this retain the actual Connection, which potentially we should potentially delete if not used? connections_in.erase(connections_in.begin() + i); } } } // Remove all connections with a value below the indicated threshold. // // TODO: Should we consider abs value? void Neuron::pruneConnectionOut(const double& threshold) { for (unsigned i = connections_out.size()-1; i > 0; i--) { if (connections_out[i]->getWeight() < threshold) { // TODO. Do we need to also remove the "From" and "To" elements of Neurons manually or will these auto remove? // TODO. Does this retain the actual Connection, which potentially we should potentially delete if not used? connections_out.erase(connections_out.begin() + i); } } } void Neuron::removeConnectionIn(const unsigned int& idx) { #ifdef DEBUG std::cout << "Neuron::removeConnectionIn" << std::endl; #endif assert(connections_in.size() >= idx); //for (unsigned i = 0; i < connections_in.size(); i++) for (unsigned i = connections_in.size()-1; i > 0; i--) { if (connections_in[i]->getIndex() == idx) { connections_in.erase(connections_in.begin() + i); return; } } } void Neuron::removeConnectionOut(const unsigned int& idx) { #ifdef DEBUG std::cout << "Neuron::removeConnectionOut" << std::endl; #endif assert(connections_out.size() >= idx); //for (unsigned i = 0; i < connections_out.size(); i++) for (unsigned i = connections_out.size()-1; i > 0; i--) { if (connections_out[i]->getIndex() == idx) { connections_out.erase(connections_out.begin() + i); return; } } } double Neuron::randomizeValue(void) { #ifdef DEBUG std::cout << "Neuron::randomizeValue" << std::endl; #endif value = rand() / double(RAND_MAX); return value; } pActivationX &Neuron::getActivation(void) { return activation; } Activation_Types Neuron::getActivationType() { return activation->getActivationType(); } void Neuron::setActivationType(Activation_Types _activation_type) { //activation_type = _activation_type; activation->setActivationType(_activation_type); } /* // Return random double between -0.5 and +0.5. double Neuron::randf() { #ifdef DEBUG std::cout << "Neuron::randf" << std::endl; #endif double r = ((double)rand()) / double(RAND_MAX); return r - 0.5; } */ // Returns a value between 0.0 and 1.0. double Neuron::sigmoid(const double& weightedSum) { #ifdef DEBUG std::cout << "Neuron::sigmoid" << std::endl; #endif return 1.0 / double((1.0 + exp(-weightedSum))); } double Neuron::sigmoid_derivative(const double& x) { #ifdef DEBUG std::cout << "Neuron::sigmoid_derivative" << std::endl; #endif return sigmoid(x) * (1.0 - sigmoid(x)); } double Neuron::sigmoidX(double x) { #ifdef DEBUG std::cout << "Neuron::sigmoidX" << std::endl; #endif if (x < -45.0) return 0.0; else if (x > 45.0) return 1.0; else return 1.0 / (1.0 + exp(-x)); } // Returns a value between -1.0 and +1.0. double Neuron::hyperTanFunction(double& x) { #ifdef DEBUG std::cout << "Neuron::hyperTanFunction" << std::endl; #endif if (x < -10.0) return -1.0; else if (x > 10.0) return 1.0; else return tanh(x); } double Neuron::tanh_derivative(const double& x) { #ifdef DEBUG std::cout << "Neuron::tanh_derivative" << std::endl; #endif return (1.0 - tanh(x)) * (1.0 + tanh(x)); } /* double Neuron::transferFunction(double x) { // tanh - output range [-1.0..1.0] return tanh(x); } double Neuron::transferFunctionDerivative(double x) { // tanh derivative return 1.0 - x * x; } */ void Neuron::printOutput(void) { #ifdef DEBUG std::cout << "Neuron::printOutput" << std::endl; #endif std::cout << "Neuron[" << index << "] = " << value << " . It has " << connections_in.size() << " Connections-In, and " << connections_out.size() << " Connections-Out" << std::endl; for (unsigned int i = 0; i<connections_in.size(); i++) { if (!connections_in[i]) continue; std::cout << " Connection-In[" << i << "] w=" << connections_in[i]->getWeight() << ", d=" << connections_in[i]->getDeltaWeight() << std::endl; } for (unsigned int i = 0; i<connections_out.size(); i++) { if (!connections_out[i]) continue; std::cout << " Connection-Out[" << i << "] w=" << connections_out[i]->getWeight() << ", d=" << connections_out[i]->getDeltaWeight() << std::endl; } }