Я работал над реализацией обучения с подкреплением Q, где Q (π, a) аппроксимируется нейронной сетью. Во время устранения неполадок я уменьшил проблему до очень простого первого шага: обучите NN вычислять atan2 (y, x).
Я использую FANN для этой проблемы, но библиотека в значительной степени не имеет значения так как этот вопрос больше о подходящей технике для использования.
Я изо всех сил пытался научить NN, учитывая input = {x, y}, вычислять output = atan2 (y, x).
Вот наивный подход, который я использовал. Это очень просто c, но я стараюсь, чтобы все было так просто.
#include "fann.h"
#include <cstdio>
#include <random>
#include <cmath>
int main()
{
// creates a 3 layered, densely connected neural network, 2-3-1
fann *ann = fann_create_standard(3, 2, 3, 1);
// set the activation functions for the layers
fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC);
fann_set_activation_function_output(ann, FANN_SIGMOID_SYMMETRIC);
fann_type input[2];
fann_type expOut[1];
fann_type *calcOut;
std::default_random_engine rng;
std::uniform_real_distribution<double> unif(0.0, 1.0);
for (int i = 0; i < 100000000; ++i) {
input[0] = unif(rng);
input[1] = unif(rng);
expOut[0] = atan2(input[1], input[0]);
// does a single incremental training round
fann_train(ann, input, expOut);
}
input[0] = unif(rng);
input[1] = unif(rng);
expOut[0] = atan2(input[1], input[0]);
calcOut = fann_run(ann, input);
printf("Testing atan2(%f, %f) = %f -> %f\n", input[1], input[0], expOut[0], calcOut[0]);
fann_destroy(ann);
return 0;
}
Очень просто, верно? Однако даже после 100 000 000 итераций эта нейронная сеть дает сбой:
Тестирование atan2 (0,949040, 0,756997) = 0,897493 -> 0,987712
Я также пытался использовать функцию линейной активации для выходной слой (FANN_LINEAR
). Не повезло. На самом деле результаты намного хуже. После 100 000 000 итераций мы получаем:
Тестирование atan2 (0,949040, 0,756997) = 0,897493 -> 7,648625
, что даже хуже, чем при случайной инициализации весов. Как NN может получить хуже после тренировки?
Я обнаружил, что эта проблема с FANN_LINEAR
соответствует другим тестам. Когда необходим линейный выход (например, при вычислении значения Q, которое соответствует произвольно большим или маленьким вознаграждениям), этот подход с треском проваливается, и ошибка фактически увеличивается с обучением.
Так что же происходит? Использование полностью подключенного 2-3-1 NN не подходит для этой ситуации? Является ли неуместной функция активации симметри c в скрытом слое? Я не вижу, что еще может объяснить эту ошибку.