Форум программистов, компьютерный форум, киберфорум
C++: ИИ, нейросети, ML, агенты
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.51/75: Рейтинг темы: голосов - 75, средняя оценка - 4.51
0 / 0 / 0
Регистрация: 19.08.2019
Сообщений: 2

Нейронная сеть на c++ - многослойный перцептрон

19.08.2019, 20:09. Показов 20940. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Уважаемые форумчане нужна ваша помощь с нейронной сетью на c++!
На днях захотел написать прогу - многослойный перцептрон на c++, вроде информации много и пытался менять код, но всё одинаково, прога выдаёт ответ который с увеличением колличества иттераций приближается к единице, но одинаков для всех входных значений, входа, кстати 3.
Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <iostream>
#include <vector>
#include <cmath>
#include <ctime>
 
const int input_amount = 3;
const int hiden_deep = 2;
const int hiden_amount = 2;
const float learning_rate = 0.001;
const int itteration_amount = 1000;
const std::vector<std::vector<float>> inputs {{0.00, 0.00, 0.00}, {0.00, 0.00, 1.00}, {0.00, 1.00, 0.00}, {0.00, 1.00, 1.00}, {1.00, 0.00, 0.00}, {1.00, 0.00, 1.00}, {1.00, 1.00, 0.00}, {1.00, 1.00, 1.00}};
const std::vector<float> right { 0.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00};
 
int random_input() {
    return rand() % 8;
}
 
float sigmoid(float number) {
    return 1 / (1 + pow(2.71, -number));
}
 
float random_number() {
    float number = rand() % 50 + 1;
    float a = (float)((1 / (number)) - 0.5);
    return a;
}
 
float end_error(float actual, float right) {
    return (actual - right)*(actual - right)*100;
}
 
void weights_random_filling(std::vector<std::vector<float>> &input_weights, std::vector<std::vector<std::vector<float>>> &hiden_weights, std::vector<float> &output_weights) {
for(int a = 0; a < input_amount; a++) {
for(int b = 0; b < hiden_amount; b++) {
input_weights.at(a).at(b) = random_number();
}
}
if(hiden_deep > 1) {
for(int a = 0; a < hiden_deep - 1; a++) {
for(int b = 0; b < hiden_amount; b++) {
for(int c = 0; c < hiden_amount; c++) {
hiden_weights.at(a).at(b).at(c) = random_number();
}
}
}
}
for(int a = 0; a < hiden_amount; a++) {
output_weights.at(a) = random_number();
}
}
 
void new_weights(std::vector<std::vector<float>> &hiden_deltas, std::vector<std::vector<float>> &input_weights, std::vector<std::vector<std::vector<float>>> &hiden_weights, std::vector<float> &output_weights,std::vector<std::vector<float>> hiden_data, std::vector<float> input_data, const float &output_data, const float &right_answer) {
float weights_delta = (output_data - right_answer) * output_data * (1 - output_data);
for(int a = hiden_amount - 1; a >= 0;a--) {
output_weights.at(a) -= hiden_data.at(hiden_deep - 1).at(a) * learning_rate * weights_delta;
hiden_deltas.at(hiden_deep - 1).at(a) = (weights_delta * output_weights.at(a)) * (hiden_data.at(hiden_deep - 1).at(a) * (1 - hiden_data.at(hiden_deep - 1).at(a)));
}
if(hiden_deep > 1) {
for(int a = hiden_deep - 2; a >= 0; a--) {
for(int b = hiden_amount - 1; b >= 1; b--){
for(int c = hiden_amount - 1; c >= 0; c--) {
hiden_weights.at(a).at(b).at(c) -= hiden_data.at(a).at(b)* learning_rate * hiden_deltas.at(a + 1).at(c);
hiden_deltas.at(a).at(b) += ((hiden_deltas.at(a + 1).at(c) * hiden_weights.at(a).at(b).at(c)) * (hiden_data.at(a).at(b) * (1 - hiden_data.at(a).at(b)))/hiden_amount);
}
}
}
}
for(int a = input_amount - 1; a >= 0; a--){
for(int b = hiden_amount - 1; b >= 0; b--){
input_weights.at(a).at(b) -= input_data.at(a) * learning_rate * hiden_deltas.at(0).at(b);
}
}
}
 
