我试图用反向传播算法制作一个简单的人工神经网络。我创建了一个ANN,我相信我已经正确地实现了BP算法,但我当然可能是错的。
现在,我正在尝试训练网络,给它两个0到0.5之间的随机数字(a,b),然后添加它们。然后,当然,每次网络给出的输出都与a + b的理论答案进行比较(这将始终通过sigmoid函数实现)。
奇怪的是,输出总是收敛到介于0和1之间的数字(由于sigmoid函数必须这样),但我输入的随机数似乎对它没有影响。
编辑:抱歉,它似乎没有收敛。这是输出的图像:
权重随机分布在-1和1之间,但我也尝试过0到1之间。
我也试过给它两个常数(0.35,0.9)并尝试训练它吐出0.5。这可以很快地收敛到0.5。如果我在0和1之间给它任意两个随机数,我也训练它吐出0.5,这也有效。
如果相反,我的目标是:
vector<double> target;
target.push_back(.5);
然后它很快收敛,即使是随机输入:
我尝试了几种不同的网络,因为我很容易在网络中添加图层。我使用的标准是一个有两个输入,一个是2个神经元,第二个层只有一个神经元(输出神经元)。但是,我也尝试添加几层,并为它们添加神经元。它似乎没有任何改变。我的学习率等于1.0,虽然我试过它等于0.5,并没有太大的不同。
有没有人知道我可以尝试的任何事情?
这甚至是ANN能够做到的吗?我无法想象它不会,因为他们可以接受训练来做这些复杂的事情。
有什么建议吗?谢谢!
这是我训练的地方:
//Initialize it. This will be one with 2 layers, the first having 2 Neurons and the second (output layer) having 1.
vector<int> networkSize;
networkSize.push_back(2);
networkSize.push_back(1);
NeuralNetwork myNet(networkSize,2);
for(int i = 0; i<5000; i++){
double a = randSmallNum();
double b = randSmallNum();
cout << "\n\n\nInputs: " << a << ", " << b << " with expected target: " << a + b;
vector<double> myInput;
myInput.push_back(a);
myInput.push_back(b);
vector<double> target;
target.push_back(a + b);
cout << endl << "Iteration " << i;
vector<double> output = myNet.backPropagate(myInput,target);
cout << "Output gotten: " << output[0];
resultPlot << i << "\t" << abs(output[0] - target[0]) << endl;
}
编辑:我设置了我的网络,并一直关注本指南:A pdf。我实现了“工作示例3.1”并得到了他们所做的相同的结果,所以我认为我的实现是正确的,至少就他们而言。
答案 0 :(得分:3)
如@macs所述,标准sigmoid的最大输出为1,因此,如果您尝试从[0,1]添加n个数字,那么您的目标应该被标准化,即sum(A1,A2,... ,An)/ n。
答案 1 :(得分:3)
在这样的模型中,sigmoid函数(在输出和中间层中)主要用于生成类似于0/1切换的东西,同时仍然是连续函数,因此使用它来表示数字范围不是这种网络设计的目的。这是因为它的设计主要考虑了分类问题。 当然,还有其他NN模型可以做这种事情(例如,在输出上删除sigmoid并将其保留为子项的总和)。
如果您可以根据输入分类重新定义模型,您可能会获得更好的结果。
网络更适合的类似任务的一些示例:
然而,这些都不会给你你想要的精确度,因为本质上NN更“模糊”