试图用c ++创建一个神经网络

时间:2016-11-04 23:52:42

标签: c++ neural-network

我正在尝试将一个神经网络实现为c ++,但我必须为它展示的是许多未知错误。我已经搜索过并找到了其他帖子,例如(C++ class has no member named),但这对我没用。请帮我弄清楚如何解决我遇到的所有错误。 这是代码

#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");
}

我一直在收到如下错误:

错误:类“神经元”没有成员“feedForward” 错误:类“Neuron”没有成员“setOutputVal” 'neuron_OutputVal':未找到标识符

3 个答案:

答案 0 :(得分:0)

class Neuron {};

此处您的文件定义了一个名为Neuron的类。这是一个没有成员,没有方法的类。一个完全空洞的课程。

几行之后:

class Neuron
{
public:

// ...

为什么,这是另一个名为Neuron的类。但是,在C ++中,所有类都必须具有唯一的名称。因此,您的C ++编译器将完全拒绝此类声明,并拒绝处理它。或者,采取其他一些未指明的行动。

答案 1 :(得分:0)

class Neuron {};不是有效的前瞻性声明。您无论如何都不能使用前瞻性声明,因为Layer的声明需要完全了解Neuron

您必须完全删除转发声明class Neuron {};并将您的typedef vector<Neuron> Layer;声明移除。把它放在你的class Net声明之上。

答案 2 :(得分:0)

您的代码中存在三个问题。

首先,正如其他人提到的那样修复你的前瞻声明。

class Neuron;

请注意,此代码中没有{}。你不需要向下移动typedef,因为你的Neuron类使用了typedef&#39; Layer&#39;。

第二,第70行,

neuron.getOutputVal

而不是neuron_getOutputVal。

第167行的第三个只是从getOutputVal(s)中删除s。