Hi guys,
I'd like some advice on designing and implementing my neural network class. It has three input neurons, four hidden neurons (one of which is a bias neuron, having the connections from the input layer of weight 1.0), and one output neuron.
It's goal is to determine where (x, y, z) lies in relation to a given 3D function.
Here's the code I have so far:
Typedefs.hpp
Code:
#ifndef TYPEDEF_HPP
#define TYPEDEF_HPP
#include <vector>
#include <random>
typedef std::vector <float>FloatV;
typedef std::random_device RNG;
typedef std::uniform_int_distribution <> UID;
#endif
BadInput.hpp
Code:
#ifndef BADINPUT_HPP
#define BADINPUT_HPP
class BadInput
{
public:
BadInput(int val):difference(val)
{
}
int difference;
};
#endif
Functor.hpp
Code:
#ifndef FUNCTOR_HPP
#define FUNCTOR_HPP
#include "Typedefs.hpp"
class Functor
{
public:
Functor();
Functor(const Functor & rhs) = default;
virtual ~Functor() =default;
virtual float operator() (const FloatV & input) const =0;
virtual int GetArgNum() const =0;
};
class Plane: public Functor
{
public:
Plane() = delete;
Plane(const FloatV& values);
Plane(const Plane & rhs) = default;
virtual ~Plane() = default;
virtual float operator() (const FloatV & input) const;
virtual int GetArgNum() const;
private:
const int argnum;
const FloatV cf;
};
#endif
Functor.cpp
Code:
#include "BadInput.hpp"
#include "Functor.hpp"
#include <iostream>
Functor::Functor()
{
}
Functor::~Functor()
{
}
Plane::Plane(const FloatV& val):cf(val), argnum(2)
{
}
float Plane::operator() (const FloatV & input) const
{
if (input.size() != argnum)
{
int val = input.size() - argnum;
BadInput error(val);
std::cerr << "Number of arguments is " << val << " more than the maximum arguments of two for this function." << std::endl;
throw error;
}
vector < future < float >>results(input.size());
auto sum =[this, input] (int i)->float { return input[i] * cf[i];
}
for (int i = 0; i < input.size(); i++)
results.push_back(async(sum, i));
float sumofprod =0;
for (auto & result:results)
sumofprod += result.get();
return sumofprod += cf.back();
}
int Plane::GetArgNum() const
{
return argnum;
}
Trainer.hpp
Code:
#ifndef TRAINER_HPP
#define TRAINER_HPP
#include "Typedefs.hpp"
#include "Functor.hpp"
class Trainer
{
public:
Trainer() = delete;
Trainer(const Functor& function);
void GenerateData();
FloatV& GetData();
int GetAnswer() const;
private:
const Functor& f;
mutable FloatV TrainingData;
mutable int answer;
};
#endif
Trainer.cpp
Code:
#include "BadInput.hpp"
#include "Trainer.hpp"
#include <future>
using std::async;
namespace
{
RNG rand;
}
Trainer::Trainer(const Functor& function):f(function),
TrainingData(f.GetArgNum())
{
}
void Trainer::GenerateData()
{
auto randomize = [this](int i) {TrainingData[i]=rand();}
for (int i =0; i < TrainingData.size(); i++)
async(randomize, TrainingData[i]);
float z;
try
{
z = f(TrainingData);
}
catch(BadInput&)
{
throw;
}
TrainingData.push_back(rand());
if (TrainingData.back() < z)
answer = -1;
else
answer = 1;
}
FloatV& Trainer::GetData()
{
return TrainingData;
}
int Trainer::GetAnswer() const
{
return answer;
}
Perceptron.hpp
Code:
#ifndef PERCEPTRON_HPP
#define PERCEPTRON_HPP
#include "Typedefs.hpp"
#include "Trainer.hpp"
class Perceptron
{
public:
Perceptron() = delete;
Perceptron(int val);
~Perceptron();
float feedforward(FloatV& input);
private:
FloatV weights;
static const float bias;
static const float correction;
};
#endif
Perceptron.cpp
Code:
#include "BadInput.hpp"
#include "Perceptron.hpp"
#include <iostream>
#include <cmath>
#include <future>
using std::async;
using std::future;
using std::exp;
const float Perceptron::bias = 1.0;
const float Perceptron::correction = 0.01;
namespace
{
UID rand(-1, 1);
RNG rng;
}
Perceptron::Perceptron(int val):weights(rand(rng))
{
}
Perceptron::~Perceptron()
{
}
int Perceptron::feedforward(FloatV& input)
{
float sum = 0;
input.push_back(bias);
if (input.size() != weights.size())
{
BadInput error(input.size() - weights.size());
std::cerr << "Biased input is " << error.difference <<
" value different from the number of weights in the perceptron." <<
std::endl;
throw error;
}
vector <future<float>> results;
auto WeightedInput = [this](float x) -> float {return x*weights[i];}
for (int i=0; i < input.size(); i++) results.push_back(async(WeightedInput, input[i]));
float sum=0;
for(auto& result: results)
sum += result.get();
return 1.0/(1.0 + exp(-sum));
}
NeuralNetwork.hpp
Code:
#ifndef NEURAL_NETWORK_HPP
#define NEURAL_NETWORK_HPP
#include "Trainer.hpp"
#include "Perceptron.hpp"
#include "Typedefs.hpp"
class NeuralNetwork
{
public:
NeuralNetwork() = delete;
NeuralNetwork(Trainer& trainer);
float operator()(FloatV& input);
private:
void Train(Trainer& trainer);
void Classify(FloatV& input);
vector<Perceptron> InputLayer;
vector<Perceptron> HiddenLayer;
Perceptron Output;
FloatV InputWeight;
FloatV OutputWeight;
};
#endif
I'm having code block right now. Also, I want the vector operations to run in it's own thread, as speed is critical.
Thanks,
Lexi