在完成了一系列在线课程并阅读了许多论文后,我开始尝试使用神经网络,但令我惊讶的是,它无法泛化一个简单的按位与操作。
输入:
Inp#1 - 随机生成的0到15之间的数字,缩放到(0,1)范围Inp#2 - 随机生成的16位无符号整数,缩放到(0,1)范围# 代码片段int in1 = (int)rand()%16;int in2 = (int)rand()%(0x0010000);in[0] = (fann_type)(in1/100.0); // 不必担心浮点数四舍五入in[1] = (fann_type)(in2/100000.0); // 不必担心浮点数四舍五入
输出:
Out#1 = 如果inp#2值中由inp#1指定的位为0,则为-1,否则为1# 代码片段int out1 = (in2 & (1<<in1)) ? 1 : -1;out[0] = (fann_type)out1;
网络:尝试了许多不同的变体,下面是一个例子
A. 一个隐藏层,30个神经元, 激活函数(隐藏层):sigmoid, 激活函数(输出层):sigmoid_symmetric(tanh), 训练方法:RPROP 学习率:0.7(默认) 动量:0.0(默认) RPROP增加因子:1.2(默认) RPROP减少因子:0.5(默认) RPROP最小步长:0(默认) RPROP最大步长:50(默认)B. 三个隐藏层,每层30个神经元,参数与A相同C. 尝试了相同的网络,也对输入进行了缩放到(-1,1),并对隐藏层使用了tanh函数。
数据集:5000个样本用于训练,5000个用于测试,5000个用于验证。甚至尝试了更大的数据集,仍然没有成功
# 训练集中的示例0.040000 0.321600 -1 0.140000 0.625890 1 0.140000 0.039210 -1 0.010000 0.432830 1 0.100000 0.102220 1
过程:使用训练集训练网络,并同时监控测试数据的均方误差,以避免可能的过拟合。
库:使用了多个库,但主要尝试了fann,并使用了fanntool作为GUI界面。
有什么想法吗?如果有特别兴趣,可以上传数据集。
回答:
如果我理解你的设置,你尝试做的是:
- 使用2-X-X-X-1的网络架构(其中X为隐藏单元) – 因此有2个输入,一个输出
- 对输入进行按位函数建模
如果这是真的,这是一个非常特殊的问题,并且是一个非常糟糕的架构选择。神经网络不是魔术帽,它们是一个非常大的模型家族。你尝试做的事情没有任何神经网络期望的函数特征。它在输入上完全不平滑,有很多不连续性,实际上是一堆if-else语句。
你应该怎么做?你应该将输入表示为位,因此你应该有32个输入,每个数字16个二进制输入,这样它就能无问题地学习你的函数。你以一种非常特定的方式编码了输入(通过取其十进制表示),并期望你的网络能够对其进行二进制分解然后在其上进行操作。神经网络会学习它,但你可能需要一个相当复杂的网络来实现这样的操作 – 再次强调,原因是你为网络提供了次优的表示,并且构建了一个非常简单的网络,原本设计用于近似平滑函数。