janhohenheim / Hippocrates

No longer maintained, actually usable implementation of NEAT
GNU Affero General Public License v3.0
63 stars 12 forks source link

"Number of inputs provided doesn't match genetic information" #101

Closed deepsorrow closed 7 years ago

deepsorrow commented 7 years ago

Hi! I can't figure it out why inputs and inputNeurons don't match: releaseissue I'm trying to use unsupervised learning, so I followed by your tutorial and implemented my IBody class, and now it looks like this:

#include <vector>
#include "body/body.hpp"

using namespace Hippocrates;
using namespace Hippocrates::Body;

class IBody2 : public IBody {
 public:
    auto Reset() -> void;
    auto Update(const Type::neuron_values_t& networkOutputs) -> void;
    auto HasFinishedTask() const -> bool;
    auto GetFitness() const -> Type::fitness_t;

    auto ProvideNetworkWithInputs() const -> Type::neuron_values_t;

    auto GetInputCount() const -> std::size_t;
    auto GetOutputCount() const -> std::size_t;

    auto GetMaximumFitness() const -> Type::fitness_t;
   //my added stuff:
        auto GetOutputs() -> std::vector<float>;
    auto SetMaximumFitness(const double &NewMaximumFitness) -> void;
    auto SetInputValues(const std::vector<float> &NewInputs) -> void;
    auto SetFitness(const double &NewFitness) -> void;
    double fitness;
    double MaxFitness = 10;
 private:
    ::std::vector<float> inputs;
    ::std::vector<float> outputs;
};

Where my .cpp file contain this:

#include "neat.h"

auto IBody2::Reset() -> void
{
    fitness = 0;
    inputs.clear();
    outputs.clear();
}

auto IBody2::Update(const Type::neuron_values_t & networkOutputs) -> void
{
    outputs = networkOutputs;
}

auto IBody2::HasFinishedTask() const -> bool
{
    if (fitness >= MaxFitness) {
        return true;
    }
    else
        return false;
}

auto IBody2::GetFitness() const -> Type::fitness_t
{
    return fitness;
}

auto IBody2::ProvideNetworkWithInputs() const -> Type::neuron_values_t
{
    return inputs;
}

auto IBody2::GetInputCount() const -> std::size_t
{
    return inputs.size();
}

auto IBody2::GetOutputCount() const -> std::size_t
{
    return outputs.size();
}

auto IBody2::GetMaximumFitness() const -> Type::fitness_t
{
    return MaxFitness;
}

auto IBody2::GetOutputs() -> std::vector<float>
{
    return outputs;
}

auto IBody2::SetMaximumFitness(float &NewMaximumFitness) -> void
{
    MaxFitness = NewMaximumFitness;
}

auto IBody2::SetInputValues(const std::vector<float>& NewInputs) -> void
{
    inputs = NewInputs;
}

auto IBody2::SetFitness(const double & NewFitness) -> void
{
    fitness = NewFitness;
}

And this is how I use it in my project:

std::vector<float> inputVals(7), outputVals(3);
IBody2 NN;

                        // This code repeats every frame:

//here I update my fitness and initialize inputVals

NN.SetFitness(fitness);   //fitness = 5.94 when error happens
NN.SetInputValues(inputVals);

std::vector<std::reference_wrapper<Body::IBody>> mybodies;
mybodies.push_back(NN);

Training::NeuralNetworkTrainer trainer;
auto champ = trainer.TrainUnsupervised(mybodies); // <--- error occurs here

outputVals = champ.GetOutputsUsingInputs(inputVals);

Could you please tell me, what am I doing wrong? P.S. I don't have much experience in these things, so any protips and advises are welcome. :)

janhohenheim commented 7 years ago

Here you delete all of your inputs:

auto IBody2::Reset() -> void
{
    fitness = 0;
    inputs.clear();
    outputs.clear();
}

Here new ones are being requested:

auto IBody2::ProvideNetworkWithInputs() const -> Type::neuron_values_t
{
    return inputs;
}

You never fill your inputs vector with anything new in the meantime.
The library still expects 7 inputs, instead gets 0, gets sad and crashes.

Feel free to ask if you have any additional questions. Good luck with your school project btw :)