serializatioin / deserialization and tests

This commit is contained in:
2016-04-06 15:54:47 +02:00
parent adb6708b39
commit 17cbf5effe
28 changed files with 437 additions and 280 deletions

View File

@@ -1,6 +1,18 @@
#pragma once
#include <string>
#include <SimpleJSON/SerializableObject.h>
#include <SimpleJSON/Factory.h>
#define NEURAL_NETWORK_REGISTER_ACTIVATION_FUNCTION(name,function) SIMPLEJSON_REGISTER(NeuralNetwork::ActivationFunction::Factory,name,function)
/*public: \
static const class __FACT_REGISTER_ {\
public: \
__FACT_REGISTER_() {\
NeuralNetwork::ActivationFunction::Factory::registerCreator( #name ,function);\
}\
} __FACT_REGISTER;
*/
#define NEURAL_NETWORK_REGISTER_ACTIVATION_FUNCTION_FINISH(name,function) SIMPLEJSON_REGISTER_FINISH(NeuralNetwork::ActivationFunction::Factory,name,function)
namespace NeuralNetwork {
namespace ActivationFunction {
@@ -9,7 +21,7 @@ namespace ActivationFunction {
* @author Tomas Cernik (Tom.Cernik@gmail.com)
* @brief Abstract class of activation function
*/
class ActivationFunction {
class ActivationFunction : public SimpleJSON::SerializableObject {
public:
virtual ~ActivationFunction() {}
@@ -41,11 +53,10 @@ namespace ActivationFunction {
*/
virtual ActivationFunction* clone() const = 0;
/**
* @brief This is a virtual function for storing Activation function
* @returns json describing function
*/
virtual std::string stringify() const =0;
const static bool FORCE_REGISTER;
};
typedef SimpleJSON::Factory<ActivationFunction> Factory;
}
}

View File

@@ -16,12 +16,18 @@ namespace ActivationFunction {
return new Heaviside(lambda);
}
virtual std::string stringify() const override {
return "{ \"class\": \"NeuralNetwork::ActivationFunction::Heaviside\", \"lamba\" : "+std::to_string(lambda)+"}";
virtual SimpleJSON::Type::Object serialize() const override {
return {{"class", "NeuralNetwork::ActivationFunction::Heaviside"}, {"lambda", lambda}};
}
static std::unique_ptr<Heaviside> deserialize(const SimpleJSON::Type::Object &obj) {
return std::unique_ptr<Heaviside>(new Heaviside(obj["lambda"].as<double>()));
}
protected:
float lambda;
NEURAL_NETWORK_REGISTER_ACTIVATION_FUNCTION(NeuralNetwork::ActivationFunction::Heaviside, Heaviside::deserialize)
};
}
}

View File

@@ -13,17 +13,24 @@ namespace ActivationFunction {
inline virtual float derivatedOutput(const float &,const float &output) const override { return lambda*(1-output*output); }
inline virtual float operator()(const float &x) const override { return tanh(lambda*x); };
inline virtual float operator()(const float &x) const override { return tanh(lambda*x); }
;
virtual ActivationFunction* clone() const override {
return new HyperbolicTangent(lambda);
}
virtual std::string stringify() const override {
return "{ \"class\": \"NeuralNetwork::ActivationFunction::HyperbolicTangent\", \"lamba\" : "+std::to_string(lambda)+"}";
virtual SimpleJSON::Type::Object serialize() const override {
return {{"class", "NeuralNetwork::ActivationFunction::HyperbolicTangent"}, {"lambda", lambda}};
}
static std::unique_ptr<HyperbolicTangent> deserialize(const SimpleJSON::Type::Object &obj) {
return std::unique_ptr<HyperbolicTangent>(new HyperbolicTangent(obj["lambda"].as<double>()));
}
protected:
float lambda;
NEURAL_NETWORK_REGISTER_ACTIVATION_FUNCTION(NeuralNetwork::ActivationFunction::HyperbolicTangent, HyperbolicTangent::deserialize)
};
}
}

View File

@@ -2,6 +2,8 @@
#include "./ActivationFunction.h"
#include <cassert>
namespace NeuralNetwork {
namespace ActivationFunction {
@@ -17,12 +19,17 @@ namespace ActivationFunction {
return new Linear(lambda);
}
virtual std::string stringify() const override {
return "{ \"class\": \"NeuralNetwork::ActivationFunction::Linear\", \"lamba\" : "+std::to_string(lambda)+"}";
virtual SimpleJSON::Type::Object serialize() const override {
return {{"class", "NeuralNetwork::ActivationFunction::Linear"}, {"lambda", lambda}};
}
static std::unique_ptr<Linear> deserialize(const SimpleJSON::Type::Object &obj) {
return std::unique_ptr<Linear>(new Linear(obj["lambda"].as<double>()));
}
protected:
float lambda;
NEURAL_NETWORK_REGISTER_ACTIVATION_FUNCTION(NeuralNetwork::ActivationFunction::Linear, Linear::deserialize)
};
}
}

View File

@@ -29,11 +29,18 @@ namespace ActivationFunction {
return new Sigmoid(lambda);
}
virtual std::string stringify() const override {
return "{ \"class\": \"NeuralNetwork::ActivationFunction::Sigmoid\", \"lamba\" : "+std::to_string(lambda)+"}";
virtual SimpleJSON::Type::Object serialize() const override {
return {{"class", "NeuralNetwork::ActivationFunction::Sigmoid"}, {"lambda", lambda}};
}
static std::unique_ptr<Sigmoid> deserialize(const SimpleJSON::Type::Object &obj) {
return std::unique_ptr<Sigmoid>(new Sigmoid(obj["lambda"].as<double>()));
}
protected:
float lambda;
NEURAL_NETWORK_REGISTER_ACTIVATION_FUNCTION(NeuralNetwork::ActivationFunction::Sigmoid, Sigmoid::deserialize)
};
}
}

View File

@@ -13,8 +13,7 @@ namespace ActivationFunction {
*/
class StreamingActivationFunction : public ActivationFunction {
public:
virtual float operator()(const float &x) const=0;
using ActivationFunction::operator();
/**
* @brief Returns value of four outputs

View File

@@ -1,13 +1,19 @@
#pragma once
#include <SimpleJSON/SerializableObject.h>
#include <SimpleJSON/Factory.h>
#include <math.h>
#include <vector>
#include <string>
#define NEURAL_NETWORK_REGISTER_BASIS_FUNCTION(name,function) SIMPLEJSON_REGISTER(NeuralNetwork::BasisFunction::Factory,name,function)
#define NEURAL_NETWORK_REGISTER_BASIS_FUNCTION_FINISH(name,function) SIMPLEJSON_REGISTER_FINISH(NeuralNetwork::BasisFunction::Factory,name,function)
namespace NeuralNetwork {
namespace BasisFunction {
class BasisFunction {
class BasisFunction : public SimpleJSON::SerializableObject {
public:
virtual ~BasisFunction() {}
virtual float operator()(const std::vector<float>& weights, const std::vector<float>& input) const =0;
@@ -15,13 +21,9 @@ namespace BasisFunction {
/**
* @brief Function returns clone of object
*/
virtual BasisFunction* clone() const = 0;
/**
* @brief This is a virtual function for storing Basis function
* @returns json describing function
*/
virtual std::string stringify() const =0;
virtual std::unique_ptr<BasisFunction> clone() const = 0;
};
typedef SimpleJSON::Factory<BasisFunction> Factory;
}
}

View File

