Backpropagation and ScaledSigmoidFunction

Report any bugs here and/or Patches for fix them

Backpropagation and ScaledSigmoidFunction

Postby fabietto » Mon Sep 21, 2009 12:44 pm

I was recently doing some tests with the backpropagation algorithm when I incurred in a strange situation.

Running the XOR example present on the website, the application compiles and it returns me the expected results. You can see here the output generated by a typical run of the software:

Iteration: 0 Error: 0.255437
Iteration: 2000 Error: 0.00587259
Iteration: 4000 Error: 0.00165885
Iteration: 6000 Error: 0.000926289
Iteration: 8000 Error: 0.000634771
Iteration: 10000 Error: 0.000480023
Iteration: 12000 Error: 0.000384738
Iteration: 14000 Error: 0.000320382
Iteration: 16000 Error: 0.000274212
Iteration: 18000 Error: 0.00023935
Iteration: 20000 Error: 0.000212056
Iteration: 22000 Error: 0.000190297
Iteration: 24000 Error: 0.000172567
Iteration: 26000 Error: 0.000157842
Iteration: 28000 Error: 0.000145477
Iteration: 30000 Error: 0.000134899
Iteration: 32000 Error: 0.000125788
Iteration: 34000 Error: 0.000117868
Iteration: 36000 Error: 0.000110822
Iteration: 38000 Error: 0.000104457
Iteration: 40000 Error: 9.87694e-05
Iteration: 42000 Error: 9.36685e-05
Iteration: 44000 Error: 8.88934e-05
Iteration: 46000 Error: 8.45752e-05
Iteration: 48000 Error: 8.06261e-05
Iteration: 50000 Error: 7.70264e-05
Inputs: 0 0 - Target output: 0 - Produced output: 0.00407879
Inputs: 0 1 - Target output: 1 - Produced output: 0.992076
Inputs: 1 0 - Target output: 1 - Produced output: 0.992016
Inputs: 1 1 - Target output: 0 - Produced output: 0.0128427

The things become weird if I try to modify the activation function for the hidden and output clusters, from SigmoidFunction to ScaledSigmoidFunction. Those are the results generated:

Iteration: 0 Error: 0.273519
Iteration: 2000 Error: 2.5
Iteration: 4000 Error: 2.5
Iteration: 6000 Error: 2.5
Iteration: 8000 Error: 2.5
Iteration: 10000 Error: 2.5
Iteration: 12000 Error: 2.5
Iteration: 14000 Error: 2.5
Iteration: 16000 Error: 2.5
Iteration: 18000 Error: 2.5
Iteration: 20000 Error: 2.5
Iteration: 22000 Error: 2.5
Iteration: 24000 Error: 2.5
Iteration: 26000 Error: 2.5
Iteration: 28000 Error: 2.5
Iteration: 30000 Error: 2.5
Iteration: 32000 Error: 2.5
Iteration: 34000 Error: 2.5
Iteration: 36000 Error: 2.5
Iteration: 38000 Error: 2.5
Iteration: 40000 Error: 2.5
Iteration: 42000 Error: 2.5
Iteration: 44000 Error: 2.5
Iteration: 46000 Error: 2.5
Iteration: 48000 Error: 2.5
Iteration: 50000 Error: 2.5
Inputs: 0 0 - Target output: 0 - Produced output: -1
Inputs: 0 1 - Target output: 1 - Produced output: -1
Inputs: 1 0 - Target output: 1 - Produced output: -1
Inputs: 1 1 - Target output: 0 - Produced output: -1

Here's the complete code:

Code: Select all
// Input-output includes
#include <iostream>
#include <fstream>

// NNFW includes
#include "nnfw/nnfw.h"
#include "nnfw/fakecluster.h"
#include "nnfw/biasedcluster.h"
#include "nnfw/dotlinker.h"
#include "nnfw/liboutputfunctions.h"
#include "nnfw/backpropagationalgo.h"
#include "nnfw/random.h"

// Define the network blocks
nnfw::FakeCluster *inputCluster;
nnfw::BiasedCluster *hiddenCluster, *outputCluster;
nnfw::DotLinker *inputToHiddenLinker, *hiddenToOutputLinker;
nnfw::BaseNeuralNet *NN;
nnfw::UpdatableVec nnUpdateOrder, bpOrder;
nnfw::BackPropagationAlgo *bp;