void neuron(std::vector<std::vector<float>> &hiden_data, std::vector<float> &input_data, float &output_data, std::vector<std::vector<float>> &input_weights, std::vector<std::vector<std::vector<float>>> &hiden_weights, std::vector<float> &output_weights) {
for(int a = 1; a < hiden_amount; a++) {
   for(int b = 0; b < input_amount; b++) {
       hiden_data.at(0).at(a) +=input_weights.at(b).at(a) * input_data.at(b);
       }
   hiden_data.at(0).at(a) = sigmoid(hiden_data.at(0).at(a));
}
if(hiden_deep > 1) {
for(int a = 1; a < hiden_deep ; a++) {
    for(int b = 1; b < hiden_amount; b++) {
       for(int c = 0; c < hiden_amount; c++) {
          hiden_data.at(a).at(b) += hiden_data.at(a - 1).at(c) * hiden_weights.at(a - 1).at(b).at(c);
                
        }
     hiden_data.at(a).at(b) = sigmoid(hiden_data.at(a).at(b));
      }
   }
}
for(int a = 0; a < hiden_amount; a++) {
    output_data += hiden_data.at(hiden_amount - 1).at(a) * output_weights.at(a);
    }
    output_data = sigmoid(output_data); 
}
 
int main() {
srand( time(0));
std::vector<std::vector<float>> hiden_data(hiden_deep, std::vector<float>(hiden_amount,0.00));
std::vector<float> input_data(input_amount, 0.00);
float output_data = 0.00;
for(int a = 0; a < hiden_deep; a++) {
   hiden_data.at(a).at(0) = 1.00;
}
std::vector<std::vector<float>> hiden_deltas (hiden_deep, std::vector<float> (hiden_amount,0.00));
 
std::vector<std::vector<float>> input_weights (input_amount, std::vector<float>(hiden_amount,0.00));
std::vector<std::vector<std::vector<float>>> hiden_weights (hiden_deep - 1, std::vector<std::vector<float>> (hiden_amount, std::vector<float> (hiden_amount, 0.00)));
std::vector<float> output_weights (hiden_amount, 0.00);
 
weights_random_filling(input_weights, hiden_weights, output_weights);
for(int a = 0; a < itteration_amount; a++) {
    int index = random_input();
    for(int b = 0; b < input_amount; b++) {
    input_data.at(b) = inputs.at(index).at(b);
    std::cout << "input at " << b + 1 << "is : " << input_data.at(b) << "\n";
       }
   neuron(hiden_data, input_data, output_data, input_weights, hiden_weights, output_weights);
    std::cout << "answer is : " << output_data << " and error is : " << end_error(output_data, right.at(index)) << " %  \n";
    new_weights(hiden_deltas, input_weights, hiden_weights, output_weights, hiden_data, input_data, output_data, right.at(index));
  }
return 0;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.08.2019, 20:09
Ответы с готовыми решениями:

Нейронная сеть на с++
Ребята, словом, это программа составлена на borland c++ builder 5. Я её попытался реализовать на VS. ( Не я составлял программу). Но VS...

Синтезирующая нейронная сеть
Я конечно понимаю, что в этом разделе форума обсуждается OpenCV, но более подходящего места для подобного вопроса я не нашёл... Я пытаюсь...

Элементарная нейронная сеть
Всем доброго времени суток, уважаемые программисты. Хочу попросить у вас помощи в понимании того, каким образом можно реализовать...

7
Модератор
Эксперт С++
 Аватар для zss
13771 / 10964 / 6491
Регистрация: 18.12.2011
Сообщений: 29,241
19.08.2019, 20:45
Посмотрите ссылки внизу страницы
0
2628 / 1640 / 266
Регистрация: 19.02.2010
Сообщений: 4,353
20.08.2019, 12:36
Цитата Сообщение от Eternal_void Посмотреть сообщение
pow(2.71,
Намекаю, что в сишной библиотеке стандартных мат.функций функция exp() присутствовала всегда

Цитата Сообщение от Eternal_void Посмотреть сообщение
float number = rand() % 50 + 1;
* * float a = (float)((1 / (number)) - 0.5);
((float)rand())/RAND_MAX сразу даёт число в пределах [0,1] - дальше сдвигайте на 0.5.
2 арифм. операции вместо Ваших четырёх.

Дальше код с пропавшими отступами не читабелен - и мне лень ломать глаза.
0
0 / 0 / 0
Регистрация: 19.08.2019
Сообщений: 2
21.08.2019, 14:20  [ТС]
Ох, я не заметил, что пропуски отсутствуют, просто с телефона скопировал(
В общем код слегка исправил, по советам VTsaregorodtsev, и добавил уточнеий, что смог, уж.
Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <iostream>
#include <vector>
#include <cmath>
#include <ctime>
 
const int input_amount = 3;
const int hiden_deep = 2;
const int hiden_amount = 2;
const float learning_rate = 0.01;
const int itteration_amount = 1000;
const std::vector<std::vector<float>> inputs {{0.00, 0.00, 0.00}, {0.00, 0.00, 1.00}, {0.00, 1.00, 0.00}, {0.00, 1.00, 1.00}, {1.00, 0.00, 0.00}, {1.00, 0.00, 1.00}, {1.00, 1.00, 0.00}, {1.00, 1.00, 1.00}};
const std::vector<float> right { 0.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00};
 
int random_input() {
    return rand() % 8;
}
 
float sigmoid(float number) {
    return 1 / (1 + exp(-number));
}
 
float random_number() {
    return (((float)rand())/RAND_MAX) - 0.5;
}
 
// средняя квадратичная ошибка, будет выводится в конце каждой итеррации:
 
float end_error(float actual, float right) {
    return (actual - right)*(actual - right)*100;
}
 
 
 
// функция занолнения случайными весами нейроны в начале : 
 
void weights_random_filling(std::vector<std::vector<float>> &input_weights, std::vector<std::vector<std::vector<float>>> &hiden_weights, std::vector<float> &output_weights) {
for(int a = 0; a < input_amount; a++) {
    for(int b = 0; b < hiden_amount; b++) {
    input_weights.at(a).at(b) = random_number();
    }
}
if(hiden_deep > 1) {
   for(int a = 0; a < hiden_deep - 1; a++) {
       for(int b = 0; b < hiden_amount; b++) {
           for(int c = 0; c < hiden_amount; c++) {
           hiden_weights.at(a).at(b).at(c) = random_number();
           }
       }
   }
}
for(int a = 0; a < hiden_amount; a++) {
   output_weights.at(a) = random_number();
   }
}
 
 
 
// регулировка весов в процессе обучения (обратное распостранение) : 
 
void new_weights(std::vector<std::vector<float>> &hiden_deltas, std::vector<std::vector<float>> &input_weights, std::vector<std::vector<std::vector<float>>> &hiden_weights, std::vector<float> &output_weights,std::vector<std::vector<float>> hiden_data, std::vector<float> input_data, const float &output_data, const float &right_answer) {
float weights_delta = (output_data - right_answer) * output_data * (1 - output_data);
for(int a = hiden_amount - 1; a >= 0;a--) {
   output_weights.at(a) -= hiden_data.at(hiden_deep - 1).at(a) * learning_rate * weights_delta;
   hiden_deltas.at(hiden_deep - 1).at(a) = (weights_delta * output_weights.at(a)) * (hiden_data.at(hiden_deep - 1).at(a) * (1 - hiden_data.at(hiden_deep - 1).at(a)));
}
for(int a = hiden_deep - 2; a >= 0; a--) {
   for(int b = hiden_amount - 1; b >= 1; b--){
       for(int c = hiden_amount - 1; c >= 0; c--) {
       hiden_weights.at(a).at(b).at(c) -= hiden_data.at(a).at(b)* learning_rate * hiden_deltas.at(a + 1).at(c);
       hiden_deltas.at(a).at(b) += ((hiden_deltas.at(a + 1).at(c) * hiden_weights.at(a).at(b).at(c)) * (hiden_data.at(a).at(b) * (1 - hiden_data.at(a).at(b)))/hiden_amount);
         }
    }
}
for(int a = input_amount - 1; a >= 0; a--){
   for(int b = hiden_amount - 1; b >= 0; b--){
      input_weights.at(a).at(b) -= input_data.at(a) * learning_rate * hiden_deltas.at(0).at(b);
      }
   }
}
 
 
 
// цикл обновления весов, умножение предыдущих значений на веса и их сумма :
 
void neuron(std::vector<std::vector<float>> &hiden_data, std::vector<float> &input_data, float &output_data, std::vector<std::vector<float>> &input_weights, std::vector<std::vector<std::vector<float>>> &hiden_weights, std::vector<float> &output_weights) {
for(int a = 1; a < hiden_amount; a++) {
   for(int b = 0; b < input_amount; b++) {
       hiden_data.at(0).at(a) +=input_weights.at(b).at(a) * input_data.at(b);
       }
   hiden_data.at(0).at(a) = sigmoid(hiden_data.at(0).at(a));
}
if(hiden_deep > 1) {
for(int a = 1; a < hiden_deep; a++) {
    for(int b = 1; b < hiden_amount; b++) {
       for(int c = 0; c < hiden_amount; c++) {
          hiden_data.at(a).at(b) += hiden_data.at(a - 1).at(c) * hiden_weights.at(a - 1).at(b).at(c);
                
        }
     hiden_data.at(a).at(b) = sigmoid(hiden_data.at(a).at(b));
      }
   }
}
for(int a = 0; a < hiden_amount; a++) {
    output_data += hiden_data.at(hiden_amount - 1).at(a) * output_weights.at(a);
    }
    output_data = sigmoid(output_data); 
}
 
 
 
// главная функция : 
 
int main() {
srand( time(0));
    
// заполнение всего нулями для стабильной работы std::vector :
     
std::vector<std::vector<float>> hiden_data(hiden_deep, std::vector<float>(hiden_amount,0.00));
std::vector<float> input_data(input_amount, 0.00);
float output_data = 0.00;
// нейрон смещения : 
for(int a = 0; a < hiden_deep; a++) {
   hiden_data.at(a).at(0) = 1.00;
}
std::vector<std::vector<float>> hiden_deltas (hiden_deep, std::vector<float> (hiden_amount,0.00));
 
std::vector<std::vector<float>> input_weights (input_amount, std::vector<float>(hiden_amount,0.00));
std::vector<std::vector<std::vector<float>>> hiden_weights (hiden_deep - 1, std::vector<std::vector<float>> (hiden_amount, std::vector<float> (hiden_amount, 0.00)));
std::vector<float> output_weights (hiden_amount, 0.00);
 
//
 
weights_random_filling(input_weights, hiden_weights, output_weights);
 
//цикл обучения :
 
for(int a = 0; a < itteration_amount; a++) {
    int index = random_input();
    for(int b = 0; b < input_amount; b++) {
    input_data.at(b) = inputs.at(index).at(b);
    std::cout << "input at " << b + 1 << "is : " << input_data.at(b) << "\n";
       }
   neuron(hiden_data, input_data, output_data, input_weights, hiden_weights, output_weights);
    std::cout << "answer is : " << output_data << " and error is : " << end_error(output_data, right.at(index)) << " %  \n";
    new_weights(hiden_deltas, input_weights, hiden_weights, output_weights, hiden_data, input_data, output_data, right.at(index));
}
 
return 0;
}
0
2628 / 1640 / 266
Регистрация: 19.02.2010
Сообщений: 4,353
21.08.2019, 20:38
Основное замеченное:

1) Дельты по нейронам предыдущего слоя надо считать ДО ТОГО, как корректируете веса текущего слоя. Т.е. нельзя будет просто переставить местами строки в паре (63-64, и 69-70 в последней версии кода) - надо будет раскладывать эти расчёты по двум отдельным циклам двойной вложенности.

2) Смещения у нейронов первого скрытого слоя - желательны. У Вас же их, вроде бы, нет (я на шаблонах и просто в Вашем стиле никогда нейронки не писал и писать не буду, поэтому лень внимательно вглядываться в совершенно не совместимый с моими мозгами код).

3) Желание впихнуть смещения прямо в вектор сигналов - добавляет Вам лишнего геморроя (со счётчиками циклов и т.д.). Лучше бы сигналы +1 явно не вводить - т.е. после цикла по синапсам нейрона просто добавить (если это прямое функционирование) вес смещения к получившейся сумме, и аналогично (отдельная строка=операция вне цикла по синапсам) при коррекции весов нейрона. Т.е. веса смещений МОЖНО держать отдельными векторами (по вектору на слой), чтобы названия этих векторов тоже помогали обеспечивать правильность кода (например, если будет цикл по входным сигналам нейрона - то там имя массива смещений НИКАК фигурировать не должно).

