Обучение NN для расчета atan2 (y, x) - PullRequest
1 голос
/ 11 января 2020

Я работал над реализацией обучения с подкреплением 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 в скрытом слое? Я не вижу, что еще может объяснить эту ошибку.

1 Ответ

3 голосов
/ 14 января 2020

Проблема, с которой вы сталкиваетесь, является нормальной, и качество вашего предиктора не улучшится за счет увеличения числа итераций, вы должны увеличить размер своего NN, либо добавив несколько слоев, либо увеличив размер скрытого слой. Вместо 2-3-1 вы можете попробовать 2-256-128-1, например. Обычно это будет работать лучше. Если вы хотите взглянуть на этот простой код , который я написал в python, чтобы выполнить ту же задачу, он хорошо работает

import numpy as np
from numpy import arctan2

from keras.models import Sequential 
from keras.layers import Dense, InputLayer



nn_atan2 = Sequential()
nn_atan2.add(Dense(256, activation="sigmoid", input_shape=(2,)))
nn_atan2.add(Dense(128, activation="sigmoid"))
nn_atan2.add(Dense(1, activation='tanh'))

nn_atan2.compile(optimizer="adam", loss="mse")
nn_atan2.summary()

N = 100000
X = np.random.uniform(size=(N,2) )
y = arctan2(X[:,0], X[:,1])/(np.pi*0.5)

nn_atan2.fit(X,y, epochs=10, batch_size=128)

def predict(x, y):
    return float(nn_atan2.predict(np.array([[x, y]]))*(np.pi*0.5))

Запуск этого кода даст

Epoch 1/10
100000/100000 [==============================] - 3s 26us/step - loss: 0.0289
Epoch 2/10
100000/100000 [==============================] - 2s 24us/step - loss: 0.0104
Epoch 3/10
100000/100000 [==============================] - 2s 24us/step - loss: 0.0102
Epoch 4/10
100000/100000 [==============================] - 2s 24us/step - loss: 0.0096
Epoch 5/10
100000/100000 [==============================] - 2s 24us/step - loss: 0.0082
Epoch 6/10
100000/100000 [==============================] - 2s 23us/step - loss: 0.0051
Epoch 7/10
100000/100000 [==============================] - 2s 23us/step - loss: 0.0027
Epoch 8/10
100000/100000 [==============================] - 2s 23us/step - loss: 0.0019
Epoch 9/10
100000/100000 [==============================] - 2s 23us/step - loss: 0.0014
Epoch 10/10
100000/100000 [==============================] - 2s 23us/step - loss: 0.0010
...