-2

I'm trying to implement a neural network into c++, but all I have to show for it are lots of unknown errors. I've already searched and found other post such as (C++ class has no member named), however this has been no help to me. Can please help me figure out how to resolve all the errors I've been getting. Here's the code

#include <iostream>
#include <vector>
#include <cstdlib>
#include <assert.h>
#include <math.h>

using namespace std;

struct Connection
{
    double weight;
    double deltaWeight;
};

class Neuron {};

typedef vector<Neuron> Layer;

// ************************* class Neuron *************************

class Neuron

{
public:
    Neuron(unsigned numOutputs, unsigned myIndex);
    void setOutputVal(double val) 
    {
        m_outputVal = val; 
    };
    double getOutputVal(void) const 
    { 
        return m_outputVal; 
    };
    void feedForward(const Layer &prevLayer);
    void calcOutputGradients(double targetVal);
    void calcHiddenGradients(const Layer &nextLayer);
    void updateInputWeights(Layer &prevLayer);

private:
    static double eta;      // [0.0..1.0] overall net training rate
    static double alpha;        // [0.0..n] multiplier of last weight change (momentum)
    static double transferFunction(double x);
    static double transferFunctionDerivative(double x);
    static double randomWeight(void) 
    { 
        return rand() / double(RAND_MAX); 
    };
    double sumDOW(const Layer &nextLayer) const;
    double m_outputVal;
    vector<Connection> m_outputWeights;
    unsigned m_myIndex;
    double m_gradient;
};

double Neuron::eta = 0.15;  // overall net learning rate, [0.0..1.0]
double Neuron::alpha = 0.5; // momentum, multiplier of last deltaWeight [0.0..n]

void Neuron::updateInputWeights(Layer &prevLayer)
{
    // The weight are updated in the Connection container
    // in the neurons in the preceding layer

    for (unsigned n = 0; n < prevLayer.size(); ++n) 
    {
        Neuron &neuron = prevLayer[n];
        double oldDeltaWeight = neuron.m_outputWeights[m_myIndex].deltaWeight;

        double newDeltaWeight =
            eta
            * neuron_getOutputVal()
            * m_gradient
            + alpha
            * oldDeltaWeight;
        neuron.m_outputWeights[m_myIndex].deltaWeight = newDeltaWeight;
        neuron.m_outputWeights[m_myIndex].weight += newDeltaWeight;
    }
}

double Neuron::sumDOW(const Layer &nextLayer) const
{
    double sum = 0.0;

    // Sum our contributions of the errors at the nodes we feed

    for (unsigned n = 0; nextLayer.size() - 1; ++n) 
    {
        sum += m_outputWeights[n].weight * nextLayer[n].m_gradient;

    }
    return sum;
}

void Neuron::calcHiddenGradients(const Layer &nextLayer)
{
    double dow = sumDOW(nextLayer);
    m_gradient = dow * Neuron::transferFunctionDerivative(m_outputVal);
}

void Neuron::calcOutputGradients(double targetVal)
{
    double delta = targetVal - m_outputVal;
    m_gradient = delta * Neuron::transferFunctionDerivative(m_outputVal);
}

double Neuron::transferFunction(double x)
{
    // tanh - output range [-1.0..1.0]
    return tanh(x);
}

double Neuron::transferFunctionDerivative(double x)
{
    // tanh derivative
    return 1.0 - x * x;
}

void Neuron::feedForward(const Layer &prevLayer)
{
    double sum = 0.0;

    // Sum the previous layer's outputs (which are our inputs)
    // Include the bias node from the  previous layer

    for (unsigned n = 0; n < prevLayer.size(); ++n) 
    {
        sum += prevLayer[n].getOutputVal() *
            prevLayer[n].m_outputWeights[m_myIndex].weight;
    }

    m_outputVal = Neuron::transferFunction(sum);
}

Neuron::Neuron(unsigned numOutputs, unsigned myIndex)
{
    for (unsigned c = 0; c < numOutputs; ++c) 
    {
        m_outputWeights.push_back(Connection());
        m_outputWeights.back().weight = randomWeight();
    }

    m_myIndex = myIndex;
}

// ************************* class Net *************************

class Net
{
public:
    Net(const vector<unsigned> &topology);
    void feedForward(const vector<double> &inputVals);
    void backProp(const vector<double> &targetVals);
    void getResults(vector<double> &resultVals) const;

private:
    vector<Layer> m_layers; // m_layers{layerNum][neuronNum]
    double m_error;
    double m_recentAverageError;
    double m_recentAverageSmoothingFactor;
};

void Net::getResults(vector<double> &resultVals) const
{
    resultVals.clear();

    for (unsigned n = 0; n < m_layers.back().size() - 1; ++n) 
    {
        resultVals.push_back(m_layers.back()[n].getOutputVals());
    }
}

void Net::backProp(const vector<double> &targetVals)
{
    // Calculate overall net error (RMS of output errors)
    Layer &outputLayer = m_layers.back();
    m_error = 0.0;

    for (unsigned n = 0; n < outputLayer.size() - 1; ++n) 
    {
        double delta = targetVals[n] - outputLayer[n].getOutputVal();
        m_error += delta * delta;
    }
    m_error /= outputLayer.size() - 1; // get average error squared
    m_error = sqrt(m_error); // RMS

    // Implement a recent average measurement:

    m_recentAverageError =
        (m_recentAverageError * m_recentAverageSmoothingFactor + m_error)
        / (m_recentAverageSmoothingFactor + 1.0);

    // Calculate output layer gradients
    for (unsigned n = 0; n < outputLayer.size() - 1; ++n) 
    {
        outputLayer[n].calcOutputGradients(targetVals[n]);
    }

    // Calculate gradients on hidden layers

    for (unsigned layerNum = m_layers.size() - 2; layerNum > 0; --layerNum) 
    {
        Layer &hiddenLayer = m_layers[layerNum];
        Layer &nextLayer = m_layers[layerNum + 1];

        for (unsigned n = 0; n < hiddenLayer.size(); ++n) 
        {
            hiddenLayer[n].calcHiddenGradients(nextLayer);
        }
    }

    // For all layers from output to first hidden layer.
    // update connection weights

    for (unsigned layerNum = m_layers.size() - 1; layerNum > 0; --layerNum) 
    {
        Layer &layer = m_layers[layerNum];
        Layer &prevLayer = m_layers[layerNum - 1];

        for (unsigned n = 0; n < layer.size() - 1; ++n) 
        {
            layer[n].updateInputWeights(prevLayer);
        }
    }

}

void Net::feedForward(const vector<double> &inputVals)
{
    assert(inputVals.size() == m_layers[0].size() - 1);

    // Assign (latch) the values into the input neurons
    for (unsigned i = 0; i < inputVals.size(); ++i) 
    {
        m_layers[0][i].setOutputVal(inputVals[i]);
    }

    // Forward propagate
    for (unsigned layerNum = 1; layerNum = m_layers.size(); ++layerNum) 
    {
        Layer &prevLayer = m_layers[layerNum - 1];
        for (unsigned n = 0; n < m_layers[layerNum].size() - 1; ++n) 
        {
            m_layers[layerNum][n].feedForward(prevLayer);
        }
    }
}

Net::Net(const vector<unsigned> &topology)
{
    unsigned numLayers = topology.size();
    for (unsigned layerNum = 0; layerNum < numLayers; ++layerNum) 
    {
        m_layers.push_back(Layer());
        unsigned numOutputs = layerNum == topology.size() - 1 ? 0 : topology[layerNum + 1];

        // We have made a new layer, now fill it with neurons, and
        // add a bias neuron to the layer:
        for (unsigned neuronNum = 0; neuronNum <= topology[layerNum]; ++neuronNum) 
        {
            m_layers.back().push_back(Neuron(numOutputs, neuronNum));
            cout << "Made a Neuron!" << endl;
        }
    }
}

int main()
{
    // e.g.. { 3, 2, 1 }
    // THIS IS FOR THE NUMBER OF NEURONS THAT YOU WANT!!
    vector<unsigned> topology;
    topology.push_back(3);
    topology.push_back(2);
    topology.push_back(1);
    Net myNet(topology);

    vector<double> inputVals;
    myNet.feedForward(inputVals);

    vector<double> targetVals;
    myNet.backProp(targetVals);

    vector<double> resultVals;
    myNet.getResults(resultVals);

    system("pause");
}

I've been getting errors such as:

Error: class "Neuron" has no member "feedForward" Error: class "Neuron" has no member "setOutputVal" 'neuron_OutputVal': identifier not found

Community
  • 1
  • 1
  • Possibly relevant: https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – Kerrek SB Nov 04 '16 at 23:56
  • Fix your `class` redefinition issue first as mentioned by Sam in the answers, second, as i can see `neuron_OutputVal` is a typo, this should be `neuron.OutputVal()`. – Mo Abdul-Hameed Nov 05 '16 at 00:04
  • Work in smaller chunks and compile often. You'll catch little errors before they can become big errors. – user4581301 Nov 05 '16 at 00:20

3 Answers3

1
class Neuron {};

Here your file defined a class called Neuron. It's a class with no members, and no methods. A completely empty class.

A few lines later:

class Neuron
{
public:

// ...

Why, here's another class called Neuron. However, in C++, all classes must have unique names. So, your C++ compiler will completely reject this class declaration, and refuse to process it. Or, take some other, unspecified action.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
1

There are three issues in your code.

First, as others mentioned fix your forward declaration.

class Neuron;

note this doesnt have {} as in your code. You dont need to move the typedef down, since your Neuron class uses the typedef 'Layer'.

Second, on line 70,

neuron.getOutputVal

instead of neuron_getOutputVal.

Third on line 167 just drop the s from getOutputVal (s).

user3279954
  • 556
  • 2
  • 7
  • 22
0

class Neuron {}; is not a valid forward declaration. You can't use a forward declaration anyway, because declaration of Layer requires full knowledge of Neuron.

You'll have to remove the forward declaration class Neuron {}; entirely and move your declaration of typedef vector<Neuron> Layer; down. Put it right above your declaration of class Net.

Thomas Hilbert
  • 3,559
  • 2
  • 13
  • 33