CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Dec 2013
    Posts
    75

    Exception seems to materialize out of nowhere!

    My perceptron's train function seems to materialize my BadInput exception object out of nowhere. Yet, everything works fine.

    And when I put an forever loop in main to validate the output with many different inputs, I get a bad_alloc exception and a call to terminate().

    BadInput.hpp
    Code:
    #ifndef BADINPUT_HPP
    #define BADINPUT_HPP
    
    
    class BadInput
    {
      public:
    	BadInput(int val):difference(val)
    	{
    	}
    	int difference;
    };
    
    #endif
    Typedefs.hpp
    Code:
    #ifndef TYPEDEF_HPP
    #define TYPEDEF_HPP
    #include <vector>
    #include <random>
    
    typedef std::vector <float>FloatV;
    typedef std::random_device RNG;
    typedef std::uniform_int_distribution <> UID;
    
    #endif
    Functor.hpp
    Code:
    #ifndef FUNCTOR_HPP
    #define FUNCTOR_HPP
    #include "Typedefs.hpp"
    #include "BadInput.hpp"
    
    class Functor
    {
      public:
    	Functor()
    	{
    	}
    	Functor(const Functor & rhs) = default;
        virtual ~Functor(){}
    	virtual float operator() (const FloatV  & input)const = 0;
    	int GetArgNum() const
    	{
    		return argnum;
    	}
      private:
    	  int argnum;
    };
    
    class Plane:public Functor
    {
      public:
    	Plane() = delete;
    	Plane(const FloatV & values):cf(values), argnum(2)
    	{
    	}
    	Plane(const Plane & rhs) = default;
    	virtual ~Plane()
    	{
    	}
    	virtual float operator() (const FloatV & input)const
    	{
    		float sum = 0;
    		if (input.size() != argnum)
    			throw BadInput(input.size() - argnum);
    		for (int i = 0; i < input.size(); i++)
    			  sum += input[i] * cf[i];
    		  sum += cf.back();
    	}
      private:
    	 const int argnum;
    	 const FloatV cf;
    };
    #endif
    Trainer.hpp
    Code:
    #ifndef TRAINER_HPP
    #define TRAINER_HPP
    #include "Typedefs.hpp"
    #include "Functor.hpp"
    
    class Trainer
    {
      public:
    	Trainer() = delete;
    	Trainer(const Functor& function);
    	void GenerateData();
    	  FloatV& GetData() const;
    	int GetAnswer() const;
      private:
    	const Functor& f;
    	mutable FloatV TrainingData;
    	mutable int answer;
    };
    #endif
    Trainer.cpp
    Code:
    #include "BadInput.hpp"
    #include "Trainer.hpp"
    
    Trainer::Trainer(const Functor& function):f(function),
    TrainingData(f.GetArgNum())
    {
    }
    
    void Trainer::GenerateData()
    {
    	RNG rand;
      for (auto & val:TrainingData)
    		val = rand();
    	float z;
    	try
    	{
    		z = f(TrainingData);
    	}
    	catch(BadInput&)
    	{
    		throw;
    	}
    	TrainingData.push_back(rand());
    	if (TrainingData.back() < z)
    		answer = -1;
    	else
    		answer = 1;
    }
    
    FloatV & Trainer::GetData() const
    {
    	return TrainingData;
    }
    
    int Trainer::GetAnswer() const
    {
    	return answer;
    }
    Perceptron.hpp
    Code:
    #ifndef PERCEPTRON_HPP
    #define PERCEPTRON_HPP
    #include "Typedefs.hpp"
    #include "Trainer.hpp"
    
    class Perceptron
    {
      public:
    	Perceptron() = delete;
    	Perceptron(Trainer& trainer);
    	~Perceptron();
    	int feedforward(FloatV& input);
    	void retrain(Trainer& trainer);
      private:
    	void train(Trainer & trainer);
    	int activate(float sum);
    	FloatV weights;
    	static const float bias;
    	static const float correction;
    };
    #endif
    Perceptron.cpp
    Code:
    #include "BadInput.hpp"
    #include "Perceptron.hpp"
    #include <iostream>
    
    const float Perceptron::bias = 1.0;
    const float Perceptron::correction = 0.01;
    
    Perceptron::Perceptron(Trainer & trainer):weights(trainer.GetData().size() + 1)
    {
    	UID rand(-1, 1);
    	RNG rng;
      for (auto & weight:weights)
    		weight = static_cast < float >(rand(rng));
    	try
    	{
    		train(trainer);
    	}
    	catch(BadInput & error)
    	{
    		std::
    			cerr <<
    			"An error occurred during the initialization of the perceptron." <<
    			std::endl;
    	}
    }
    
    
    Perceptron::~Perceptron()
    {
    }
    
    void Perceptron::retrain(Trainer & trainer)
    {
    
    	UID rand(-1, 1);
    	RNG rng;
      for (auto & weight:weights)
    		weight = static_cast < float >(rand(rng));
    		try
    		{
    	train(trainer);
    		}
    	catch(BadInput & error)
    	{
    		std::
    			cerr <<
    			"An error occurred during the retraining of the perceptron." <<
    			std::endl;
    	}
    }
    
    int Perceptron::feedforward(FloatV & input)
    {
    	float sum = 0;
    	input.push_back(bias);
    	if (input.size() != weights.size())
    	{
    		BadInput error(input.size() - weights.size());
    		std::cerr << "Biased input is " << error.difference <<
    			" value different from the number of weights in the perceptron." <<
    			std::endl;
    		throw error;
    	}
    	for (int i = 0; i < input.size(); i++)
    		sum += (input[i] * weights[i]);
    	return activate(sum);
    }
    
    void Perceptron::train(Trainer & trainer)
    {
    	for (int i = 0; i < 2000; i++)
    	{
    		int guess;
    		int correct;
    		try
    		{
    			trainer.GenerateData();
    		}
    		catch(BadInput & error)
    		{
    			std::cerr << "An error has occurred in training the perceptron." <<
    				std::endl;
    			throw;
    		}
    		guess = feedforward(trainer.GetData());
    
    		correct = trainer.GetAnswer();
    		int error = correct - guess;
    		for (int i = 0; i < (trainer.GetData().size() + 1); i++)
    			weights[i] += (trainer.GetData()[i] * error * correction);
    	}
    }
    
    int Perceptron::activate(float sum)
    {
    	if (sum > 0)
    		return 1;
    	else
    		return -1;
    }
    Main.cpp
    Code:
    #include <iostream>
    #include "BadInput.hpp"
    #include "Typedefs.hpp"
    #include "Functor.hpp"
    #include "Trainer.hpp"
    #include "Perceptron.hpp"
    using std::cout;
    using std::cerr;
    using std::cin;
    using std::endl;
    
    int main()
    {
    	FloatV coefficients(3);
    	cout <<
    		"This program will learn to classify whether a given point lies above or below a plane given by z=mx+ny+b. Please enter values for m, n, and b: "
    		<< endl;
      for (auto & val:coefficients)
    	{
    		cin >> val;
    		if (cin.fail())
    		{
    			cerr << "Please enter a number! Program will now terminate." <<
    				endl;
    			return -1;
    		}
    	}
    	Plane f(coefficients);
    
    	Trainer ProfessorWilson(f);
    	Perceptron brain(ProfessorWilson);
    
    	cout << "Enter a point (x, y, z) to classify: " << endl;
    	FloatV point(3);
      for (auto & val:point)
    	{
    		cin >> val;
    		if (cin.fail())
    		{
    			cerr << "Please enter a number! Program will now terminate." <<
    				endl;
    			return -1;
    		}
    	}
    	int classification;
    	try
    	{
    		classification = brain.feedforward(point);
    	}
    	catch(const BadInput & error)
    	{
    		return -1;
    	}
    
    	if (classification == 1)
    		cout << "Point is above the plane." << endl;
    	if (classification == -1)
    		cout << "Point is below the plane." << endl;
    	return 0;
    }
    I cannot figure out why train() is throwing an exception...feedforward didn't, as it's error message never printed.

    Thanks,
    Lexi

  2. #2
    Join Date
    Dec 2013
    Posts
    75

    Re: Exception seems to materialize out of nowhere!

    The TrainingData vector in Trainer seems to be one longer than it should be. The exception is coming from Plane's function call operator.

  3. #3
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Exception seems to materialize out of nowhere!

    Quote Originally Posted by TSLexi View Post
    The TrainingData vector in Trainer seems to be one longer than it should be. The exception is coming from Plane's function call operator.
    Code:
    for (int i = 0; i < (trainer.GetData().size() + 1); i++)
    	weights[i] += (trainer.GetData()[i] * error * correction);
    Arrays / vectors are indexed from 0 to n-1, where n is the total number of items. What is the value of i on the last iteration of this loop? And in general, why are you adding 1 (which is what is suspicious)?

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; January 30th, 2014 at 06:36 AM.

  4. #4
    Join Date
    Dec 2013
    Posts
    75

    Re: Exception seems to materialize out of nowhere!

    I fixed it. No exceptions, and output is correct.

    I forgot to declare GetArgNum() as virtual, so Trainer's ctor was calling Functor's instead of Plane's.
    Last edited by TSLexi; January 31st, 2014 at 01:20 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured