RNN Решетова переобучается или недообучается?

13 июня 2017, 15:36
Forester
0
474

Я немного поэксперементировал с RNN и похоже, что она просто запоминает примеры обучения (важные в связке с шумовыми предикторами), а на новых данных шумовые предикторы портят результат. Т.е. RNN склонна к переобучению. По крайней мере для логических задач, где 0 и 1.


То что правильность работы RNN нарушает шум можно проверить следущим экспериментом.
Создан советник с оригинальной функцией RNN.

Обучим систему на решение задачи XOR на 1-м и 2-м входах (0 и 1 бит), на 3-й вход подадим не влияющий на задачу XOR шумовой сигнал.

   int    in[8][3] = { {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1} };
В матрице входы идут справа налево {3й,2-й,1й}
Составим правильные ответы
   int    out[8] = { 0,1,1,0,0,1,1,0}; //XOR по 1 и 2 входу, 3-й вход шумовой не должен влиять
Обучим RNN на 75% полной матрицы (6 примеров) и проверим на последних 2-х

Для этого запустим эксперт в тестере, в режиме оптимизации с полным перебором параметров, и в режиме математических вычислений.
Для входных переменных зададим старт = 0, шаг = 100, стоп=100, т.е. по 2 варианта для каждой переменной попробуем, что и нужно для логических задач типа XOR. В программе 100% будет сконвертировано в вероятность, т.е. =1.

После завершения оптимизации получим 255 вариантов. В работу запускать будем с максимальным значением, для этого сортируем список по Custom.

Pass    Custom    x0    x1    x2    x3    x4    x5    x6    x7
230    6    0    100    100    0    0    100    100    100
166    6    0    100    100    0    0    100    0    100
102    6    0    100    100    0    0    100    100    0
38    6    0    100    100    0    0    100    0    0

246    5    0    100    100    0    100    100    100    100
238    5    0    100    100    100    0    100    100    100
231    5    100    100    100    0    0    100    100    100
228    5    0    0    100    0    0    100    100    100
......

Проверять работу RNN на неизвестных (валидационных) данных будем на выборках с максимальным значением Custom=6. Уже по списку с результатами видно, что из 4-х вариантов с Custom=6 только одно полное соответствие обучающей матрице out[8] = { 0,1,1,0,0,1,1,0}.
Это строка:
102    6    0    100    100    0    0    100    100    0  (где 100 соответствует 1 в обучающей матрице.)

Для проверки можно запустить все варианты с Custom=6 в одиночные тесты, двойным кликом.

Получим сообщения для участка "Проверка на новых данных":
для 230    6    0    100    100    0    0    100    100    100
Правильно:110 вычислил 1
ошибка:111 вычислил 1, должен вычислсть 0

для 166    6    0    100    100    0    0    100    0    100
ошибка:110 вычислил 0, должен вычислсть 1
ошибка:111 вычислил 1, должен вычислсть 0

для
102    6    0    100    100    0    0    100    100    0
Правильно:110 вычислил 1
Правильно:111 вычислил 0

для
38    6    0    100    100    0    0    100    0    0
ошибка:110 вычислил 0, должен вычислсть 1
Правильно:111 вычислил 0

Сообщения показывают правильность или ошибочность вычислений RNN.

Таким образом только 1 из 4-х вариантов обучения является верным.
Не зная правильного ответа, мы выберем случайный вариант из этих 4-х, и на новых данным можем иметь ошибку от 0 до 100% (смотря какой вариант возьмем). В среднем 50%.

В итоге можно сделать вывод, что RNN обучилась не решению задачи XOR на 1 и 2 входах, а некоей другой задаче вместе с шумовым входом. Т.е. шум на RNN оказывает значительное влияние, приводящий к ошибке на новых данных в среднем равной 50% (для 4х вариантов мы в сумме имеем 4 правильных и 4 неправильных ответа). И RNN не научилась решать задачу XOR вложенную в первые 2 входа, а обучилась некоей другой задаче с учетом шумового входа.

Т.е. относительно задачи XOR можно сказать, что RNN переобучилась. А относительно задачи "XOR+ шумовой вход" RNN недообучилась, ведь мы не подали на обучение все варианты шума.

Однако, одновременно с этим мы видим абсолютную точность при проверке на известных данных, т.е. ни одной ошибки.
Можно сделать еще один вывод, что RNN очень точно запоминает обучающие данные. И не исключено, что она так же хорошо справится с данными лежащими между 0 и 1. Т.е. хорошо сможет находить ответы в пределах обучающего множества. Т.е. что она будет неплохо интерполировать.
Но это тема для отдельного исследования.

П.С.
Обычная нейросеть решила задачу XOR+ шум лучше, о с не нулевой ошибкой на обучающих примерах. Хотя ошибку в 0,1% смешно считать ошибкой)) Так что обычный MLP на незнакомых данных лучше справился.

Средняя ошибка на обучающем     (75.0%) участке =0.001 (0.1%)
Средняя ошибка на валидационном (25.0%) участке =0.034 (3.4%)

Обучающий участок

 0.00000000, 0.00000000, 0.00000000, 0.00106781
 0.00000000, 0.00000000, 1.00000000, 0.99912817
 0.00000000, 1.00000000, 0.00000000, 0.99887599
 0.00000000, 1.00000000, 1.00000000, 0.00146612
 1.00000000, 0.00000000, 0.00000000, 0.00015709
 1.00000000, 0.00000000, 1.00000000, 0.99958727

Валидация:
 1.00000000, 1.00000000, 0.00000000, 1.00136207
 1.00000000, 1.00000000, 1.00000000, 0.04871333

П.П.С.

Дополнительные эксперименты после изменения советника показали следующие результаты, в сравнении с обычным MLP 3-5-1.

Для проверок использовались разные формулы:

//double func(double d1,double d2,double d3 ){return d1*d2;}   //ошибка 0-2% , т.к. умножение заложено в формулы. 2% получается т.к. генетический оптимизатор не всегда останавливается не на идеальном решении.
//double func(double d1,double d2,double d3 ){return d1*d2*d3;}// ошибка 0-2%  умножение заложено в формулы, на MLP 1%
//double func(double d1,double d2,double d3 ){return MathSin(d1);}// ошибка 2-6%, на MLP 0,1%
//double func(double d1,double d2,double d3 ){return MathSin(d1)*MathSin(d2)*MathSin(d3);}// ошибка 2%, на MLP 1%
//double func(double d1,double d2,double d3 ){return MathSin(d1)*MathSin(d2)*MathSqrt(d3);}// ошибка 3-4%, на MLP 1%
//double func(double d1,double d2,double d3 ){return MathSin(d1)*MathPow(d2,.33)*MathSqrt(d3);}// ошибка 8-4%, на MLP 1.5%
//double func(double d1,double d2,double d3 ){return MathPow(d1,2)*MathPow(d2,.33)*MathSqrt(d3);}// ошибка 8-4%, на MLP 1.5%

В итоге можно сделать вывод, что обычный MLP имеет ошибку в 2-3 раза меньше, чем RNN Решетова. Возможно, часть этой ошибки возникает из за того, что генетический оптимизатор терминала МТ5 останавливается не на идеальном решении.

Прикреплены файлы на которых производилось тестирование и оригинальный RNN c примером торговой стратегии.

Файлы:
Поделитесь с друзьями: