// Copyright (C) 1999 Jean-Marc Valin
#include "BufferedNode.h"
#include "ObjectRef.h"
#include "FFNet.h"
#include "TrainingAlgo.h"
using namespace std;
namespace FD {
class NNetTrainDBD;
DECLARE_NODE(NNetTrainDBD)
/*Node
*
* @name NNetTrainDBD
* @category NNet
* @description Neural network (MLP) training unsing the Delta-bar-delta algorithm
* @require FFNetTrain
*
* @input_name TRAIN_IN
* @input_type Vector<ObjectRef>
* @input_description Input data accumulator
*
* @input_name TRAIN_OUT
* @input_type Vector<ObjectRef>
* @input_description Output data accumulator
*
* @input_name NNET
* @input_type FFNet
* @input_description Neural network that will be trained
*
* @output_name OUTPUT
* @output_type FFNet
* @output_description Trained network
*
* @parameter_name MAX_EPOCH
* @parameter_type int
* @parameter_value 2000
* @parameter_description Number of training epoch (default 2000)
*
* @parameter_name LEARN_RATE
* @parameter_type float
* @parameter_value 0.000001
* @parameter_description Initial learning rate (default 0.000001)
*
* @parameter_name INCREASE
* @parameter_type float
* @parameter_value 1.04
* @parameter_description Learning rate increment (> 1.0) factor (default 1.04)
*
* @parameter_name DECREASE
* @parameter_type float
* @parameter_value 0.6
* @parameter_description Learning rate decrement (< 1.0) factor (default 0.6)
*
* @parameter_name NB_SETS
* @parameter_type int
* @parameter_value 1
* @parameter_description Number of batch subsets for accelerated training (default 1)
*
* @parameter_name ALLOC_CHUNK
* @parameter_type bool
* @parameter_value false
* @parameter_description If true, a big vector is allocated to store all the inputs (default false)
*
* @parameter_name RPROP
* @parameter_type bool
* @parameter_value false
* @parameter_description If true, use the RProp variant of delta-bar-delta (default false)
*
END*/
class NNetTrainDBD : public BufferedNode {
protected:
/**The ID of the 'trainIN' input*/
int trainInID;
/**The ID of the 'trainOut' input*/
int trainOutID;
/**The ID of the 'output' output*/
int outputID;
/**The ID of the 'nnet' input*/
int netInputID;
int maxEpoch;
float learnRate;
float decrease;
float increase;
int nbSets;
bool allocChunk;
bool rprop;
public:
/**Constructor, takes the name of the node and a set of parameters*/
NNetTrainDBD(string nodeName, ParameterSet params)
: BufferedNode(nodeName, params)
{
outputID = addOutput("OUTPUT");
netInputID = addInput("NNET");
trainInID = addInput("TRAIN_IN");
trainOutID = addInput("TRAIN_OUT");
if (parameters.exist("MAX_EPOCH"))
maxEpoch = dereference_cast<int> (parameters.get("MAX_EPOCH"));
else maxEpoch = 2000;
if (parameters.exist("LEARN_RATE"))
learnRate = dereference_cast<float> (parameters.get("LEARN_RATE"));
else learnRate = .000001;
if (parameters.exist("INCREASE"))
increase = dereference_cast<float> (parameters.get("INCREASE"));
else increase = 1.04;
if (parameters.exist("DECREASE"))
decrease = dereference_cast<float> (parameters.get("DECREASE"));
else decrease = .6;
if (parameters.exist("NB_SETS"))
nbSets = dereference_cast<int> (parameters.get("NB_SETS"));
else nbSets = 1;
if (parameters.exist("ALLOC_CHUNK"))
allocChunk = dereference_cast<bool> (parameters.get("ALLOC_CHUNK"));
else allocChunk = false;
if (parameters.exist("RPROP"))
rprop = dereference_cast<bool> (parameters.get("RPROP"));
else rprop = false;
}
/**Ask for the node's output which ID (number) is output_id
and for the 'count' iteration */
virtual void calculate(int output_id, int count, Buffer &out)
{
cerr << "getOutput in NNetTrainDBD\n";
int i,j;
ObjectRef trainInValue = getInput(trainInID, count);
ObjectRef trainOutValue = getInput(trainOutID, count);
ObjectRef netValue = getInput(netInputID, count);
//cerr << "inputs calculated\n";
Vector<ObjectRef> &inBuff = object_cast<Vector<ObjectRef> > (trainInValue);
Vector<ObjectRef> &outBuff = object_cast<Vector<ObjectRef> > (trainOutValue);
//cerr << "inputs converted\n";
int nbSamples = inBuff.size();
if (nbSamples != outBuff.size())
throw new NodeException(this, "Input buffer sizes don't fit", __FILE__, __LINE__);
int inLength = object_cast <Vector<float> > (inBuff[0]).size();
int outLength = object_cast <Vector<float> > (outBuff[0]).size();
vector <float *> tin(nbSamples);
vector <float *> tout(nbSamples);
float *buff;
if (allocChunk)
{
buff = new float [nbSamples*(inLength+outLength)];
for (i=0;i<nbSamples;i++)
{
tin[i] = buff+i*(inLength+outLength);
tout[i] = buff+i*(inLength+outLength)+inLength;
Vector<float> &vin = object_cast <Vector<float> > (inBuff[i]);
Vector<float> &vout = object_cast <Vector<float> > (outBuff[i]);
if (inLength != vin.size() || outLength != vout.size())
throw new NodeException(this, "Vectors in buffers have different sizes", __FILE__, __LINE__);
for (int j=0;j<inLength;j++)
tin[i][j] = vin[j];
for (int j=0;j<outLength;j++)
tout[i][j] = vout[j];
//vec_copy(&vin[0], tin[i], inLength);
//vec_copy(&vout[0], tout[i], outLength);
}
} else {
for (i=0;i<nbSamples;i++)
{
tin[i]=&object_cast <Vector<float> > (inBuff[i])[0];
tout[i]=&object_cast <Vector<float> > (outBuff[i])[0];
}
}
/*
vector <float *> tin(inBuff.size());
for (i=0;i<inBuff.size();i++)
tin[i]=&object_cast <Vector<float> > (inBuff[i])[0];
vector <float *> tout(outBuff.size());
for (i=0;i<outBuff.size();i++)
tout[i]=&object_cast <Vector<float> > (outBuff[i])[0];
*/
FFNet &net = object_cast<FFNet> (netValue);
//net.setDerivOffset(.05);
TrainingDeltaBarDelta::train(&net, tin, tout, maxEpoch, learnRate, increase, decrease, nbSets, rprop);
if (allocChunk)
delete [] buff;
out[count] = netValue;
}
};
}//namespace FD
syntax highlighted by Code2HTML, v. 0.9.1