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

Неправильно обучается нейросеть

22.08.2019, 15:31. Показов 1992. Ответов 5

Студворк — интернет-сервис помощи студентам
Вопрос, наверное, плохой, но уже не знаю что делать. Пишу нейросеть с 2 входными нейронами, одним скрытым слоем с 4 нейронами, и 2 выходных. Я имею:
Класс Weight (класс для синапса): есть свойства "left" и "right" типа Neuron, а так же свойство "value" для обозначения веса (double).
Класс Neuron (класс для нейрона): свойства "weights" и "inWeights" (массивы типа Weight). Первый - для синапсов, исходящих от нейрона, второй - для синапсов, направленных в нейрон. Свойство "delta" для дельты нейрона.
Класс Layer (для слоя): есть свойство "neurons" (массив типа Neuron).
Класс NeuralNetwork (собственно, сеть): свойство Layers(нужно объяснять?). Layers[2] - выходной слой.

Я бы мог просто дать код, но тогда бы этот вопрос был типа "вот вам код, разберитесь что не так".
Что будет делать нейросеть: на вход даём 2 числа (1 или 0). Результат первого выходного нейрона - XOR этих чисел, результат второго - XAND.
Вот метод Learn в классе NeuralNetwork:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void Learn(int[] data, int[] ideal) //data - данные для работы сети, ideal - для обучения
        {
            Work(data); //делаем передачу вперёд для получения результата
            double[] actual = new double[] { Layers[2].neurons[0].input, Layers[2].neurons[1].input}; //массив для результата нейросети
            for(int i = 0; i < Layers[2].neurons.Length; i++)
            {
Layers[2].neurons[i].delta = (ideal[i] - actual[i]) * ((1 - actual[i]) * actual[i]); //вычисляем дельту каждого выходного нейрона
                for(int j = 0; j < Layers[2].neurons[i].inWeights.Count; j++)
                {
                    Layers[2].neurons[i].inWeights[j].value = Layers[2].neurons[i].inWeights[j].value - Layers[2].neurons[i].inWeights[j].left.input
                        * 0.1 * Layers[2].neurons[i].delta; //меняем веса скрытого слоя
                    Layers[2].neurons[i].inWeights[j].left.error = Layers[2].neurons[i].delta * Layers[2].neurons[i].inWeights[j].value; //вычисляем ошибку каждого скрытого нейрона
                    Layers[2].neurons[i].inWeights[j].left.delta = Layers[2].neurons[i].inWeights[j].left.error * (1 - Layers[2].neurons[i].inWeights[j].left.input) 
                        * Layers[2].neurons[i].inWeights[j].left.input; //и дельту
                    for (int a = 0; a < Layers[2].neurons[i].inWeights[j].left.inWeights.Count; a++)
                    {
                        Layers[2].neurons[i].inWeights[j].left.inWeights[a].value = Layers[2].neurons[i].inWeights[j].left.inWeights[a].value
                            - Layers[2].neurons[i].inWeights[j].left.inWeights[a].left.input * 0.3 * Layers[2].neurons[i].inWeights[j].left.delta; //меняем веса входного слоя
                    }
                }
            }
Потом в main я пишу следующее:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Layer[] lay = new Layer[3]; //слои сети
            lay[0] = new Layer(NeuronType.Input, 2); //указываем тип нейронов и их количество
            lay[1] = new Layer(NeuronType.Hidden, 4);
            lay[2] = new Layer(NeuronType.Output, 2);
            NeuralNetwork NN = new NeuralNetwork(lay); //подаём массив слоёв
            int[] d = new int[] { 1, 1, 1, 0, 0, 1, 0, 0 }; //данные для работы сети (читается парами в цикле)
            int[] learn = new int[] { 0, 1, 1, 0, 1, 0, 0, 1 }; //данные для обучения (читается парами в цикле)
            for (int a = 0; a < 5; a++) //подаём сети на ввод все данные по порядку 5 раз
            {
                for (int i = 0; i < 8; i += 2)
                {
                    NN.Work(new int[] { d[i], d[i + 1] }); //работа сети
                    WriteLine(NN.Layers[2].neurons[0].input.ToString() + " " + NN.Layers[2].neurons[1].input.ToString());//вывод
                    NN.Learn(new int[] { d[i], d[i + 1] }, new int[] { learn[i], learn[i + 1] }); //обучение
 
                }
            }
Вот что получается в консоли:

0,852210360077681 0,82908578060323
0,954972387167715 0,943151589006229
0,95494799083375 0,943593736898526
0,953187409341935 0,942364864217283
0,956916543163962 0,946126201500646
0,956654618024507 0,945444992877915
0,95590592471756 0,944981959661313
0,954138436648871 0,943716961875468
0,957829733756037 0,947448620990524
0,957550167675213 0,94676507529644
0,956811152355055 0,946293631572523
0,955055554832821 0,945014636414085
0,95871049370678 0,948717428335963
0,958414397185524 0,948031859373236
0,957684872229569 0,947552997978094
0,955941074869534 0,946261530336712
0,959560384681489 0,94993551680857
0,959248774892242 0,949248196015417
0,958528554737874 0,948762825048352
0,956796465993338 0,947460291465876
0,960380852728539 0,951105565855228
0,959592061471054 0,950329631805967

Результат, почему-то, только увеличивается. Это только если генерировать веса от 0 до 1. Если генерировать их от -1 до 1, получается что-то такое:

0,358196882332513 0,33810444999961
0,379808951901738 0,341043411257091
0,366483534164459 0,328430389359288
0,284765417929902 0,2456195980602
0,389840314390435 0,35449617387211
0,376634196711263 0,336212460356599
0,362034513794386 0,323478223694895
0,280463988844663 0,241154985905794
0,38546647012055 0,349655261693114
0,372018308756311 0,331056646558477
0,35733119041086 0,318333251046109
0,275996632256886 0,236539666970238
0,380886640218297 0,344597982026318
0,367183430172728 0,325673202882944
0,352414483749225 0,312972930273048
0,271359047926998 0,231768310952576
0,37608900160482 0,339312909412778
0,362117062020839 0,320051044450856
0,347273277285281 0,307387911751381
0,266544867226751 0,226836839042086
0,371061169945926 0,333788420510768
0,345399756942264 0,303503240855514
В чём может быть проблема?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
22.08.2019, 15:31
Ответы с готовыми решениями:

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

Двухслойный персептрон, алгоритм BP. Не обучается, запоминает только последний заученный образ
Доброго времени суток. Для моей научной работы мне понадобился двухслойный персптрон (вместо реализованного однослойного). Алгоритм...

Нейросеть
using System; using System.IO; using System.Runtime.InteropServices; namespace ClassLibraryNeuralNetworks { //...

5
2615 / 1627 / 265
Регистрация: 19.02.2010
Сообщений: 4,318
22.08.2019, 18:39
Цитата Сообщение от ITLDS Посмотреть сообщение
В чём может быть проблема?
Шаг обучения завышен на пару порядков.
Попробуйте вместо 0.3 что-то типа 0.001.

Насчёт правильности кода - ХЗ, ибо с моими глазами и мозгами такой стиль совершенно не совместим.
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,214
22.08.2019, 19:17
double[] actual = new double[] { Layers[2].neurons[0].input, Layers[2].neurons[1].input}; //массив для результата нейросети
input - это у вас выход? Или таки вход?

Добавлено через 4 минуты
Уфф, тяжело же читать ваш код. По-хорошему, каждый слой в НС должен быть просто двумерным массивом, где
кол-во строк - число нейронов в слое.
Столбцов - размер входного вектора. Если для полносвязной сети.

Добавлено через 2 минуты
Я вижу, что у вас вычисляется какая-то дельта, пока не будем обсуждать, правильно ли она вычисляется.
Что смущает, так что к Layers идет обращение только по индексу 2. А где же скрытый слой обучаться будет? Скрытый слой не обучается? У вас 3 слоя, значит обучаться должны все три слоя.

+

Добавлено через 1 минуту
Цитата Сообщение от ITLDS Посмотреть сообщение
Что будет делать нейросеть: на вход даём 2 числа (1 или 0). Результат первого выходного нейрона - XOR этих чисел, результат второго - XAND.
А что тогда делает скрытый слой?
0
2 / 2 / 0
Регистрация: 06.07.2019
Сообщений: 29
23.08.2019, 08:02  [ТС]
input - это скорее выход, не знаю почему, но я решил сделать вместо input и output сделать только одно. Сейчас понял, что это плохое решение. Вот метод "Work" в классе Neuron:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if(type == NeuronType.Input)
            {
                this.input = input; 
                for(int i = 0; i < weights.Count; i++)
                {
                    weights[i].right.input += this.input * weights[i].value;
                }
            }
            else if(type == NeuronType.Hidden)
            {
                this.input = 1 / (1 + Exp(this.input - (this.input * 2)));
                for (int i = 0; i < weights.Count; i++) 
                {
                    weights[i].right.input += this.input * weights[i].value;
                }
            }
            else
                this.input = 1 / (1 + Exp(this.input - (this.input * 2)));
То есть, тут мы считаем выход нейрона и передаём данные дальше.
Насчёт скрытого слоя, мы его обучаем там же, в том же цикле, он вложенный.

Добавлено через 25 минут
Попробовал другие формулы, с вычислением градиента для каждого веса, брал формулы отсюда: https://habr.com/ru/post/313216/
Вот что выходит: когда я обучаю сеть на одном примере несколько раз, ошибка уверено падает, но когда я даю другой пример, сеть выдаёт тот же результат, что и с тем примером. Начинаю обучать на другом примере - то же самое. Код нужен?
0
2615 / 1627 / 265
Регистрация: 19.02.2010
Сообщений: 4,318
23.08.2019, 10:08
this.input = 1 / (1 + Exp(this.input - (this.input * 2)));
Зачем используется подчёркнутое?
Ведь школьная математика же, и итогом должно быть классическое
this.input = 1 / (1 + Exp(-this.input));


И у Вас в обратном распространении (первый код в первом посте, строка 7) взята производная для СОВСЕМ ИНОЙ нелинейной функции Сравните там 7 со строками 13-14.
0
2 / 2 / 0
Регистрация: 06.07.2019
Сообщений: 29
23.08.2019, 11:55  [ТС]
Исправил всё на формулу на 13 строке, ничего нового.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.08.2019, 11:55
Помогаю со студенческими работами здесь

Простая нейросеть
Привет всем! Есть задача: Научить нейросеть ставить диагноз. 1 диагноз - 1 сеть. Сеть 3 слоя: входные нейроны (результаты...

Нейросеть Хопфилда
Всем привет, не знаю в какую тему писать, поэтому сюда. Ищу доступную информацию по реализации сети Хопфилда, нашел вот такую статейку для...

Нейросеть для окрашивания изображений
Здравствуйте! Есть необходимость перевести (задача написать нейросеть для раскрашивания изображений, используя C#) код одной известной...

Нейросеть, которая распознает символ
Здравствуйте,формучане. у меня такая задача-нужно сделать нейросеть, которая распознает символ,но не по картинке а по ее бинарнику. Есть...

Научить нейросеть переводить двоичные числа в десятиричные
В общем. Задание :научить нейросеть переводить двоичные числа в десятиричные. С чего начинать вообще без понятия, как вообще устроить...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1 У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\ А в самом низу файла-профиля. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru