【发布时间】:2020-04-28 16:27:11
【问题描述】:
我一直在研究 Q 强化学习实现,其中 Q(π, a) 是用神经网络近似的。在故障排除过程中,我将问题简化为非常简单的第一步:训练 NN 来计算 atan2(y, x)。
我正在使用 FANN 来解决这个问题,但这个库在很大程度上是无关紧要的,因为这个问题更多的是关于要使用的适当技术。
我一直在努力教 NN,给定输入 = {x, y},计算输出 = 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) 上使用线性激活函数。没有运气。事实上,结果要糟糕得多。经过 100,000,000 次迭代,我们得到:
测试 atan2(0.949040, 0.756997) = 0.897493 -> 7.648625
这比权重随机初始化时更糟糕。 NN 怎么会在训练后变得更糟?
我发现FANN_LINEAR 的这个问题与其他测试一致。当需要线性输出时(例如,在计算 Q 值时,它对应于任意大或小的奖励),这种方法会惨遭失败,并且错误实际上会随着训练而增加。
那么发生了什么?使用完全连接的 2-3-1 NN 是否不适合这种情况?隐藏层中的对称 sigmoid 激活函数是否不合适?我看不出还有什么可能导致此错误。
【问题讨论】:
-
您有特定的硬件限制吗?您为什么选择这种网络架构?
标签: c++ machine-learning neural-network fann