@Ivanychhypit

Почему моя нейросеть не обучается?

Я новичок в машинном обучении и поэтому не могу врубится в чем проблема. Я сделал нейросеть так, чтоб ее было легко изменять.
#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...
При обучении, нейросеть схватывает только поверхностные вещи и выдает в не зависимости от входных данных примерно одни и те же значения. Понимаю код у меня далек от идеала, но пожалуйста подскажите что я делаю не так.
  • Вопрос задан
  • 95 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы