Как совместить информацию по нескольким ТФ для обучения нейросети? - страница 4

 

Vitalii Ananev:

 Например визуально я определяю тренд вверх, а сеть говорит, что вниз, жму кнопочку (SELL) после чего сеть перестраивает свои веса и начинает показывать тренд вниз. Обучил ее сначала на одном временном участке. Потом на втором ... и т.д. В результате сеть запоминает только то что учила на последнем участке, а все предыдущее забывает. Теперь ломаю голову или я не так учу или сеть у меня криво написана (писал на mql4). В общем хотелось бы получить какой нибудь совет по этому поводу. 

подозреваю, что Вы не совсем поняли как работает НС

судя по Вашему сообщению, Вы подали на НС тренировочный набор данных (MA --> SELL) и она обучилась

все - обучение законченно, НС готова по новым данным МА рассчитать выход

а следующие Ваши манипуляции - это новое обучение НС, соответственно Вы и удивлены, что НС забыла свое обучение

НС учат примерно так: есть набор данных = 100 и результатов 10, обучили, далее только проверка качества обучения

ЗЫ: вот я давно разбирался как НС работают, такие же ошибки как у Вас https://www.mql5.com/ru/forum/5010#comment_329034

Библиотеки: Класс нейронной сети MLP
Библиотеки: Класс нейронной сети MLP
  • 2011.10.24
  • www.mql5.com
Статьи и техническая библиотека по автоматическому трейдингу: Библиотеки: Класс нейронной сети MLP
 
Mihail Marchukajtes:

Ну во первых давайте сначала разберемся что у нас с выходом? ЧТо является выходом сети Верх/вниз или же какое то значение? С учителем это я так понимаю Вы сами её учите пошагово? зачем когда это делается программно. Создаете файл обучающий и передаете его в сеть посредством многочисленных итераций или эпохи как это называется. Так что у нас с выходом?

На выходе по идее, когда должен быть тренд вниз логистическая функция активации выдавать должна 0 для тренда вверх соответственно 1. Я вычисляю ошибку. Реально она выдает например 0.8, а должно быть 0, тренд вниз сообщаю ей что ошибка составляет 0.8 она пересчитывает веса на выходном нейроне, рассчитывает ошибку для предыдущего внутреннего слоя и передает ее дальше.

 
Igor Makanu:

подозреваю, что Вы не совсем поняли как работает НС

судя по Вашему сообщению, Вы подали на НС тренировочный набор данных (MA --> SELL) и она обучилась

все - обучение законченно, НС готова по новым данным МА рассчитать выход

а следующие Ваши манипуляции - это новое обучение НС, соответственно Вы и удивлены, что НС забыла свое обучение

НС учат примерно так: есть набор данных = 100 и результатов 10, обучили, далее только проверка качества обучения

ЗЫ: вот я давно разбирался как НС работают, такие же ошибки как у Вас https://www.mql5.com/ru/forum/5010#comment_329034

Да подозреваю, что я не правильно ее учу. То есть мне надо заранее подготовить какой то набор входных данных и какие она должна выдавать результаты. После чего N-ное кол-во раз прогнать обучение  по этим данным.

 
Vitalii Ananev:

Да подозреваю, что я не правильно ее учу. То есть мне надо заранее подготовить какой то набор входных данных и какие она должна выдавать результаты. После чего N-ное кол-во раз прогнать обучение  по этим данным.

Отлично. То есть вы строите классификатор, добро пожаловать в реальный мир, а не то что эти прогнозисты. Ладно теперь далее,по вот этой ссылке выложил обучающий файл в котором только последний столбец является выходом, оостальные входы. Это некое не гласное правило при подготовке обучающей выборки с учителем для классификации. В итоге каждая срока имеет набор значений и самое последнее значение в этой строке является выход. Лучше всего это представляется в таблице ексел  в итоге имеем таблицу из  100 строк. Резервируем часть данных для тестирования. Далее сам процес обучения. Обучающая выборка состоит из 50 строк и мы начинаем по очереди подавать ей данные и при каждом предьялении меняются веса функции активации. Так вот когда мы предьявим сетки все 50 строк это будет считаться одной эпохой, для того что бы сеть более менее смогла оптимизировать веса нужно порядка 10000 эпох. Если, как Вы говорите что делали это в ручную,  хм...... Хотя может я чего то недопонял но мне кажется что руками это просто нереально. Так или иначе смысл обучения в следующем. Там примерно просхидит следующее выподали строку номер один на вход и на выход. Говоря тем самым сети, эй детка настрой мне веса так что бы при вот этих данных у тебя на выходе была единица, а она тебе в ответ, да не вопрос и меняет коэфиценты один раз, не факт что эти коэфиценти приведут к нужному результате, но в соотвестфии с функцией активации коэфиценты будут изменены сокращая ошибку, далее подается вторая строка и снова идет идиничное изменение коэфицентов. В итоге когда закончится первая эпоха. Предоставим сети все 50 строк. В итоге после первой эпохи сеть будет люто ошибатся 100% при последующем прогоне ошибка сети будет снижатся иона все правильней будет давать ответы. С каждой эпохой коэфиценты будут изменятся таким образом что в итоге это приведет к тому что она перестанет ошибатся на всем участке обучения.
 
Самое главное в этом деле не обмануть прежде всего себя, пытаясь схитрить по средством манипуляции данных. И соблюдать правила при сборе и обработке данных. Попробую их сформулировать.
1. При сборе данных нужно строго придерживатся хронологического порядка, не допускать заглядывания в перед. Это приводит к ошоломляющим результатам обучения и является признаком что что то не так.
2. Выходная переменная должна заглядывать в будущее, нести в себе прогностическую состовляющу. Если скажем возник бар вверх, то для обучения мы можем взять все что было до этого бара, но никак сам этот бар или все что с ни связанно. Должна бытьь разница во времени между входом и выходом. О выходе мы узнаем когда событие уже свершилось, знамо на вход можно подать все что предшествовало этому событию именно по времени.
В обще частота сбора данных заслуживает особого внимания при проектировании именно поэтому мне стало интересно по поводу использования данных тругого ТФ, тут как раз высокая вероятность заглянуть невзначей в будущее. Но если все тщательно проверить и не допустить подобного при сохранении данных, тогда использование старшего ТФ вполне может быть уместным. Приведу пример:
 У нас есть 15 М и 1 Н периоды, как нам их подать на вход правильно. Мы стхраняемся каждые 15 минут при закрытии свечи. При зкиытии час у нас есть два значения за закрытый час и за закрытую 15 минутку которая этот час закрывала. После того как у нас закрылась вервая 15 минутка следующего часа мы сохраняем данные и за нее и за предыдущий час и так с каждой свечкой в этом часе,  закрывающая пятнадцатиминутка перепишет значение часа. В итоге часовые данные будут у вас повторятся внутри часа для каждой 15 минутке. Как пример: открытый интерес транслируется только за день в итоге получив его значение я в течении всего дня подаю только его в сеть ну или спользую в расчетах не меняя. Как то так...
 
Mihail Marchukajtes:
Отлично. То есть вы строите классификатор, добро пожаловать в реальный мир, а не то что эти прогнозисты. Ладно теперь далее,по вот этой ссылке выложил обучающий файл в котором только последний столбец является выходом, оостальные входы. Это некое не гласное правило при подготовке обучающей выборки с учителем для классификации. В итоге каждая срока имеет набор значений и самое последнее значение в этой строке является выход. Лучше всего это представляется в таблице ексел  в итоге имеем таблицу из  100 строк. Резервируем часть данных для тестирования. Далее сам процес обучения. Обучающая выборка состоит из 50 строк и мы начинаем по очереди подавать ей данные и при каждом предьялении меняются веса функции активации. Так вот когда мы предьявим сетки все 50 строк это будет считаться одной эпохой, для того что бы сеть более менее смогла оптимизировать веса нужно порядка 10000 эпох. Если, как Вы говорите что делали это в ручную,  хм...... Хотя может я чего то недопонял но мне кажется что руками это просто нереально. Так или иначе смысл обучения в следующем. Там примерно просхидит следующее выподали строку номер один на вход и на выход. Говоря тем самым сети, эй детка настрой мне веса так что бы при вот этих данных у тебя на выходе была единица, а она тебе в ответ, да не вопрос и меняет коэфиценты один раз, не факт что эти коэфиценти приведут к нужному результате, но в соотвестфии с функцией активации коэфиценты будут изменены сокращая ошибку, далее подается вторая строка и снова идет идиничное изменение коэфицентов. В итоге когда закончится первая эпоха. Предоставим сети все 50 строк. В итоге после первой эпохи сеть будет люто ошибатся 100% при последующем прогоне ошибка сети будет снижатся иона все правильней будет давать ответы. С каждой эпохой коэфиценты будут изменятся таким образом что в итоге это приведет к тому что она перестанет ошибатся на всем участке обучения.

Принцип понятен. Сейчас для обучения сделал вот так:

         Comment("Запущено 50 000 обучающих циклов");
         for (int s=1;s<=50000;s++)
         {
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] =  1; VX[5] =  1; VX[6] =  1; VX[7] =  1; VX[8] =  1;
            NeuroNet.LearnOne(1.0,VX,0);

            VX[0] = -1; VX[1] = -1; VX[2] = -1; VX[3] = -1; VX[4] = -1; VX[5] = -1; VX[6] = -1; VX[7] = -1; VX[8] = -1;            
            NeuroNet.LearnOne(0.0,VX,0);

            VX[0] =  0; VX[1] =  0; VX[2] =  0; VX[3] =  0; VX[4] =  0; VX[5] =  0; VX[6] =  0; VX[7] =  0; VX[8] = 0;            
            NeuroNet.LearnOne(0.5,VX,0);
            
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] =  1; VX[5] =  1; VX[6] =  1; VX[7] =  1; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] =  1; VX[5] =  1; VX[6] =  1; VX[7] =  0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] =  1; VX[5] =  1; VX[6] =  0; VX[7] =  0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] =  1; VX[5] =  0; VX[6] =  0; VX[7] =  0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] =  0; VX[5] =  0; VX[6] =  0; VX[7] =  0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  0; VX[4] =  0; VX[5] =  0; VX[6] =  0; VX[7] =  0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] =  0; VX[3] =  0; VX[4] =  0; VX[5] =  0; VX[6] =  0; VX[7] =  0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  0; VX[2] =  0; VX[3] =  0; VX[4] =  0; VX[5] =  0; VX[6] =  0; VX[7] =  0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] =  1; VX[5] =  1; VX[6] =  1; VX[7] =  1; VX[8] = -1;            
            NeuroNet.LearnOne(0.5,VX,0);            
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] =  1; VX[5] =  1; VX[6] =  1; VX[7] = -1; VX[8] = -1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] =  1; VX[5] =  1; VX[6] = -1; VX[7] = -1; VX[8] = -1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] =  1; VX[5] = -1; VX[6] = -1; VX[7] = -1; VX[8] = -1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] =  1; VX[4] = -1; VX[5] = -1; VX[6] = -1; VX[7] = -1; VX[8] = -1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] =  1; VX[3] = -1; VX[4] = -1; VX[5] = -1; VX[6] = -1; VX[7] = -1; VX[8] = -1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] =  1; VX[2] = -1; VX[3] = -1; VX[4] = -1; VX[5] = -1; VX[6] = -1; VX[7] = -1; VX[8] = -1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  1; VX[1] = -1; VX[2] = -1; VX[3] = -1; VX[4] = -1; VX[5] = -1; VX[6] = -1; VX[7] = -1; VX[8] = -1;            
            NeuroNet.LearnOne(0.5,VX,0);


            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =  -1; VX[4] =  -1; VX[5] =  -1; VX[6] =  -1; VX[7] =  -1; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =  -1; VX[4] =  -1; VX[5] =  -1; VX[6] =  -1; VX[7] =   0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =  -1; VX[4] =  -1; VX[5] =  -1; VX[6] =   0; VX[7] =   0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =  -1; VX[4] =  -1; VX[5] =   0; VX[6] =   0; VX[7] =   0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =  -1; VX[4] =   0; VX[5] =   0; VX[6] =   0; VX[7] =   0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =   0; VX[4] =   0; VX[5] =   0; VX[6] =   0; VX[7] =   0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =   0; VX[3] =   0; VX[4] =   0; VX[5] =   0; VX[6] =   0; VX[7] =   0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  0;  VX[2] =   0; VX[3] =   0; VX[4] =   0; VX[5] =   0; VX[6] =   0; VX[7] =   0; VX[8] =  0;            
            NeuroNet.LearnOne(0.5,VX,0);
            
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =  -1; VX[4] =  -1; VX[5] =  -1; VX[6] =  -1; VX[7] =  -1; VX[8] =  1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =  -1; VX[4] =  -1; VX[5] =  -1; VX[6] =  -1; VX[7] =   1; VX[8] =  1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =  -1; VX[4] =  -1; VX[5] =  -1; VX[6] =   1; VX[7] =   1; VX[8] =  1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =  -1; VX[4] =  -1; VX[5] =   1; VX[6] =   1; VX[7] =   1; VX[8] =  1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =  -1; VX[4] =   1; VX[5] =   1; VX[6] =   1; VX[7] =   1; VX[8] =  1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =  -1; VX[3] =   1; VX[4] =   1; VX[5] =   1; VX[6] =   1; VX[7] =   1; VX[8] =  1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =  -1; VX[2] =   1; VX[3] =   1; VX[4] =   1; VX[5] =   1; VX[6] =   1; VX[7] =   1; VX[8] =  1;            
            NeuroNet.LearnOne(0.5,VX,0);
            VX[0] =  -1; VX[1] =   1; VX[2] =   1; VX[3] =   1; VX[4] =   1; VX[5] =   1; VX[6] =   1; VX[7] =   1; VX[8] =  1;            
            NeuroNet.LearnOne(0.5,VX,0);                        
         }

В методе NeuroNet.LearnOne(1.0,VX,0); Первый параметр, это что хочу получить на выходе, второй VX[] - входные данные. И третий номер нейрона выходного слоя на случай если выходов будет несколько. Код конечно не очень красивый но это пока для отладки что бы разобраться как работает обучение. Посмотрите, если есть свободное время, правильно ли я понял процесс обучения? Хочу когда на входе все значения равны 1 сеть на выходе давала 1. Когда на входе все значения -1, хочу на выходе 0. Во всех остальных случаях на выходе нужно 0.5.

 
Vitalii Ananev:

Принцип понятен. Сейчас для обучения сделал вот так:

В методе NeuroNet.LearnOne(1.0,VX,0); Первый параметр, это что хочу получить на выходе, второй VX[] - входные данные. И третий номер нейрона выходного слоя на случай если выходов будет несколько. Код конечно не очень красивый но это пока для отладки что бы разобраться как работает обучение. Посмотрите, если есть свободное время, правильно ли я понял процесс обучения? Хочу когда на входе все значения равны 1 сеть на выходе давала 1. Когда на входе все значения -1, хочу на выходе 0. Во всех остальных случаях на выходе нужно 0.5.

Помимо прочих правил существует еще одно фундаментальное и гласи оно так, если есть возможность реализовать алгоритм без применени НС то следует так и поступить. В вашем случае все рашается простыми условиями програмирования и сеть здесь не нужна. Я признатся код Ваш не смотрел но судя по описанию Вам нужет тринартный классификатор и это уже совсем по другому. Опять опять же считаю превеликой глупостью пихать классификатору ВСЕ бары. Именню поэтому класификатору требуется базовая стратегия чтобы принимать решение в определенное время. Почитайте мою статью, она конечно устарела и я уже долеко продвинулся от написанного там, но общий подход актуален до сих пор.
 
Mihail Marchukajtes:
Помимо прочих правил существует еще одно фундаментальное и гласи оно так, если есть возможность реализовать алгоритм без применени НС то следует так и поступить. В вашем случае все рашается простыми условиями програмирования и сеть здесь не нужна. Я признатся код Ваш не смотрел но судя по описанию Вам нужет тринартный классификатор и это уже совсем по другому. Опять опять же считаю превеликой глупостью пихать классификатору ВСЕ бары. Именню поэтому класификатору требуется базовая стратегия чтобы принимать решение в определенное время. Почитайте мою статью, она конечно устарела и я уже долеко продвинулся от написанного там, но общий подход актуален до сих пор.

Да этот алгоритм можно и без НС сделать. Но я его взял просто для тренировки что бы разобраться как все работает. Сначала, с вашей помощью, вроде получилось ее обучить. Более или менее работала. Потом поменял архитектуру сети. Добавил еще слой и еще нейронов. Начал обучать заново и уже не хочет обучаться. Опять запоминает только то что выучила последним. 

Я не все бары пихаю. А только скользящие средние  разницы цен закрытия последний двух баров. Используется 9- скользящих. Соответственно входных сигналов тоже 9-ть.

Вы имеете ввиду статью  "СЕКВЕНТА ДЕМАРКА ...."? 

 
Vitalii Ananev:

Да этот алгоритм можно и без НС сделать. Но я его взял просто для тренировки что бы разобраться как все работает. Сначала, с вашей помощью, вроде получилось ее обучить. Более или менее работала. Потом поменял архитектуру сети. Добавил еще слой и еще нейронов. Начал обучать заново и уже не хочет обучаться. Опять запоминает только то что выучила последним. 

Я не все бары пихаю. А только скользящие средние  разницы цен закрытия последний двух баров. Используется 9- скользящих. Соответственно входных сигналов тоже 9-ть.

Вы имеете ввиду статью  "СЕКВЕНТА ДЕМАРКА ...."? 

Да именно. Пойми базовая стратегия тебе дает только момент времени для анализа и всего лишь. У секвенты есть ещё одно Важное преимущество это динамическое окно которое сформировано самим рынком. Но опять же базовой стратегией могут быть и простое пересечение машек. В итоге мы получаем срезы рынка в пределёный момент времени, тем самым отсеивая львиную долю не нужно информации (мусор), тем самым резервируя мощности НС которые были бы потрачены на этот мусор в угоду полезной информации или сигналов.

 
Mihail Marchukajtes:

Да именно. Пойми базовая стратегия тебе дает только момент времени для анализа и всего лишь. У секвенты есть ещё одно Важное преимущество это динамическое окно которое сформировано самим рынком. Но опять же базовой стратегией могут быть и простое пересечение машек. В итоге мы получаем срезы рынка в пределёный момент времени, тем самым отсеивая львиную долю не нужно информации (мусор), тем самым резервируя мощности НС которые были бы потрачены на этот мусор в угоду полезной информации или сигналов.

Ладно, буду думать. Информации много, надо все это переварить.