Реализация нейронной сети C ++ XOR.Output всегда около 0,5 - PullRequest
0 голосов
/ 16 февраля 2020

Я пытаюсь реализовать простую нейронную сеть на C ++. Но при тестировании с HOR он всегда дает выход около 0.5. Я пытаюсь изменить скорость обучения, импульс, значение нейрона, но ничего не помогает.

Сеть сама по себе - это двумерный вектор структур (нейрон)

struct Neuron
{
    vector<double> weights;
    vector<double> deltaWeights;
    vector<double> gradient;
    double value;
    double delta;
};

typedef vector<Neuron> Layer;

class Network
{
    public:
    Network(vector<unsigned>& Topology);
    double Sigmoid(double& x) { return 1 / (1 + exp(-x)); };
    double SigmoidDerivative(double& x) { return Sigmoid(x) * (1 - Sigmoid(x)); };
    double RandomWeights() { return ((double)rand() / RAND_MAX); };
    double ErrorFactor(vector<double>& TargetVals);
    void FeedForward(vector<double>& inputVals);
    void BackPropagation(vector<double>& targetVals);
private:
    vector<Layer> Net;
    const double alpha = 0.15; //learning rate
    const double epsilon = 0.3; //momentum
};

Я пытался FeedForward с постоянными весами, и я думаю, что ошибка в алгоритме обратного распространения

алгоритм обратного распространения:

void Network::BackPropagation(vector<double>& targetVals)
{
    for (unsigned i = 0; i < Net.back().size() - 1; i++) //delta for output neurons
    {
        Net.back()[i].delta = (targetVals[i] - Net.back()[i].value)  * SigmoidDerivative(Net.back()[i].value);
    }
    for (int i = Net.size()-2; i >= 0; i--) //delta for hiden neurons
    {
        for (unsigned j = 0; j < Net[i].size(); j++)
        {
            Net[i][j].delta = 0;

            for (unsigned l = 0; l < Net[i][j].weights.size(); l++)
            {
                Net[i][j].delta += (Net[i][j].weights[l] * Net[i + 1][l].delta);
            }

            Net[i][j].delta *= SigmoidDerivative(Net[i][j].value);
        }
    }

    for (unsigned i = 0; i < Net.size() - 1; i++) //gradient
    {
        for (unsigned j = 0; j < Net[i].size(); j++)
        {
            for (unsigned l = 0; l < Net[i][j].weights.size(); l++)
            {
                Net[i][j].gradient[l] = Net[i][j].value * Net[i + 1][l].delta;
            }
        }
    }

    for (unsigned i = 0; i < Net.size() - 1; i++) //changing weigths
    {
        for (unsigned j = 0; j < Net[i].size(); j++)
        {
            for (unsigned l = 0; l < Net[i][j].weights.size(); l++)
            {
                Net[i][j].deltaWeights[l] = (Net[i][j].gradient[l] * epsilon + Net[i][j].deltaWeights[l] * alpha);
                Net[i][j].weights[l] += Net[i][j].deltaWeights[l];
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...