4) Есть возможность сэкономить одно умножение на коррекции каждого веса нейросетки, если применить известное со средней школы правило вынесения общего множителя за скобки. Но этот совет уже совсем посторонний к Вашей текущей задаче реализации успешной обучаемости сетки.
0
0 / 0 / 0
Регистрация: 14.03.2021
Сообщений: 2
16.08.2021, 14:37
Можешь посмотреть данный видос, там как раз нейросеть на C++
https://www.youtube.com/watch?v=gBYQWvz13Ds
0
53 / 7 / 1
Регистрация: 06.10.2020
Сообщений: 221
16.08.2021, 19:58
Правильный способ написания нейронной сети:
C++
1
2
3
4
5
6
if(...)
{ if(...)
 { if(...)
  { if(...)
   { if(...)
 {//...
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
16.08.2021, 20:37
Цитата Сообщение от Aleksey_1024 Посмотреть сообщение
Правильный способ написания нейронной сети:
если хочешь потроллить тебе на другой форум !
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.08.2021, 20:37
Помогаю со студенческими работами здесь

Нейронная сеть стремится к 0.5
В любой задаче сеть после кучи эпох начинает выдавать ответы ~0.5. Пробовал менять веса, количество слоев и нейронов, никак. neuron.h ...

Линейная нейронная сеть
Доброго времени суток! Можете скинуть пример простейшей нейронной сети на Си/С++, Матлабе, или Java? У меня есть код для матлаба, но не...

Понятие нейронная сеть
У меня возникли некоторые недопонимания в процессе изучения нейронной сети. 1) Как я понял нейронная сеть - это универсальный...

Нейронная сеть Кохонена
Применить нейронную сеть Кохонена с самообучением для задачи кластеризации. На первом этапе сгенерировать случайные точки на плоскости...

Нейронная сеть, обучение с нуля
Нужен совет экспертов с чего начать. Бегло читала про библиотеки ИИ и остановилась на двух tensorflow и caffe2. Пишу на С++, поэтому...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru