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

nnfile.cc

//
// nnfile.cc
//
// Made by Guillaume Stordeur
// Login   <kami@GrayArea.Masaq>
//
// Started on  Sat Apr  5 16:53:04 2003 Guillaume Stordeur
// Last update Mon May  5 21:46:57 2003 Guillaume Stordeur
//

#include <fstream>
#include <iostream>
#include <stdlib.h>
#include "nnfile.hh"
#include "utils.hh"

namespace NeuralNet
{

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Input functions
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void  NNFile::_inputLayers(const std::string &line)
{
  unsigned int i, lastp = 9;
  for (i = 10; i < line.size(); i++)
    {
      if (line[i] == ',')
      {
        char *nb = strndup(&line.c_str()[lastp], &line.c_str()[i] - &line.c_str()[lastp]);
        _layers.push_back(atoi(nb));
        free(nb);
        lastp = i + 1;
      }
    }
  char *nb = strndup(&line.c_str()[lastp], &line.c_str()[i] - &line.c_str()[lastp]);
  _layers.push_back(atoi(nb));
  free(nb);
}

void  NNFile::_inputHiddenActivation(const std::string &line)
{
  if (!line.compare(19, 7, "sigmoid"))
    _type = ACT_SIGMOID;
  else if (!line.compare(19, 14, "sigmoid_approx"))
    _type = ACT_SIGMOID_APPROX;
  else if (!line.compare(19, 4, "tanh"))
    _type = ACT_TANH;
  else if (!line.compare(19, 11, "tanh_approx"))
    _type = ACT_TANH_APPROX;
  else if (!line.compare(19, 5, "gauss"))
    _type = ACT_GAUSS;
  else if (!line.compare(19, 6, "linear"))
    _type = ACT_LINEAR;
  else if (!line.compare(19, 3, "sgn"))
    _type = ACT_SGN;
  else
    {
      std::cerr << "Invalid [HiddenActivation] type.\n";
      std::cerr << "Possible values are:\n sigmoid\n sigmoid_approx\n tanh\n tanh_approx\n gauss\n sgn\n linear\n";
      exit(1);
    }
}

void  NNFile::_inputOutputActivation(const std::string &line)
{
  if (!line.compare(19, 7, "sigmoid"))
    _type_out = ACT_SIGMOID;
  else if (!line.compare(19, 14, "sigmoid_approx"))
    _type_out = ACT_SIGMOID_APPROX;
  else if (!line.compare(19, 4, "tanh"))
    _type_out = ACT_TANH;
  else if (!line.compare(19, 11, "tanh_approx"))
    _type_out = ACT_TANH_APPROX;
  else if (!line.compare(19, 5, "gauss"))
    _type_out = ACT_GAUSS;
  else if (!line.compare(19, 6, "linear"))
    _type_out = ACT_LINEAR;
  else if (!line.compare(19, 3, "sgn"))
    _type_out = ACT_SGN;
  else
    {
      std::cerr << "Invalid [OutputActivation] type.\n";
      std::cerr << "Possible values are:\n sigmoid\n sigmoid_approx\n tanh\n tanh_approx\n gauss\n sgn\n linear\n";
      exit(1);
    }
}

//
// Helper function, gets all the layers represented by
// the string layer
//
std::vector<unsigned int>     NNFile::_getLayerIndices(char *layer)
{
  unsigned int lidx;
  std::vector<unsigned int> lv;
  if (layer[0] == '*')
    for (unsigned int i = 1; i < _layers.size(); i++)
      lv.push_back(i);
  else
    {
      sscanf(layer, "%d", &lidx);
      lv.push_back(lidx);
    }
  return lv;
}

void  NNFile::_makeCombinations(unsigned int srcLayer,
                          unsigned int srcNeuron,
                          const std::vector<unsigned int> &dstLayerIdx,
                          int dnidx,
                          int random,
                          float value)
{
  std::vector<float>    tmp;
  for (unsigned int i = 0; i < dstLayerIdx.size(); i++)
    if (dnidx != -1)
      {
      tmp.clear();
      tmp.push_back(srcLayer);
      tmp.push_back(srcNeuron);
      tmp.push_back(dstLayerIdx[i]);
      tmp.push_back((int) dnidx);
      tmp.push_back(random ? randWeight() : value);
      _connects.push_back(tmp);
      }
    else
      for (unsigned int j = 0; j < _layers[dstLayerIdx[i]]; j++)
      {
        tmp.clear();
        tmp.push_back(srcLayer);
        tmp.push_back(srcNeuron);
        tmp.push_back(dstLayerIdx[i]);
        tmp.push_back(j);
        tmp.push_back(random ? randWeight() : value);
        _connects.push_back(tmp);
      }
}

void  NNFile::_inputConnect(const std::string &line)
{
  assert(!_layers.empty());
  const char *str = line.c_str();
  char srcLayer[255], srcNeuron[255], weight[255],
    dstLayer[255], dstNeuron[255];

  // scan the line
  sscanf(str, "[connect] %s %s -> %s %s = %s",
       srcLayer, srcNeuron, dstLayer, dstNeuron, weight);
  // get the layer indices
  std::vector<unsigned int> srcLayerIdx = _getLayerIndices(srcLayer);
  std::vector<unsigned int> dstLayerIdx = _getLayerIndices(dstLayer);

  // Value info
  float value;
  int random = 0;
  if (!strcmp(weight, "random") || !strcmp(weight, "rand"))
    random = 1;
  else
    sscanf(weight, "%f", &value);

  // SrcNeuron info
  int           snidx = -1;
  if (srcNeuron[0] != '*')
    sscanf(srcNeuron, "%d", &snidx);
  // DstNeuron info
  int           dnidx = -1;
  if (dstNeuron[0] != '*')
    sscanf(dstNeuron, "%d", &dnidx);

  // fill it up
  for (unsigned int i = 0; i < srcLayerIdx.size(); i++)
    if (snidx != -1)
      _makeCombinations(srcLayerIdx[i], (int) snidx,
                  dstLayerIdx, dnidx, random, value);
    else
      for (unsigned int j = 0; j < _layers[srcLayerIdx[i]]; j++)
      _makeCombinations(srcLayerIdx[i], j,
                    dstLayerIdx, dnidx, random, value);
}

void  NNFile::_inputThreshold(const std::string &line)
{
  assert(!_layers.empty());
  const char *str = line.c_str();
  char layer[255], neuron[255], threshold[255];

  // scan the line
  sscanf(str, "[threshold] %s %s = %s", layer, neuron, threshold);

  // Value info
  float value;
  int random = 0;
  if (!strcmp(threshold, "random") || !strcmp(threshold, "rand"))
    random = 1;
  else
    sscanf(threshold, "%f", &value);

  // Layer info
  std::vector<unsigned int> lv = _getLayerIndices(layer);

  // Neuron info
  int           nidx = -1;
  if (neuron[0] != '*')
    sscanf(neuron, "%d", &nidx);

  std::vector<float>    tmp;
  // Fill it up
  for (unsigned int i = 0; i < lv.size(); i++)
    if (nidx != -1)
      {
      tmp.clear();
      tmp.push_back(lv[i]);
      tmp.push_back(nidx);
      tmp.push_back(random ? randWeight() : value);
      _thresholds.push_back(tmp);
      }
    else
      for (unsigned int j = 0; j < _layers[lv[i]]; j++)
      {
        tmp.clear();
        tmp.push_back(lv[i]);
        tmp.push_back(j);
        tmp.push_back(random ? randWeight() : value);
        _thresholds.push_back(tmp);
      }
}


void  NNFile::_inputFixed(const std::string &line)
{
  assert(!_layers.empty());
  const char *str = line.c_str();
  char layer[255], neuron[255];

  // scan the line
  sscanf(str, "[fixed] %s %s", layer, neuron);

  // Layer info
  std::vector<unsigned int> lv = _getLayerIndices(layer);

  // Neuron info
  int           nidx = -1;
  if (neuron[0] != '*')
    sscanf(neuron, "%d", &nidx);

  std::vector<unsigned int>   tmp;
  // Fill it up
  for (unsigned int i = 0; i < lv.size(); i++)
    if (nidx != -1)
      {
      tmp.clear();
      tmp.push_back(lv[i]);
      tmp.push_back(nidx);
      _fixed.push_back(tmp);
      }
    else
      for (unsigned int j = 0; j < _layers[lv[i]]; j++)
      {
        tmp.clear();
        tmp.push_back(lv[i]);
        tmp.push_back(j);
        _fixed.push_back(tmp);
      }
}

void  NNFile::_inputTimeLagged(const std::string &line)
{
  assert(!_layers.empty());
  const char *str = line.c_str();
  char layer[255], neuron[255];

  // scan the line
  sscanf(str, "[timelagged] %s %s", layer, neuron);

  // Layer info
  std::vector<unsigned int> lv = _getLayerIndices(layer);

  // Neuron info
  int           nidx = -1;
  if (neuron[0] != '*')
    sscanf(neuron, "%d", &nidx);

  std::vector<unsigned int>   tmp;
  // Fill it up
  for (unsigned int i = 0; i < lv.size(); i++)
    if (nidx != -1)
      {
      tmp.clear();
      tmp.push_back(lv[i]);
      tmp.push_back(nidx);
      _timeLagged.push_back(tmp);
      }
    else
      for (unsigned int j = 0; j < _layers[lv[i]]; j++)
      {
        tmp.clear();
        tmp.push_back(lv[i]);
        tmp.push_back(j);
        _timeLagged.push_back(tmp);
      }
}

//
// Input a neural net description file
//
void  NNFile::inputFile(const std::string &filen)
{
  std::ifstream file(filen.c_str());
  if (!file.is_open())
    {
      std::cerr << "Error opening file\n";
      exit (1);
    }
  std::string line;
  while (std::getline(file, line))
    {
      if (line.c_str()[0] == '#')
      continue;
      else if (!line.compare(0, 9, "[layers]="))
      _inputLayers(line);
      else if (!line.compare(0, 7, "[fixed]"))
      _inputFixed(line);
      else if (!line.compare(0, 9, "[connect]"))
      _inputConnect(line);
      else if (!line.compare(0, 12, "[timelagged]"))
      _inputTimeLagged(line);
      else if (!line.compare(0, 11, "[threshold]"))
      _inputThreshold(line);
      else if (!line.compare(0, 19, "[HiddenActivation]="))
      _inputHiddenActivation(line);
      else if (!line.compare(0, 19, "[OutputActivation]="))
      _inputOutputActivation(line);
    }
  file.close();
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Output functions
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

//
// Dump header information
//
void  NNFile::_dumpHeader(std::ofstream &file)
{
  file << "# " << version << "\n";
  file << "# This is a neural network description file for the neuralnet lib.\n#\n";
}

//
// Dump neural network activation function type
//
void  NNFile::_dumpActivation(std::ofstream &file)
{
  std::string s;
  file << "[HiddenActivation]=";
  ACT_STRING(_type, s);
  file << s << std::endl;
  file << "[OutputActivation]=";
  ACT_STRING(_type_out, s);
  file << s << std::endl;
}

//
// Dump layer info
//
void  NNFile::_dumpLayers(std::ofstream &file,
                      const std::vector<t_layer>      &layers)
{
  file << "[layers]=";
  for (unsigned int i = 0; i < layers.size(); i++)
    {
      if (i != 0)
      file << ",";
      file << layers[i].size();
    }
  file << "\n";
}

//
// Dump threshold values
//
void  NNFile::_dumpThresholds(std::ofstream &file,
                        const std::vector<t_layer>    &layers)
{
  file << "\n# Tresholds\n";
  file << "#\n";
  for (unsigned int i = 1; i < layers.size(); i++)
    for (unsigned int j = 0; j < layers[i].size(); j++)
      file << "[threshold] " << i << " " << j << " = "
         << (layers[i])[j]->getWeight(0) << "\n";
}

//
// Dump fixed neurons
//
void  NNFile::_dumpFixed(std::ofstream &file,
                     const std::vector<t_layer> &layers)
{
  file << "\n# Fixed neurons\n";
  file << "#\n";
  for (unsigned int i = 1; i < layers.size(); i++)
    for (unsigned int j = 0; j < layers[i].size(); j++)
      if ((layers[i])[j]->getFixed())
      file << "[fixed] " << i << " " << j << std::endl;
}

//
// Dump timeLagged neurons
//
void  NNFile::_dumpTimeLagged(std::ofstream &file,
                        const std::vector<t_layer>    &layers)
{
  file << "\n# TimeLagged neurons\n";
  file << "#\n";
  for (unsigned int i = 1; i < layers.size(); i++)
    for (unsigned int j = 0; j < layers[i].size(); j++)
      if ((layers[i])[j]->getTimeLagged())
      file << "[timelagged] " << i << " " << j << std::endl;
}

//
// Gets neurons that are connected to this neuron
// returns a vector of (layer, neuron, weight) vectors
//
std::vector<std::vector<float> > NNFile::_getConnect(const std::vector<t_layer>     &layers,
                                         Neuron             *neuron)
{
  std::vector<std::vector<float> > res;
  std::vector<float>             tmp;
  for (unsigned int i = 0; i < layers.size(); i++)
    for (unsigned int j = 0; j < layers[i].size(); j++)
      {
      Neuron *dst = (layers[i])[j];
      int idx = dst->isInputNeuron(neuron);
      if (idx != -1)
        {
          tmp.clear();
          tmp.push_back(i);
          tmp.push_back(j);
          tmp.push_back(dst->getWeight(idx));
          res.push_back(tmp);
        }
      }
  return res;
}

//
// Dump connection weights
//
void  NNFile::_dumpWeights(std::ofstream &file,
                       const std::vector<t_layer>     &layers)
{
  file << "\n# Connections\n";
  file << "#\n";

  for (unsigned int i = 0; i < layers.size(); i++)
    for (unsigned int j = 0; j < layers[i].size(); j++)
      {
      Neuron *neuron = (layers[i])[j];
      std::vector<std::vector<float> > connect = _getConnect(layers, neuron);
      for (unsigned int k = 0; k < connect.size(); k++)
        file << "[connect] " << i << " " << j << " -> "
             << (int) connect[k][0] << " "
             << (int) connect[k][1] << " = " << connect[k][2] << "\n";
      }
}

//
// Output neural network description to file
//
void  NNFile::outputFile(const std::string            filen,
                     ActivationFunctionType     type,
                     ActivationFunctionType     type_out,
                     const std::vector<t_layer> &layers)
{
  _type = type;
  _type_out = type_out;
  std::ofstream file(filen.c_str());
  if (!file.is_open())
    {
      std::cerr << "Error opening file\n";
      exit (1);
    }

  // Write header information
  _dumpHeader(file);
  // Write the neural net activation type
  _dumpActivation(file);
  // Write layer info
  _dumpLayers(file, layers);
  // Write fixed neurons
  _dumpFixed(file, layers);
  // Write thresholds
  _dumpThresholds(file, layers);
  // Write connection weights
  _dumpWeights(file, layers);

  file.close();
}

} //end NeuralNet namespace

Generated by  Doxygen 1.6.0   Back to index