训练NN计算atan2(y,x)

时间:2020-01-11 04:01:45

标签: c++ machine-learning neural-network fann

我一直在研究Q强化学习的实现,其中Q(π,a)用神经网络来近似。在排除故障期间,我将问题简化为一个非常简单的第一步:训练一个NN以计算atan2(y,x)。

我正在使用FANN来解决此问题,但是由于该问题更多地与要使用的适当技术有关,因此库在很大程度上无关紧要。

在输入= {x,y}的情况下,我一直在努力教NN,以计算输出= atan2(y,x)。

这是我一直在使用的幼稚方法。这是非常简单的,但是我正在尝试使其保持简单。

#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)上使用线性激活函数。没有运气。实际上,结果要差得多。经过1亿次迭代,我们得到:

测试atan2(0.949040,0.756997)= 0.897493-> 7.648625

这比随机初始化权重时还要糟糕。训练后,NN怎么会变得更糟?

我发现FANN_LINEAR的此问题与其他测试一致。当需要线性输出时(例如,在Q值的计算中,它对应于任意大或小的奖励),这种方法会严重失败,并且误差实际上会随着训练而增加。

那是怎么回事?在这种情况下使用完全连接的2-3-1 NN是否不合适?隐藏层中的对称S形激活函数是否不合适?我看不到还有什么可能导致此错误。

1 个答案:

答案 0 :(得分:3)

您面临的问题是正常的,并且通过增加迭代次数并不能提高预测变量的质量,您应该通过添加一些层或通过增加隐藏层的大小来增加NN的大小。层。例如,您可以尝试使用2-256-128-1,而不是使用2-3-1。通常,这会更好。如果您想看看这个simple code,我是用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