Я новичок в машинном обучении и поэтому не могу врубится в чем проблема. Я сделал нейросеть так, чтоб ее было легко изменять.
#include <fstream>
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <random>
using namespace std;
// Изменяемые характеристики нейросети, обучения и ввода
vector<int> nn_char = {4, 8, 3};
int input_size = 4;
int output_size = 1;
int output_format = 3;
bool displacement = false;
double learning_rate = 0.1;
double moment = 0;
int generations = 30000;
//Структуры
struct neuron
{
vector<double> weight;
};
struct train
{
vector<double> input, output;
};
//Функции для оброботки данных
double sigmoid(double s)
{
return 1 / (1 + exp(-s));
}
vector<double> dot(vector<double> a, vector<double> b)
{
for (int i = 0; i < min(a.size(), b.size()); i++)
a[i] *= b[i];
return a;
}
double sum(vector<double> a)
{
double result = 0;
for (int i = 0; i < a.size(); i++)
result += a[i];
return result;
}
double delta_weight(double output, double input, double iter_delta, double error)
{
return error * output * (1 - output) * input * learning_rate + iter_delta * moment;
}
//Активация всей нейросети
vector<vector<double>> nn_act(vector<vector<neuron>> neuralnet, vector<double> input)
{
vector<vector<double>> result;
vector<double> str = input;
result.push_back(str);
for (int layer = 0; layer < nn_char.size(); layer++)
{
str.clear();
if(displacement)
result[layer].push_back(1);
for (int neuron = 0; neuron < nn_char[layer] - (displacement * (layer != nn_char.size() - 1)); neuron++)
str.push_back(sigmoid(sum(dot(result[layer], neuralnet[layer][neuron].weight))));
result.push_back(str);
}
return result;
}
int main()
{
//Ввод Dataset для обучения
ifstream in("input.txt");
int case_size;
in >> case_size;
vector<train> trainer;
for (int case_count = 0; case_count < case_size; case_count++)
{
train buffer;
for (int count = 0; count < input_size; count++)
{
double buff;
in >> buff;
buffer.input.push_back(buff);
}
for (int count = 0; count < output_size; count++)
{
string buff;
in >> buff;
if (buff == "setosa")
buffer.output = { 1, 0, 0 };
else if(buff == "versicolor")
buffer.output = { 0, 1, 0 };
else
buffer.output = { 0, 0, 1 };
}
trainer.push_back(buffer);
}
//Инициализация нейросети
vector<vector<neuron>> neuralnet;
vector<neuron> str;
srand(time(NULL));
for (int neuro = 0; neuro < nn_char[0]; neuro++)
{
neuron buffer;
for (int synaps = 0; synaps < input_size + displacement; synaps++)
buffer.weight.push_back((rand() % 20000) / 10000 - 1);
str.push_back(buffer);
}
neuralnet.push_back(str);
for (int layer = 1; layer < nn_char.size(); layer++)
{
vector<neuron> str;
for (int neuro = 0; neuro < nn_char[layer] + displacement; neuro++)
{
neuron buffer;
for (int synaps = 0; synaps < nn_char[layer - 1]; synaps++)
buffer.weight.push_back((rand() % 20000) / 10000 - 1);
str.push_back(buffer);
}
neuralnet.push_back(str);
}
//Обучение
for (int generation = 0; generation < generations; generation++)
{
train train_case = trainer[rand() % trainer.size()];
vector<vector<vector<double>>> iter_delta;
vector<vector<double>> act_status = nn_act(neuralnet, train_case.input);
vector<double> errors;
for (int layer = 0; layer < nn_char.size(); layer++)
{
vector<vector<double>> str;
for (int neuron = 0; neuron < act_status[layer+1].size(); neuron++)
{
vector<double> neuro;
for (int synaps = 0; synaps < act_status[layer].size(); synaps++)
neuro.push_back(0);
str.push_back(neuro);
}
iter_delta.push_back(str);
}
for (int neuron = 0; neuron < nn_char[nn_char.size() - 1]; neuron++)
{
errors.push_back(act_status[act_status.size() - 1][neuron] - train_case.input[neuron]);
for (int synaps = 0; synaps < act_status[act_status.size() - 2].size(); synaps++)
neuralnet[neuralnet.size() - 1][neuron].weight[synaps] -= (iter_delta[iter_delta.size() - 1][neuron][synaps] = delta_weight(act_status[act_status.size() - 1][neuron], act_status[act_status.size() - 2][synaps], iter_delta[iter_delta.size() - 1][neuron][synaps], errors[neuron]));
}
for (int layer = nn_char.size() - 2; layer >= 0; layer--)
{
vector<double> new_errors;
for (int neuron = 0; neuron < nn_char[layer]; neuron++)
{
double error = 0;
for (int synaps = 0; synaps < errors.size(); synaps++)
error += errors[synaps] * neuralnet[layer + 1][synaps].weight[neuron];
new_errors.push_back(error);
for (int synaps = 0; synaps < act_status[layer].size(); synaps++)
neuralnet[layer][neuron].weight[synaps] -= (iter_delta[layer][neuron][synaps] = delta_weight(act_status[layer + 1][neuron], act_status[layer][synaps], iter_delta[layer][neuron][synaps], error));
}
errors = new_errors;
}
}
vector<double> inp;
for (int i = 0; i < input_size; i++)
{
double buffer;
cin >> buffer;
inp.push_back(buffer);
}
for (int i = 0; i < output_format; i++)
cout << nn_act(neuralnet, inp)[nn_char.size()][i] << " ";
}
В конкретном примере я ее подстроил под решение задачи Ирисы Фишера
https://ru.wikipedia.org/wiki/%D0%98%D1%80%D0%B8%D...
При обучении, нейросеть схватывает только поверхностные вещи и выдает в не зависимости от входных данных примерно одни и те же значения. Понимаю код у меня далек от идеала, но пожалуйста подскажите что я делаю не так.