Реализация нейронной сети (C++).Независимо от входных значений,вывод в районе 0.5
Я пытаюсь реализовать простую нейронную сеть на с++,но при тестирование c XOR ,при обучении вывод сводится к числу в районе 0.5 .Изменение скорости обучения, моментума,значения корректировочного нейрона(bias) не влияет на итоговый результат,после обучения.Я уже протестировал feedforward с фиксированными весами и входными значениями и полагаю что ошибка в самом алгоритме обучения(backpropagation) ,но ,прочитав множество статей о работе алгоритма обучения,так и не смог понять где именно.
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) * 2; };
void FeedForward(vector<double>& inputVals);
void BackPropagation(vector<double>& targetVals);
private:
vector<Layer> Net;
const double alpha = 0.15;
const double epsilon = 0.3;
};
Структура сети построена с помощью двумерного вектора структур(Neuron)
Алгоритм обучения:
void Network::BackPropagation(vector<double>& targetVals)
{
for (unsigned i = 0; i < Net.back().size() - 1; ++i) //дельта для выходного слоя
{
Net.back()[i].delta = (targetVals[i] - Net.back()[i].value) * SigmoidDerivative(Net.back()[i].value);
}
for (int i = Net.size()-2; i >= 0; --i) //дельта для скрытых слоев
{
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) //расчет градиента каждого веса
{
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) //изменение веса и запись изменения в deltaWeight
{
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];
}
}
}
}