Я пытаюсь реализовать простую нейронную сеть на 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];
}
}
}
}