From 04d751a222725304dc26a72a4be0b0d251605f27 Mon Sep 17 00:00:00 2001
From: mrovma <martin.mrovec@vsb.cz>
Date: Thu, 9 May 2019 16:59:12 +0200
Subject: [PATCH] ENH: Added new neurons - Absolute, LinearSaturated

---
 include/4neuro.h                              |  2 +
 src/CMakeLists.txt                            |  2 +
 src/DataSet/DataSet.cpp                       | 12 ++++
 src/DataSet/DataSet.h                         |  6 ++
 src/Neuron/NeuronAbsolute.cpp                 | 39 +++++++++++
 src/Neuron/NeuronAbsolute.h                   | 70 +++++++++++++++++++
 src/Neuron/NeuronAbsoluteSerialization.h      | 48 +++++++++++++
 src/Neuron/NeuronLinearSaturated.cpp          | 64 +++++++++++++++++
 src/Neuron/NeuronLinearSaturated.h            | 36 ++++++++++
 .../NeuronLinearSaturatedSerialization.h      | 49 +++++++++++++
 10 files changed, 328 insertions(+)
 create mode 100644 src/Neuron/NeuronAbsolute.cpp
 create mode 100644 src/Neuron/NeuronAbsolute.h
 create mode 100644 src/Neuron/NeuronAbsoluteSerialization.h
 create mode 100644 src/Neuron/NeuronLinearSaturated.cpp
 create mode 100644 src/Neuron/NeuronLinearSaturated.h
 create mode 100644 src/Neuron/NeuronLinearSaturatedSerialization.h

diff --git a/include/4neuro.h b/include/4neuro.h
index 6f076b20..731b1bb0 100644
--- a/include/4neuro.h
+++ b/include/4neuro.h
@@ -12,9 +12,11 @@
 #include "../src/Neuron/NeuronLinear.h"
 #include "../src/Neuron/NeuronLogistic.h"
 #include "../src/Neuron/NeuronBiased.h"
+#include "../src/Neuron/NeuronAbsolute.h"
 #include "../src/Neuron/NeuronBinaryBiased.h"
 #include "../src/Neuron/NeuronFilter.h"
 #include "../src/Neuron/NeuronRectifier.h"
+#include "../src/Neuron/NeuronLinearSaturated.h"
 #include "../src/Solvers/DESolver.h"
 #include "../src/ErrorFunction/ErrorFunctions.h"
 #include "../src/LearningMethods/ParticleSwarm.h"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d9d2f75c..f8f6b9b6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -87,10 +87,12 @@ IF("${BUILD_LIB}" STREQUAL "yes")
         Neuron/NeuronBinary.cpp
         Neuron/NeuronConstant.cpp
         Neuron/NeuronLinear.cpp
+        Neuron/NeuronAbsolute.cpp
         Neuron/NeuronLogistic.cpp
         Neuron/NeuronRectifier.cpp
         Neuron/NeuronFilter.cpp
         Neuron/NeuronBinaryBiased.cpp
+        Neuron/NeuronLinearSaturated.cpp
         Network/NeuralNetwork.cpp
         Network/NeuralNetworkSum.cpp
         NetConnection/ConnectionFunctionGeneral.cpp
diff --git a/src/DataSet/DataSet.cpp b/src/DataSet/DataSet.cpp
index a87d9ab4..425ccb10 100644
--- a/src/DataSet/DataSet.cpp
+++ b/src/DataSet/DataSet.cpp
@@ -487,4 +487,16 @@ namespace lib4neuro {
             return newData;
         }
     }
+	
+	void DataSet::add_zero_output_columns(size_t n_columns)
+	{
+		for (size_t i = 0; i < this->n_elements; i++)
+		{
+			for (size_t j = 0; j < n_columns; j++)
+			{
+				this->data.at(i).second.push_back(0);
+			}
+		}
+		this->output_dim += n_columns;
+	}
 }
diff --git a/src/DataSet/DataSet.h b/src/DataSet/DataSet.h
index aa850d8d..f6be02b0 100644
--- a/src/DataSet/DataSet.h
+++ b/src/DataSet/DataSet.h
@@ -308,6 +308,12 @@ namespace lib4neuro {
          */
         LIB4NEURO_API std::vector<std::pair<std::vector<double>, std::vector<double>>>
         get_random_data_batch(size_t max);
+
+		/**
+		 * Adds a new output column filled with zeros 
+		 * @param n_columns Number of columns to be inserted
+		 */
+		LIB4NEURO_API void add_zero_output_columns(size_t n_columns);
     };
 }
 #endif //INC_4NEURO_DATASET_H
diff --git a/src/Neuron/NeuronAbsolute.cpp b/src/Neuron/NeuronAbsolute.cpp
new file mode 100644
index 00000000..2e54269f
--- /dev/null
+++ b/src/Neuron/NeuronAbsolute.cpp
@@ -0,0 +1,39 @@
+
+#include <boost/serialization/export.hpp>
+
+#include "NeuronAbsolute.h"
+#include "NeuronConstant.h"
+#include "NeuronSerialization.h"
+#include "NeuronAbsoluteSerialization.h"
+#include "exceptions.h"
+
+BOOST_CLASS_EXPORT_IMPLEMENT(lib4neuro::NeuronAbsolute);
+
+namespace lib4neuro {
+	NeuronAbsolute::NeuronAbsolute() {}
+
+	double NeuronAbsolute::activate(double x,
+		double b) {
+		//this->activation_val = abs(x + b);
+		this->activation_val = pow((x + b),2);
+		return this->activation_val;
+	}
+
+	double NeuronAbsolute::activation_function_eval_derivative_bias(double x,
+		double b) {
+		//return (x + b > 0)? 1.0 : -1.0;
+		return 2 * (x + b);
+	}
+
+	double NeuronAbsolute::activation_function_eval_derivative(double x,
+		double b) {
+		//return (x + b > 0) ? 1.0 : -1.0;
+		return 2 * (x + b);
+	}
+
+
+	Neuron* NeuronAbsolute::get_derivative() {//TODO: implement this function correctly
+		THROW_NOT_IMPLEMENTED_ERROR("");
+	}
+
+}
\ No newline at end of file
diff --git a/src/Neuron/NeuronAbsolute.h b/src/Neuron/NeuronAbsolute.h
new file mode 100644
index 00000000..47665409
--- /dev/null
+++ b/src/Neuron/NeuronAbsolute.h
@@ -0,0 +1,70 @@
+                                         /**
+* DESCRIPTION OF THE CLASS
+*
+* @author Martin Beseda
+* @author Martin Mrovec
+* @author Michal KravÄŤenko
+* @date 2017 - 2018
+*/
+
+#ifndef INC_4NEURO_NEURONABSOLUTE_H
+#define INC_4NEURO_NEURONABSOLUTE_H
+
+#include "Neuron.h"
+
+namespace lib4neuro {
+
+	/**
+	* Linear neuron class - uses activation function in the form f(x)=a*x + b,
+	* 'x' being the neuron's potential
+	*/
+	class NeuronAbsolute : public NeuronDifferentiable {
+
+	public:
+
+		/**
+		* Struct used to access private properties from
+		* the serialization function
+		*/
+		struct access;
+
+		/**
+		* Constructs the object of the Linear neuron with activation function
+		* f(x) = x + b
+		* @param[in] b Bias
+		*/
+		LIB4NEURO_API explicit NeuronAbsolute();
+
+		/**
+		* Evaluates 'x + b' and stores the result into the 'state' property
+		*/
+		LIB4NEURO_API double activate(double x,
+			double b) override;
+
+		/**
+		* Calculates the partial derivative of the activation function
+		* f(x) = x + b at point x
+		* @return Partial derivative of the activation function according to the
+		* 'bias' parameter. Returns 1.0
+		*/
+		LIB4NEURO_API double activation_function_eval_derivative_bias(double x,
+			double b) override;
+
+		/**
+		* Calculates d/dx of (x + b) at point x
+		* @return 1.0
+		*/
+		LIB4NEURO_API double activation_function_eval_derivative(double x,
+			double b) override;
+
+		/**
+		* Returns a pointer to a Neuron with derivative as its activation function
+		* @return
+		*/
+		LIB4NEURO_API Neuron* get_derivative() override;
+
+	};
+
+}
+
+#endif //INC_4NEURO_NeuronAbsolute_H
diff --git a/src/Neuron/NeuronAbsoluteSerialization.h b/src/Neuron/NeuronAbsoluteSerialization.h
new file mode 100644
index 00000000..74db6d8a
--- /dev/null
+++ b/src/Neuron/NeuronAbsoluteSerialization.h
@@ -0,0 +1,48 @@
+
+#ifndef LIB4NEURO_NEURONABSOLUTESERIALIZATION_H
+#define LIB4NEURO_NEURONABSOLUTESERIALIZATION_H
+
+#include <boost/serialization/base_object.hpp>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/serialization/export.hpp>
+
+#include "NeuronAbsolute.h"
+#include "NeuronSerialization.h"
+
+BOOST_CLASS_EXPORT_KEY(lib4neuro::NeuronAbsolute);
+
+namespace lib4neuro {
+    struct NeuronAbsolute::access {
+        template<class Archive>
+        static void serialize(Archive& ar,
+                              NeuronAbsolute& n,
+                              const unsigned int version) {
+            ar & boost::serialization::base_object<Neuron>(n);
+        }
+    };
+}
+
+namespace boost {
+    namespace serialization {
+
+        /**
+         * Serialization function
+         * @tparam Archive Boost library template
+         * @param ar Boost parameter - filled automatically during serialization!
+         * @param n NeuronAbsolute instance
+         * @param version Boost parameter - filled automatically during serialization!
+         */
+        template<class Archive>
+        void serialize(Archive& ar,
+                       lib4neuro::NeuronAbsolute& n,
+                       const unsigned int version) {
+            lib4neuro::NeuronAbsolute::access::serialize(ar,
+                                                       n,
+                                                       version);
+        }
+
+    } // namespace serialization
+} // namespace boost
+
+#endif //LIB4NEURO_NeuronAbsoluteSERIALIZATION_H
diff --git a/src/Neuron/NeuronLinearSaturated.cpp b/src/Neuron/NeuronLinearSaturated.cpp
new file mode 100644
index 00000000..4904b682
--- /dev/null
+++ b/src/Neuron/NeuronLinearSaturated.cpp
@@ -0,0 +1,64 @@
+
+#include <boost/serialization/export.hpp>
+#include <iostream>
+#include "NeuronLinearSaturated.h"
+#include "NeuronBinary.h"
+#include "NeuronSerialization.h"
+#include "NeuronLinearSaturatedSerialization.h"
+#include "exceptions.h"
+
+BOOST_CLASS_EXPORT_IMPLEMENT(lib4neuro::NeuronLinearSaturated);
+
+namespace lib4neuro {
+    NeuronLinearSaturated::NeuronLinearSaturated(double saturation_point) {
+		this->saturation_point = saturation_point;
+	}
+
+    double NeuronLinearSaturated::activate(double x,
+                                     double b) {
+		if (x + b < 0) {
+			this->activation_val = 0.0;
+		}
+		else if (x + b > this->saturation_point) {
+			this->activation_val = this->saturation_point;
+		}
+		else {
+			this->activation_val = x + b;
+		}
+        return this->activation_val;
+    }
+
+    double NeuronLinearSaturated::activation_function_eval_derivative_bias(double x,
+                                                                		 double b) {
+        // f'(0) = 0 for the purposes of training
+		if (x + b < 0) {
+			return 0.0;
+		}
+		else if (x + b > this->saturation_point) {
+			return 0.0;
+		}
+		else {
+			return 1.0;
+		}
+    }
+
+    double NeuronLinearSaturated::activation_function_eval_derivative(double x,
+                                                                double b) {
+        // f'(0) = 0 for the purposes of training
+		if (x + b < 0) {
+			return 0.0;
+		}
+		else if (x + b > this->saturation_point) {
+			return 0.0;
+		}
+		else {
+			return 1.0;
+		}
+    }
+
+    Neuron* NeuronLinearSaturated::get_derivative() {
+        THROW_NOT_IMPLEMENTED_ERROR("");
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/Neuron/NeuronLinearSaturated.h b/src/Neuron/NeuronLinearSaturated.h
new file mode 100644
index 00000000..def4d910
--- /dev/null
+++ b/src/Neuron/NeuronLinearSaturated.h
@@ -0,0 +1,36 @@
+
+#include "Neuron.h"
+
+#ifndef INC_4NEURO_NEURONLINEARSATURATED_H
+#define INC_4NEURO_NEURONLINEARSATURATED_H
+
+namespace lib4neuro {
+
+    /**
+     * LinearSaturated linear unit neuron class 
+     * 
+     */
+    class NeuronLinearSaturated : public NeuronDifferentiable {
+	
+	protected:
+		double saturation_point;
+	
+	public:
+        struct access;
+
+        LIB4NEURO_API explicit NeuronLinearSaturated(double saturation_point = 0.0);
+
+        LIB4NEURO_API double activate(double x,
+                                      double b) override;
+
+        LIB4NEURO_API double activation_function_eval_derivative_bias(double x,
+                                                                      double b) override;
+
+        LIB4NEURO_API double activation_function_eval_derivative(double x,
+                                                                 double b) override;
+
+        LIB4NEURO_API Neuron* get_derivative() override;
+    };
+}
+
+#endif //INC_4NEURO_NEURONLINEARSATURATED_H
diff --git a/src/Neuron/NeuronLinearSaturatedSerialization.h b/src/Neuron/NeuronLinearSaturatedSerialization.h
new file mode 100644
index 00000000..22e19c19
--- /dev/null
+++ b/src/Neuron/NeuronLinearSaturatedSerialization.h
@@ -0,0 +1,49 @@
+
+#ifndef LIB4NEURO_NEURONLINEARSATURATEDSERIALIZATION_H
+#define LIB4NEURO_NEURONLINEARSATURATEDSERIALIZATION_H
+
+#include <boost/serialization/base_object.hpp>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/serialization/export.hpp>
+
+#include "NeuronLinearSaturated.h"
+#include "NeuronSerialization.h"
+
+BOOST_CLASS_EXPORT_KEY(lib4neuro::NeuronLinearSaturated);
+
+namespace lib4neuro {
+    struct NeuronLinearSaturated::access {
+        template<class Archive>
+        static void serialize(Archive& ar,
+                              NeuronLinearSaturated& n,
+                              const unsigned int version) {
+            ar & boost::serialization::base_object<Neuron>(n);
+			ar & n.saturation_point;
+        }
+    };
+}
+
+namespace boost {
+    namespace serialization {
+
+        /**
+         * Serialization function
+         * @tparam Archive Boost library template
+         * @param ar Boost parameter - filled automatically during serialization!
+         * @param n NeuronLinearSaturated instance
+         * @param version Boost parameter - filled automatically during serialization!
+         */
+        template<class Archive>
+        void serialize(Archive& ar,
+                       lib4neuro::NeuronLinearSaturated& n,
+                       const unsigned int version) {
+            lib4neuro::NeuronLinearSaturated::access::serialize(ar,
+                                                          n,
+                                                          version);
+        }
+
+    } // namespace serialization
+} // namespace boost
+
+#endif //LIB4NEURO_NEURONLINEARSATURATEDSERIALIZATION_H
-- 
GitLab