@@ -22,14 +22,18 @@ namespace BasisFunction {
virtual float operator()(const std::vector<float>& weights, const std::vector<float>& input) const override;
virtual BasisFunction* clone() const override {
return new Linear();
virtual std::unique_ptr<BasisFunction> clone() const override {
return std::unique_ptr<BasisFunction>(new Linear());
}
virtual std::string stringify() const override {
return "{ \"class\": \"NeuralNetwork::BasisFunction::Linear\" }";
virtual SimpleJSON::Type::Object serialize() const override {
return {{"class", "NeuralNetwork::BasisFunction::Linear"}};
}
static std::unique_ptr<Linear> deserialize(const SimpleJSON::Type::Object &) {
return std::unique_ptr<Linear>(new Linear());
}
NEURAL_NETWORK_REGISTER_BASIS_FUNCTION(NeuralNetwork::BasisFunction::Linear, deserialize)
};
}
}

View File

@@ -21,14 +21,19 @@ namespace BasisFunction {
return product;
}
virtual Product* clone() const override {
return new Product();
virtual std::unique_ptr<BasisFunction> clone() const override {
return std::unique_ptr<BasisFunction>(new Product());
}
virtual std::string stringify() const override {
return "{ \"class\": \"NeuralNetwork::BasisFunction::Product\" }";
virtual SimpleJSON::Type::Object serialize() const override {
return {{"class", "NeuralNetwork::BasisFunction::Product"}};
}
static std::unique_ptr<Product> deserialize(const SimpleJSON::Type::Object &) {
return std::unique_ptr<Product>(new Product());
}
NEURAL_NETWORK_REGISTER_BASIS_FUNCTION(NeuralNetwork::BasisFunction::Product, deserialize)
};
}
}

View File

@@ -1,5 +1,4 @@
#ifndef __BASIS_RADIAL_H_
#define __BASIS_RADIAL_H_
#pragma once
#include "./BasisFunction.h"
@@ -20,14 +19,19 @@ namespace BasisFunction
return sqrt(sum);
}
virtual BasisFunction* clone() const override {
return new Radial();
virtual std::unique_ptr<BasisFunction> clone() const override {
return std::unique_ptr<BasisFunction>(new Radial());
}
virtual std::string stringify() const override {
return "{ \"class\": \"NeuralNetwork::BasisFunction::Radial\" }";
virtual SimpleJSON::Type::Object serialize() const override {
return {{"class", "NeuralNetwork::BasisFunction::Radial"}};
}
static std::unique_ptr<Radial> deserialize(const SimpleJSON::Type::Object &) {
return std::unique_ptr<Radial>(new Radial());
}
NEURAL_NETWORK_REGISTER_BASIS_FUNCTION(NeuralNetwork::BasisFunction::Radial, deserialize)
};
}
}
#endif
}

View File

@@ -1,11 +1,12 @@
#pragma once
#include "../Neuron.h"
#include <SimpleJSON/SerializableObject.h>
#include <cstddef>
#include <vector>
#include "../Neuron.h"
#include "../Stringifiable.h"
namespace NeuralNetwork {
namespace FeedForward {
@@ -13,9 +14,10 @@ namespace FeedForward {
* @author Tomas Cernik (Tom.Cernik@gmail.com)
* @brief Class for Layer of FeedForward network
*/
class Layer : public Stringifiable {
class Layer : public SimpleJSON::SerializableObject {
public:
Layer(std::size_t size, const ActivationFunction::ActivationFunction &activationFunction):neurons() {
neurons.push_back(new BiasNeuron);
for(std::size_t i=0;i<size;i++) {
@@ -70,11 +72,18 @@ namespace FeedForward {
}
}
using Stringifiable::stringify;
virtual void stringify(std::ostream& out) const override;
virtual SimpleJSON::Type::Object serialize() const override;
static std::unique_ptr<Layer> deserialize(const SimpleJSON::Type::Object&);
typedef SimpleJSON::Factory<Layer> Factory;
protected:
std::vector<NeuronInterface*> neurons;
private:
Layer():neurons() {
}
SIMPLEJSON_REGISTER(NeuralNetwork::FeedForward::Layer::Factory, NeuralNetwork::FeedForward::Layer,NeuralNetwork::FeedForward::Layer)
};
}
}

View File

@@ -4,13 +4,8 @@
#include "Layer.h"
#include <vector>
#include <sstream>
#include <iomanip>
#include <limits>
#include <iostream>
namespace NeuralNetwork {
namespace FeedForward {
@@ -63,24 +58,29 @@ namespace FeedForward {
using NeuralNetwork::Network::stringify;
void stringify(std::ostream& out) const override {
out << "{" << std::endl;
out << "\t \"class\": \"NeuralNetwork::FeedForward::Network\"," << std::endl;
out << "\t \"layers\": [" << std::endl;
bool first=true;
for(auto &layer:layers) {
if(!first) {
out << ",";
}
out << *layer;
first=false;
virtual SimpleJSON::Type::Object serialize() const override {
std::vector<SimpleJSON::Value> layersSerialized;
for(std::size_t i=0;i<layers.size();i++) {
layersSerialized.push_back(layers[i]->serialize());
}
out << "]";
out << "}";
return {
{"class", "NeuralNetwork::FeedForward::Network"},
{"layers", layersSerialized },
};
}
static std::unique_ptr<Network> deserialize(const SimpleJSON::Type::Object&);
typedef SimpleJSON::Factory<Network> Factory;
protected:
std::vector<Layer*> layers;
private:
inline Network():NeuralNetwork::Network(),layers() {
};
SIMPLEJSON_REGISTER(NeuralNetwork::FeedForward::Network::Factory, NeuralNetwork::FeedForward::Network,NeuralNetwork::FeedForward::Network::deserialize)
};
}
}

View File

@@ -1,14 +1,13 @@
#pragma once
#include "Neuron.h"
#include <SimpleJSON/SerializableObject.h>
#include <cstddef>
#include <vector>
#include "Neuron.h"
#include "Stringifiable.h"
#include <ostream>
#include <sstream>
#define NEURAL_NETWORK_INIT() const static bool ______TMP= NeuralNetwork::Network::loaded()
namespace NeuralNetwork
{
@@ -17,13 +16,15 @@ namespace NeuralNetwork
* @author Tomas Cernik (Tom.Cernik@gmail.com)
* @brief Abstract model of simple Network
*/
class Network : public Stringifiable
class Network : public SimpleJSON::SerializableObject
{
public:
/**
* @brief Constructor for Network
*/
inline Network() {};
inline Network() {
loaded();
};
/**
* @brief Virtual destructor for Network
@@ -49,5 +50,8 @@ namespace NeuralNetwork
* @brief Number of threads used by network
*/
unsigned threads=1;
public:
static bool loaded();
};
}

View File

@@ -1,22 +1,20 @@
#pragma once
#include <NeuralNetwork/ActivationFunction/Sigmoid.h>
#include <NeuralNetwork/BasisFunction/Linear.h>
#include <string>
#include <vector>
#include <sstream>
#include <limits>
#include <NeuralNetwork/ActivationFunction/Sigmoid.h>
#include <NeuralNetwork/BasisFunction/Linear.h>
namespace NeuralNetwork
{
/**
* @author Tomas Cernik (Tom.Cernik@gmail.com)
* @brief Abstract class of neuron. All Neuron classes should derive from this on
*/
class NeuronInterface
{
class NeuronInterface : public SimpleJSON::SerializableObject {
public:
NeuronInterface(const unsigned long &_id=0): id(_id), weights(1),_output(1),
_value(0) {
@@ -33,12 +31,6 @@ namespace NeuralNetwork
*/
virtual ~NeuronInterface() {};
/**
* @brief This is a virtual function for storing network
* @returns json describing network and it's state
*/
virtual std::string stringify(const std::string &prefix="") const =0;
/**
* @brief getter for neuron weight
* @param &neuron is neuron it's weight is returned
@@ -118,6 +110,8 @@ namespace NeuralNetwork
* @brief id is identificator if neuron
*/
const unsigned long id;
typedef SimpleJSON::Factory<NeuronInterface> Factory;
protected:
std::vector<float> weights;
float _output;
@@ -128,8 +122,7 @@ namespace NeuralNetwork
* @author Tomas Cernik (Tom.Cernik@gmail.com)
* @brief Class of FeedForward neuron.
*/
class Neuron: public NeuronInterface
{
class Neuron: public NeuronInterface {
public:
Neuron(unsigned long _id=0, const ActivationFunction::ActivationFunction &activationFunction=ActivationFunction::Sigmoid(-4.9)):
NeuronInterface(_id), basis(new BasisFunction::Linear),
@@ -137,7 +130,7 @@ namespace NeuralNetwork
_output=0.0;
}
Neuron(const Neuron &r): NeuronInterface(r), basis(r.basis->clone()), activation(r.activation->clone()) {
Neuron(const Neuron &r): NeuronInterface(r), basis(r.basis->clone().release()), activation(r.activation->clone()) {
}
virtual ~Neuron() {
@@ -147,8 +140,6 @@ namespace NeuralNetwork
Neuron operator=(const Neuron&) = delete;
virtual std::string stringify(const std::string &prefix="") const override;
float operator()(const std::vector<float>& inputs) {
//compute value
_value=basis->operator()(weights,inputs);
@@ -174,7 +165,7 @@ namespace NeuralNetwork
virtual void setBasisFunction(const BasisFunction::BasisFunction& basisFunction) override {
delete basis;
basis=basisFunction.clone();
basis=basisFunction.clone().release();
}
@@ -182,10 +173,16 @@ namespace NeuralNetwork
delete activation;
activation=activationFunction.clone();
}
virtual SimpleJSON::Type::Object serialize() const override;
static std::unique_ptr<Neuron> deserialize(const SimpleJSON::Type::Object &obj);
protected:
BasisFunction::BasisFunction *basis;
ActivationFunction::ActivationFunction *activation;
SIMPLEJSON_REGISTER(NeuralNetwork::NeuronInterface::Factory, NeuralNetwork::Neuron,NeuralNetwork::Neuron::deserialize)
};
class BiasNeuron: public NeuronInterface {
@@ -203,8 +200,6 @@ namespace NeuralNetwork
std::string text;
};
virtual std::string stringify(const std::string& prefix = "") const override { return prefix+"{ \"class\" : \"NeuralNetwork::BiasNeuron\" }"; }
virtual float operator()(const std::vector< float >&) override { return 1.0; }
virtual BiasNeuron* clone() const { return new BiasNeuron(); }
@@ -226,6 +221,15 @@ namespace NeuralNetwork
throw usageException("activation function");
}
virtual SimpleJSON::Type::Object serialize() const override {
return {{"class", "NeuralNetwork::BiasNeuron"}};
}
static std::unique_ptr<BiasNeuron> deserialize(const SimpleJSON::Type::Object &) {
return std::unique_ptr<BiasNeuron>(new BiasNeuron());
}
SIMPLEJSON_REGISTER(NeuralNetwork::NeuronInterface::Factory, NeuralNetwork::BiasNeuron,NeuralNetwork::BiasNeuron::deserialize)
};
class InputNeuron: public NeuronInterface {
@@ -247,8 +251,6 @@ namespace NeuralNetwork
}
virtual std::string stringify(const std::string& prefix = "") const override { return prefix+"{ \"class\" : \"NeuralNetwork::InputNeuron\", \"id\": "+std::to_string(id)+" }"; }
virtual float operator()(const std::vector< float >&) override { return 1.0; }
virtual InputNeuron* clone() const { return new InputNeuron(id); }
@@ -269,5 +271,15 @@ namespace NeuralNetwork
virtual void setActivationFunction(const ActivationFunction::ActivationFunction &) override {
throw usageException("activation function");
}
virtual SimpleJSON::Type::Object serialize() const override {
return {{"class", "NeuralNetwork::InputNeuron"}, {"id", id}};
}
static std::unique_ptr<NeuronInterface> deserialize(const SimpleJSON::Type::Object &obj) {
return std::unique_ptr<NeuronInterface>(new InputNeuron(obj["id"].as<int>()));
}
SIMPLEJSON_REGISTER(NeuralNetwork::NeuronInterface::Factory, NeuralNetwork::InputNeuron,NeuralNetwork::InputNeuron::deserialize)
};
}

View File

@@ -40,6 +40,15 @@ namespace Recurrent {
}
};
Network(const Network &r) :inputSize(r.inputSize), outputSize(r.outputSize), neurons(0), outputs(r.outputs) {
neurons.push_back(new NeuralNetwork::BiasNeuron());
for(std::size_t i=1;i<r.neurons.size();i++) {
neurons.push_back(r.neurons[i]->clone());
}
}
Network& operator=(const Network&r);
/**
* @brief Virtual destructor for Network
*/
@@ -70,9 +79,7 @@ namespace Recurrent {
return neurons;
}
using NeuralNetwork::Network::stringify;
void stringify(std::ostream& out) const override;
virtual SimpleJSON::Type::Object serialize() const override;
NeuronInterface& addNeuron() {
neurons.push_back(new Neuron(neurons.size()));
@@ -90,12 +97,17 @@ namespace Recurrent {
*/
NeuralNetwork::Recurrent::Network connectWith(const NeuralNetwork::Recurrent::Network &r) const;
static std::unique_ptr<Network> deserialize(const SimpleJSON::Type::Object&);
typedef SimpleJSON::Factory<Network> Factory;
protected:
size_t inputSize=0;
size_t outputSize=0;
std::vector<NeuronInterface*> neurons;
std::vector<float> outputs;
SIMPLEJSON_REGISTER(NeuralNetwork::Recurrent::Network::Factory,NeuralNetwork::Recurrent::Network, deserialize)
};
}
}

View File

@@ -1,30 +0,0 @@
#pragma once
#include <sstream>
namespace NeuralNetwork {
class Stringifiable {
public:
virtual ~Stringifiable() {
}
/**
* @brief This is a virtual function for class
*/
virtual void stringify(std::ostream& out) const =0;
virtual std::string stringify() final {
std::ostringstream s;
stringify(s);
return s.str();
}
};
inline static std::ostream& operator<<(std::ostream& o, const Stringifiable& n) {
n.stringify(o);
return o;
}
}

View File

@@ -1,80 +0,0 @@
#pragma once
namespace Array {
/**
* @author Tomas Cernik (Tom.Cernik@gmail.com)
* @brief Template of array for simple usage
*/
template <typename T>
class Array {
public:
Array(unsigned long size=0):arr(size==0? nullptr: new T[size]),_size(0) {
}
Array (const Array& r):arr(r.arr),_size(r._size) {
}
~Array() {
}
inline Array& operator=(const Array& r) {
arr=r.arr;
_size=r._size;
}
inline void resize(unsigned long size) {
if(arr==nullptr) {
arr=new T[size];
_size=size;
}else {
T* tmp=new T[size];
for(unsigned long i=0;i<_size;i++) {
tmp[i]=arr[i];
}
delete[] arr;
arr=tmp;
}
}
inline void free() {
delete[] arr;
arr=nullptr;
_size=0;
}
inline const T& operator[](unsigned long i) const {
return arr[i];
}
inline T& operator[](unsigned long i) {
return arr[i];
}
unsigned long size() const {
return _size;
}
protected:
T* arr;
unsigned long _size;
private:
};
template <typename T>
class DynamicArray: public Array<T> {
public:
DynamicArray(unsigned long size=0,float _scaleFactor=1):Array<T>(size),scaleFactor(_scaleFactor) {
}
protected:
float scaleFactor;
private:
};
}