我下载了一个用PHP编写的XOR门神经网络程序。我想将其修改为适用于其他数据集的程序。仅仅通过更改训练数据集是否可行?
我更改了这部分。我使用了数据集(1,2,1)-(3),(1,4,1)-(5),(2,2,1)-(4),(2,4,1)-(6),而不是XOR门的训练数据集。
代码之前是可以工作的,但仅仅通过更改训练数据集,它对我不起作用。每个数据集的输出都是1。您能帮帮我吗?
<?phprequire_once ("class_neuralnetwork.php");// 创建一个具有3个输入神经元、4个隐藏神经元和1个输出神经元的新神经网络$n = new NeuralNetwork(3, 4, 1);$n->setVerbose(false);// 向网络添加测试数据。在这种情况下,我们希望网络学习'XOR'函数$n->addTestData(array (-1, -1, 1), array (-1));$n->addTestData(array (-1, 1, 1), array ( 1));$n->addTestData(array ( 1, -1, 1), array ( 1));$n->addTestData(array ( 1, 1, 1), array (-1));// 我们尝试最多训练网络$max次$max = 3;echo "<h1>学习XOR函数</h1>";// 在最多1000个周期内训练网络,最大平方误差为0.01while (!($success = $n->train(1000, 0.01)) && ++$i<$max) { echo "第$i轮:未成功...<br />";}// 如果网络成功训练,打印一条消息if ($success) { $epochs = $n->getEpoch(); echo "在$epochs次训练轮次中成功!<br />";}echo "<h2>结果</h2>";echo "<div class='result'>";// 无论如何,我们打印神经网络的输出for ($i = 0; $i < count($n->trainInputs); $i ++) { $output = $n->calculate($n->trainInputs[$i]); echo "<div>测试集$i; "; echo "预期输出 = (".implode(", ", $n->trainOutput[$i]).") "; echo "神经网络输出 = (".implode(", ", $output).")\n</div>";}echo "</div>";//echo "<h2>内部网络状态</h2>";//$n->showWeights($force=true);// 现在,稍微调整一些网络参数,看看它如何影响结果$learningRates = array(0.1, 0.25, 0.5, 0.75, 1);$momentum = array(0.2, 0.4, 0.6, 0.8, 1);$rounds = array(100, 500, 1000, 2000);$errors = array(0.1, 0.05, 0.01, 0.001);echo "<h1>尝试调整...</h1>";echo "<p>以下内容展示了如何通过更改动量和学习率,结合轮次数量和最大允许误差,可以导致结果的巨大差异。为了获得最适合您情况的结果,请尝试调整这些数字,直到找到最适合您的那个。</p>";echo "<p>这里显示的值是随机选择的,因此您可以重新加载页面以查看另一组值...</p>";for ($j=0; $j<10; $j++) { // 无超时 set_time_limit(0); $lr = $learningRates[array_rand($learningRates)]; $m = $momentum[array_rand($momentum)]; $r = $rounds[array_rand($rounds)]; $e = $errors[array_rand($errors)]; echo "<h2>学习率$lr,动量$m @ ($r轮次,最大平方误差$e)</h2>"; $n->clear(); $n->setLearningRate($lr); $n->setMomentum($m); $i = 0; while (!($success = $n->train($r, $e)) && ++$i<$max) { echo "第$i轮:未成功...<br />"; flush(); } // 如果网络成功训练,打印一条消息 if ($success) { $epochs = $n->getEpoch(); echo "在$epochs次训练轮次中成功!<br />"; echo "<div class='result'>"; for ($i = 0; $i < count($n->trainInputs); $i ++) { $output = $n->calculate($n->trainInputs[$i]); echo "<div>测试集$i; "; echo "预期输出 = (".implode(", ", $n->trainOutput[$i]).") "; echo "神经网络输出 = (".implode(", ", $output).")\n</div>"; } echo "</div>"; }}?> </div> </body></html>
回答:
在没有看到神经网络实现代码的情况下,很难给出明确的答案。但看起来实现可能使用了tanh
激活函数,这会将神经元输出限制在(-1, 1)范围内。此外,看起来实现没有使用隐式偏置输入,这就是为什么XOR函数的示例使用第三个输入明确设置为所有情况下的1。
所以基本问题是您所有的目标输出都在激活函数的范围之外。您需要重构您的网络,但具体如何做取决于您想要实现什么。从您的问题来看,不清楚您是试图训练一个分类器还是插值一个函数。
如果您的四个不同输出(3, 5, 4和6)代表类别,那么您应该定义一个具有四个输出的网络,并按以下方式定义期望的输出值:
$n = new NeuralNetwork(3, 4, 4);$n->addTestData(array (1, 2, 1), array ( 1, -1, -1, -1));$n->addTestData(array (1, 4, 1), array (-1, 1, -1, -1));$n->addTestData(array (2, 2, 1), array (-1, -1, 1, -1));$n->addTestData(array (2, 4, 1), array (-1, -1, -1, 1));
请注意,您可能需要为您的示例使用超过4个隐藏节点。
如果您尝试进行函数插值,那么您将保留单个输出神经元,但需要将目标输出值缩放到tanh
函数的范围内。