Logo Search packages:      
Sourcecode: libneuralnet version File versions  Download package

trainer.cc

//
// trainer.cc
//
// Made by Guillaume Stordeur
// Login   <kami@GrayArea.Masaq>
//
// Started on  Fri Aug  2 05:53:59 2002 Guillaume Stordeur
// Last update Thu May  1 17:05:36 2003 Guillaume Stordeur
//

#include <stdlib.h>
#include <iostream>
#include <vector>
#include <getopt.h>
#include "neuralnet.hh"
#include <exception/exception.hh>
#include <data/csvloader.hh>

enum options_e
  {
    opt_help = 'h',
    opt_version = 'v',
    opt_maxiter = 'm',
    opt_changeiter = 'c',
    opt_epsilon = 'e',
    opt_lrate = 'l',
    opt_fudge = 'f',
    opt_momentum = 'o',
    opt_batch = 'b',
    opt_algorithm = 'a',
    opt_nplus = 'n',
    opt_nminus = 'i',
    opt_deltamin = 'd',
    opt_deltamax = 't',
    opt_mu = 'u',
    opt_wdecay = 'y',
    opt_errorfunc = 'r',
    opt_pca = 'p',
    opt_skip = 's',
    opt_gn = 'g'
  };

static struct option const long_options[] =
  {
    {"help",            0,          0,    opt_help},
    {"version",         0,          0,    opt_version},
    {"maxiter",         1,          0,    opt_maxiter},
    {"changeiter",      1,          0,    opt_changeiter},
    {"epsilon",         1,          0,    opt_epsilon},
    {"lrate",           1,          0,    opt_lrate},
    {"fudge",           1,          0,    opt_fudge},
    {"momentum",  1,          0,    opt_momentum},
    {"batch",           1,          0,    opt_batch},
    {"pca",       1,          0,    opt_pca},
    {"algorithm", 1,          0,    opt_algorithm},
    {"nplus",           1,          0,    opt_nplus},
    {"nminus",          1,          0,    opt_nminus},
    {"deltamin",  1,          0,    opt_deltamin},
    {"deltamax",  1,          0,    opt_deltamax},
    {"errorfunc", 1,          0,    opt_errorfunc},
    {"mu",        1,          0,    opt_mu},
    {"wdecay",          1,          0,    opt_wdecay},
    {"skip",            1,          0,    opt_skip},
    {"gn",        1,          0,    opt_gn},
    {NULL,        0,          NULL, 0}
  };

static const char short_options[] =  "hvp:m:c:e:l:f:o:b:a:n:i:d:t:r:y:s:g:";

void  help(char **argv)
{
  std::cout << "Usage: " << argv[0]
          << " [options] network.nn data.csv separator outputColumn [outputColumn2, ...]" << std::endl;

  std::cout << "Options:" << std::endl
          << "  -h, --help\t\tDisplay this help and exit" << std::endl
          << "  -v, --version\t\tOutput version information and exit" << std::endl;

  std::cout << " Training criteria:" << std::endl
          << "  -m, --maxiter\t\tStop training after this many iterations [default is 10000]" << std::endl
          << "  -c, --changeiter\tStop training after this many iterations without error decrease [default is 0; disabled]" << std::endl
          << "  -e, --epsilon\t\tStop training when total error is <= epsilon [default is 0.001]" << std::endl
          << "  -s, --skip\t\tUse only one in every [skip] training samples [default is 1]" << std::endl;


  std::cout << " Training algorithm global parameters:" << std::endl
          << "  -p, --pca <algo>\tInit weights with a PCA algorithm : gha or ala" << std::endl
          << "  -g, --gn\t Perform Gauss-Newton algorithm after PCA" << std::endl
          << "  -a, --algorithm\tLearning algorithm: NONE, BACKPROP, QUICKPROP or RPROP [default is BACKPROP]" << std::endl
          << "  -b, --batch\t\tLearning is done via batch mode, 0 for stochastic [default is 1]" << std::endl
          << "  -f, --fudge\t\tAdded to derivative of activation function [default is 0]" << std::endl
          << "  -r, --errorfunc\tError function: DIFF, TRIMMED_DIFF, SCALED_DIFF, ATANH [default is DIFF]" << std::endl
          << "  -y, --wdecay\t\tWeight decay used in batch mode [default is 0.0]" << std::endl;

  std::cout << " Training algorithm local parameters:" << std::endl
          << "  -l, --lrate\t\tLearning rate constant used in BACKPROP [default is 0.6]" << std::endl
          << "  -o, --momentum\tMomentum constant used in BACKPROP [default is 0.7]" << std::endl
          << "  -n, --nplus\t\tDelta increase constant used in RPROP [default is 1.2]" << std::endl
          << "  -i, --nminus\t\tDelta decrease constant used in RPROP [default is 0.5]" << std::endl
          << "  -d, --deltamin\tMinimum delta used in RPROP [default is 0.00001]" << std::endl
          << "  -t, --deltamax\tMaximum delta used in RPROP [default is 50]" << std::endl
                << "  -u, --mu\t\tMax factor used in QUICKPROP [default is 1.75]" << std::endl;

  exit(1);
}

void  ver(char **argv)
{
  std::cout << "Version: " << __NN_VERSION << std::endl;
  std::cout << "Authors: " << __NN_AUTHORS << std::endl;
  exit(1);
}

void  parse_args(float &lrate, float &momentum, float &nplus,
               float &nminus, float &deltamin, float &deltamax,
               float &epsilon, float &fudge, float &mu, float &wdecay,
               NeuralNet::TrainingAlgorithm &algorithm, int &batch,
               int &maxiter, int &changeiter, NeuralNet::ErrorFunctionType &errorfunc,
               std::string& pca, int &skip, int &gn, int argc, char **argv)
{
  int idx, c;
  while ((c = getopt_long(argc, argv, short_options, long_options, &idx)) != -1)
    {
      switch (c)
      {
      case opt_gn:
        gn = strtol(optarg, 0, 10);
        break;
      case opt_skip:
        skip = strtol(optarg, 0, 10);
        break;
      case opt_deltamin:
        deltamin = strtof(optarg, 0);
        break;
      case opt_deltamax:
        deltamax = strtof(optarg, 0);
        break;
      case opt_nminus:
        nminus = strtof(optarg, 0);
        break;
      case opt_nplus:
        nplus = strtof(optarg, 0);
        break;
      case opt_wdecay:
        wdecay = strtof(optarg, 0);
        break;
      case opt_pca:
        pca = std::string(optarg);
        break;
      case opt_fudge:
        fudge = strtof(optarg, 0);
        break;
      case opt_mu:
        mu = strtof(optarg, 0);
        break;
      case opt_momentum:
        momentum = strtof(optarg, 0);
        break;
      case opt_lrate:
        lrate = strtof(optarg, 0);
        break;
      case opt_batch:
        batch = strtol(optarg, 0, 10);
        break;
      case opt_errorfunc:
        if (!strcmp(optarg, "DIFF"))
          errorfunc = NeuralNet::ERR_DIFF;
        else if (!strcmp(optarg, "TRIMMED_DIFF"))
          errorfunc = NeuralNet::ERR_TRIMMED_DIFF;
        else if (!strcmp(optarg, "SCALED_DIFF"))
          errorfunc = NeuralNet::ERR_SCALED_DIFF;
        else if (!strcmp(optarg, "ATANH"))
          errorfunc = NeuralNet::ERR_ATANH;
        else
          {
            std::cerr << "Unsupported error function. Please use DIFF, SCALED_DIFF, TRIMMED_DIFF, or ATANH."
                  << std::endl;
            exit(1);
          }
        break;
      case opt_algorithm:
        if (!strcmp(optarg, "BACKPROP"))
          algorithm = NeuralNet::ALG_BACKPROP;
        else if (!strcmp(optarg, "RPROP"))
          algorithm = NeuralNet::ALG_RPROP;
        else if (!strcmp(optarg, "NONE"))
          algorithm = NeuralNet::ALG_NONE;
        else if (!strcmp(optarg, "QUICKPROP"))
          algorithm = NeuralNet::ALG_QUICKPROP;
        else if (!strcmp(optarg, "GN"))
          algorithm = NeuralNet::ALG_GAUSS_NEWTON;
        else
          {
            std::cerr << "Unsupported algorithm. Please use NONE, BACKPROP, QUICKPROP or RPROP."
                  << std::endl;
            exit(1);
          }
        break;
      case opt_epsilon:
        epsilon = strtof(optarg, 0);
        break;
      case opt_changeiter:
        changeiter = strtol(optarg, 0, 10);
        break;
      case opt_maxiter:
        maxiter = strtol(optarg, 0, 10);
        break;
      case opt_help:
        help(argv);
        break;
      case opt_version:
        ver(argv);
        break;
      default:
        //help(argv);
        break;
      }
    }
}

//
// Main
//
int   main(int argc, char *argv[])
{
  float lrate = 0.6, momentum = 0.7, nplus = 1.2, nminus = 0.5, wdecay = 0.0,
    deltamin = 0.00001, deltamax = 50, epsilon = 0.001, fudge = 0, mu = 1.75;
  int batch = 1, maxiter = 10000, changeiter = 0, skip = 1, gn = 0;
  NeuralNet::ErrorFunctionType errorfunc = NeuralNet::ERR_DIFF;
  NeuralNet::TrainingAlgorithm algorithm = NeuralNet::ALG_BACKPROP;
  std::string csvfile, nnfile, pca;
  char separator;
  std::vector<std::string> outputCols;

  srand(time(NULL));

  try
    {
      // Parse command line
      parse_args(lrate, momentum, nplus, nminus, deltamin,
             deltamax, epsilon, fudge, mu, wdecay, algorithm, batch, maxiter,
             changeiter, errorfunc, pca, skip, gn, argc, argv);

      // Remaining are "nnfile, csvfile, separator, outputCols"
      if (argc - optind < 4)
      help(argv);
      else
      {
        nnfile = std::string(argv[optind++]);
        csvfile = std::string(argv[optind++]);
        separator = argv[optind++][0];
        while (optind < argc)
          outputCols.push_back(argv[optind++]);
      }

      //Init cvsloader and get cols
      Data::CsvLoader   loader;
      std::vector<Data::Column*>    cols;
      cols = loader.read_file(csvfile, separator);

      // Init neural net
      NeuralNet::NeuralNet    nn(nnfile);
      nn.setLRate(lrate);
      nn.setMomentum(momentum);
      nn.setDeltaMin(deltamin);
      nn.setDeltaMax(deltamax);
      nn.setNPlus(nplus);
      nn.setNMinus(nminus);
      nn.setMaxIterations(maxiter);
      nn.setChangeIterations(changeiter);
      nn.setErrorEpsilon(epsilon);
      nn.setFudge(fudge);
      nn.setMu(mu);
      nn.setSkip(skip);
      nn.setGaussNewton(gn);
      nn.setWDecay(wdecay);
      nn.setErrorFunction(errorfunc);
      //nn.display();

      // Check that the outputColumns are in the data
      unsigned int out = 0;
      for (unsigned int j = 0; j < outputCols.size(); j++)
      {
        //std::cerr << "Looking for output col: " << outputCols[j].c_str() << std::endl;
        for (unsigned int i = 0; i < cols.size(); i++)
          {
            //std::cerr << " col " << i << ": " << cols[i]->get_name().c_str() << std::endl;
            if (!strcmp(cols[i]->get_name().c_str(), outputCols[j].c_str()))
            {
              std::cerr << "Found the output variable: " << outputCols[j] << std::endl;
              out++;
              break;
            }
          }
      }
      // Check for size differences inputs/outputs with the nn
      if (out != outputCols.size())
      {
        std::cerr << "ERROR: Could not find all output variables in " << csvfile << std::endl;
        return 1;
      }
      if (nn.getNbInputNeurons() != (cols.size() - out))
      {
        std::cerr << "ERROR: Data inputs do not match number of input neurons:" << std::endl;
        std::cerr << "       nbInputNeurons = " << nn.getNbInputNeurons() << std::endl;
        std::cerr << "       nbDataInputs   = " << cols.size() - out << std::endl;
        return 1;
      }
      if (nn.getNbOutputNeurons() != out)
      {
        std::cerr << "ERROR: Data outputs do not match number of output neurons:" << std::endl;
        std::cerr << "       nbOutputNeurons = " << nn.getNbOutputNeurons() << std::endl;
        std::cerr << "       nbDataOutputs   = " << out << std::endl;
        return 1;
      }

      // Make Training Pattern (inputs, results)
      std::vector<float> dres, input;
      std::vector<std::vector<float> > inputs, results;

      for (unsigned int j = 0; j < cols[0]->get_size(); j++)
      {
        input.clear();
        dres.clear();
        for (unsigned int i = 0; i < cols.size(); i++)
          {
            if (cols[i]->get_type() == Data::STRING)
            {
              std::cerr << "ERROR: This trainer does not support strings,";
              std::cerr << "please discretize the data first." << std::endl;
              return 1;
            }
            int out = 0;
            float value;
            if (cols[i]->get_type() == Data::INT)
            value = (float) (dynamic_cast<Data::ColumnTyped<int>*> (cols[i]))->get_value(j);
            else if (cols[i]->get_type() == Data::FLOAT)
            value = (dynamic_cast<Data::ColumnTyped<float>*> (cols[i]))->get_value(j);

            for (unsigned k = 0; k < outputCols.size(); k++)
            if (!strcmp(cols[i]->get_name().c_str(), outputCols[k].c_str()))
              out = 1;
            if (out)
            dres.push_back(value);
            else
            input.push_back(value);
          }
        inputs.push_back(input);
        results.push_back(dres);
      }

      // Apply pca algorithm
      if (pca.size() > 0)
      nn.PCAinit(pca, inputs, results);

      // Learn the Training Pattern
      if (algorithm != NeuralNet::ALG_NONE)
      nn.trainNetwork(inputs, results, batch, algorithm);

      // Dump info
      std::cerr << "Dumping neuralnet to out.nn\n";
      nn.outputFile("out.nn");
      if (nn.getNbInputNeurons() == 2 && nn.getNbOutputNeurons() == 1)
      {
        std::cerr << "Dumping graph response to response.pgm\n";
        nn.graph2d1output("reponse.pgm");
      }

    }
  catch (Exception::Exception e)
    {
      std::cerr << e;
      return 1;
    }
  return 0;
}

Generated by  Doxygen 1.6.0   Back to index