// Main
int main (int argc, char * const argv[]) {
   
   // Initialize the randomizer
   nnfw::Random::setSeed(time(0));
   
   // Create the network
   NN = new nnfw::BaseNeuralNet();
   
   inputCluster = new nnfw::FakeCluster(2, "CL_inputCluster");
   hiddenCluster = new nnfw::BiasedCluster(4, "CL_hiddenCluster");
   outputCluster = new nnfw::BiasedCluster(1, "CL_outputCluster");
   
   inputCluster->setFunction(nnfw::IdentityFunction());

   hiddenCluster->setFunction(nnfw::ScaledSigmoidFunction(1.0, -1.0, 1.0));
   outputCluster->setFunction(nnfw::ScaledSigmoidFunction(1.0, -1.0, 1.0));
   
   //hiddenCluster->setFunction(nnfw::SigmoidFunction(1.0));
   //outputCluster->setFunction(nnfw::SigmoidFunction(1.0));
   
   inputToHiddenLinker = new nnfw::DotLinker(inputCluster, hiddenCluster);
   hiddenToOutputLinker = new nnfw::DotLinker(hiddenCluster, outputCluster);
   
   NN->addCluster(inputCluster, true, false);
   NN->addCluster(hiddenCluster, false, false);
   NN->addCluster(outputCluster, false, true);
   NN->addLinker(inputToHiddenLinker);
   NN->addLinker(hiddenToOutputLinker);
   
   nnUpdateOrder << inputCluster << inputToHiddenLinker << hiddenCluster << hiddenToOutputLinker << outputCluster;
   NN->setOrder(nnUpdateOrder);
   
   // Randomize
   NN->randomize(-1.0, 1.0);
   
   // Create the back-propagation algorithm
   bpOrder << outputCluster << hiddenToOutputLinker << hiddenCluster << inputToHiddenLinker << inputCluster;
   bp = new nnfw::BackPropagationAlgo(NN, bpOrder, 0.2); // the third parameter is the learning rate (LR)

   // Set-up the momentum (typically 0.8 according to the literature)
   bp->setMomentum(0.8);
   bp->enableMomentum();

   // Define the teaching input (called learning set in NNFW)
   nnfw::PatternSet learningSet(4); // 4 elements
   // First element: 0,0 -> 1
   learningSet[0].setInputsOf(inputCluster, nnfw::RealVec() << 0.0 << 0.0);
   learningSet[0].setOutputsOf(outputCluster, nnfw::RealVec() << 0.0);
   // Second element: 0,1 -> 1
   learningSet[1].setInputsOf(inputCluster, nnfw::RealVec() << 0.0 << 1.0);
   learningSet[1].setOutputsOf(outputCluster, nnfw::RealVec() << 1.0);
   // Third element: 1,0 -> 1
   learningSet[2].setInputsOf(inputCluster, nnfw::RealVec() << 1.0 << 0.0);
   learningSet[2].setOutputsOf(outputCluster, nnfw::RealVec() << 1.0);
   // Fourth element: 1,1 -> 0
   learningSet[3].setInputsOf(inputCluster, nnfw::RealVec() << 1.0 << 1.0);
   learningSet[3].setOutputsOf(outputCluster, nnfw::RealVec() << 0.0);
   
   // Create and open the file where to write the error rate
   std::ofstream errorFileStream("/Users/fruini/Desktop/error.txt", std::ios::out|std::ios::app|std::ios::ate);
   
   // Apply the BP algorithm for 50,000 iterations
   int i;
   for (i=0; i<50000; i++) {   
      bp->learnOnSet(learningSet);
      errorFileStream << bp->calculateMSEOnSet(learningSet) << std::endl;
      if (i%2000 == 0) std::cout << "Iteration: " << i << "\t\tError: " << bp->calculateMSEOnSet(learningSet) << std::endl;
   }
   std::cout << "Iteration: " << i << "\t\tError: " << bp->calculateMSEOnSet(learningSet) << std::endl;
   
   // Explicitely compare the outputs produced by the network with those contained into the learning set
   for (int i=0; i<4; i++) {   
      inputCluster->inputs() = learningSet[i].inputsOf(inputCluster);
      NN->step();
      std::cout << "Inputs: " << inputCluster->getOutput(0) << "\t" << inputCluster->getOutput(1) << " - Target output: " << learningSet[i].outputsOf(outputCluster)[0] << " - Produced output: " << outputCluster->getOutput(0) << std::endl;
   }   
   
   // Close the file previously opened
   errorFileStream.close();
   
   // End of the application
   return 0;
   
}
fabietto
 
Posts: 20
Joined: Wed Feb 20, 2008 4:11 pm

Return to Bugs and Patches

Who is online

Users browsing this forum: No registered users and 1 guest

cron