// Copyright (C) 2001 Jean-Marc Valin #include "FFNet.h" #include #include "ObjectParser.h" #ifdef HAVE_FLOAT_H #include #endif #include "misc.h" #include "Array.h" using namespace std; namespace FD { DECLARE_TYPE(FFNet) //DECLARE_TYPE(Vector) DECLARE_TYPE(Vector) DECLARE_TYPE2("Vector>", Vector >) //@implements FFNet FFNet::FFNet(const Vector &_topo, const Vector &functions) : topo(_topo) , layers(topo.size()-1) { init(functions); } void FFNet::init(const Vector &functions) { nbNeurons = 0; nbWeights = 0; for (int i=0;iinit(1.0); weightOffset += (topo[i]+1)*topo[i+1]; neuronOffset += topo[i+1]; } } FFNet::FFNet(const Vector &_topo, const Vector &functions, vector &tin, vector &tout) : topo(_topo) , layers(topo.size()-1) { init(functions); //cerr << tin.size() << endl; vector inputMeans(topo[0], 0); vector outputMeans(topo[topo.size()-1], 0); vector inputStd(topo[0], 0); vector outputStd(topo[topo.size()-1], 0); for (int i=0;iinit(&inputMeans[0], &inputStd[0]); //layers[i]->init(10); } else { //layers[i]->init(10.0); layers[i]->init(1.0); } if (i==topo.size()-2) layers[i]->setBias(&outputMeans[0]); } } FFNet::FFNet(FFNet &net) : topo(net.topo) , layers(net.layers.size()) { cerr << "I wouldn't do that if I were you...\n"; // for (int i=0;iinit(1.0); layers[i]->setupAfterRead(weights, weightOffset, neuronOffset); weightOffset += (topo[i]+1)*topo[i+1]; neuronOffset += topo[i+1]; } } void FFNet::learn(float *input, float *output, double *gradient, double *err, float *calc_output) { int outputLayer = topo.size()-2; //float value[nbNeurons]; //float deriv[nbNeurons]; //float error[nbNeurons]; //float fgradient[nbWeights]; DYN_VEC(float, nbNeurons, value); DYN_VEC(float, nbNeurons, deriv); DYN_VEC(float, nbNeurons, error); DYN_VEC(float, nbWeights, fgradient); float *calc_out = calc(input, value, deriv); if (calc_output) for (int i=0;i=0;k--) { FFLayer *currentLayer = &(*layers[k]); float *previousValue, *currentValue; if (k==0) previousValue = input; else previousValue = value + layers[k-1]->getNeuronOffset(); currentValue = value + currentLayer->getNeuronOffset(); int layerSize = topo[k+1]; int layerInputs = topo[k]; float *delta = error + currentLayer->getNeuronOffset(); if (k==outputLayer) { // Error calculation is simple for (int i=0;igetNeuronOffset(); for (int j=0;jgetWeights(j); float outErr = outErrPtr[j]; vec_mul_and_add(outErr, outW, delta, layerSize); } } for (int i=0;igetNeuronWeightOffset(i); delta[i] = deriv[i+currentLayer->getNeuronOffset()]*delta[i]; vec_mul_scal (delta[i], previousValue, grad, layerInputs); grad[layerInputs] = delta[i]; } } for (int i=0;i &tin, vector &tout, Array eval_weights, Array &gradient, double &err) { int i,j; //float tmp[nbWeights]; DYN_VEC(float, nbWeights, tmp); for (int i=0;i=0;k--) { FFLayer *currentLayer = &(*layers[k]); float *previousValue, *currentValue; if (k==0) previousValue = input; else previousValue = value + layers[k-1]->getNeuronOffset(); currentValue = value + currentLayer->getNeuronOffset(); int layerSize = topo[k+1]; int layerInputs = topo[k]; float *delta = error + currentLayer->getNeuronOffset(); if (k==outputLayer) { // Error calculation is simple for (int i=0;igetNeuronOffset(); for (int j=0;jgetWeights(j); float outErr = outErrPtr[j]; vec_mul_and_add(outErr, outW, delta, layerSize); } } for (int i=0;igetNeuronWeightOffset(i); delta[i] = deriv[i+currentLayer->getNeuronOffset()]*delta[i]; vec_mul_scal (delta[i], previousValue, grad, layerInputs); grad[layerInputs] = delta[i]; } } for (int i=0;i &tin, vector &tout, vector &learnWeights, Array eval_weights, Array &gradient, double &err) { int i,j; //float tmp[nbWeights]; DYN_VEC(float, nbWeights, tmp); for (int i=0;i tin, vector tout) { double SSE=0; Array wk(nbWeights); vec_copy(weights, &wk[0], nbWeights); //getWeights(&wk[0]); Array dEk(nbWeights); calcGradient(tin, tout, wk, dEk, SSE); return SSE; } void FFNet::setDerivOffset(float d) { for (int i=0;isetDerivOffset(d); } void FFNet::printOn(ostream &out) const { out << "" << endl; out << "" << endl; out << ">\n"; } void FFNet::readFrom (istream &in) { string tag; //cerr << "FFNet::readFrom\n"; while (1) { char ch; in >> ch; if (ch == '>') break; else if (ch != '<') throw new ParsingException ("FFNet::readFrom : Parse error: '<' expected"); in >> tag; if (tag == "topo") in >> topo; else if (tag == "layers") { in >> layers; } else throw new ParsingException ("FFNet::readFrom : unknown argument: " + tag); if (!in) throw new ParsingException ("FFNet::readFrom : Parse error trying to build " + tag); in >> tag; if (tag != ">") throw new ParsingException ("FFNet::readFrom : Parse error: '>' expected "); } setupLayersAfterRead(); } istream &operator >> (istream &in, FFNet &net) { if (!isValidType(in, "FFNet")) return in; net.readFrom(in); return in; } }//namespace FD