【问题标题】:How to decide activation function in neural network如何确定神经网络中的激活函数
【发布时间】:2014-04-09 10:08:32
【问题描述】:

我正在使用前馈、反向传播、多层神经网络,并且我使用 sigmoid 函数作为激活函数,其范围为 -1 到 1。但最小误差不会低于 5.8,我想要的更少,你可以查看 100000 次迭代后的输出。

我认为这是因为我的输出范围高于 1,而 sigmoid 函数的范围仅为 -1 到 1。任何人都可以建议我如何克服这个问题,因为我想要的输出范围是 0 到 2.5。建议我哪种激活函数最适合这个范围。

【问题讨论】:

    标签: python neural-network backpropagation feed-forward


    【解决方案1】:

    如果您想减少输出错误,调整节点的激活函数之前有几件事需要考虑。

    首先,你有一个偏置节点吗?偏置节点有几个含义,但是 - 与本讨论最相关 - 它们允许将网络输出转换为所需的输出范围。正如this reference 所说:

    在神经网络中使用偏差通过允许分离各个类别的超平面被抵消以获得更好的定位,从而提高了网络解决问题的能力。

    这篇文章提供了一个很好的讨论: Role of Bias in Neural Networks。 这个也不错:Why the BIAS is necessary in ANN? Should we have separate BIAS for each layer?

    第二种方法:通常有助于标准化您的输入和输出。正如您所注意到的,您的 sigmoid 提供了 +/- 1 的范围。当尝试学习范围为 0 到 1000(例如)的函数时,这个小范围可能会出现问题。为了帮助学习,通常缩放和转换输入以适应节点激活函数。在此示例中,可以将范围除以 500,产生 0 到 2 的范围,然后从该范围中减去 1。通过这种方式,输入已被归一化为 -1 到 1 的范围,这更好地拟合了激活函数。请注意,网络输出应该是非规范化的:首先,将输出加 +1,然后乘以 500。

    在您的情况下,您可以考虑将输入缩放 0.8,然后从结果中减去 1。然后将 1 添加到网络输出,然后乘以 1.25 以恢复所需的范围。请注意,此方法可能最容易完成,因为它不会像添加偏置那样直接改变您的网络拓扑。

    最后,您是否尝试过更改隐藏节点的数量?尽管我相信前两个选项更适合提高性能,但您可以尝试一下。 (作为参考,我不记得修改激活函数的形状比选项 1 和 2 更能改善网络响应的实例。)

    以下是关于隐藏层/节点配置的一些很好的讨论: multi-layer perceptron (MLP) architecture: criteria for choosing number of hidden layers and size of the hidden layer? How to choose number of hidden layers and nodes in neural network?

    24 个输入使您的问题成为高维问题。确保您的训练数据集充分覆盖输入状态空间,并确保您是您的测试数据,并且训练数据来自具有相似代表性的总体。 (看看训练神经网络时的“交叉验证”讨论)。

    【讨论】:

    • 实际上我想要的输出范围是 0 到 5000,我尝试将此范围除以 5000,得到结果后我再次乘以 5000,这里的错误已得到纠正。但是我仍然会按照您的建议进行尝试,因为在测试 NN 时,我在训练时仅针对给定的输入组合获得了正确的输出,而对于其他输入,它没有给出正确的输出。这里我使用一个偏置节点,因为我的输入数是 24(节点:24+1),在隐藏层中我使用一般规则,即 (#inputs + #outputs)*(2/3)。
    • 请建议是否有任何规则来初始设置随机权重,我有输入数量:24(二进制 0 和 1)+1 偏差,隐藏节点:18,输出:1(范围: 0 到 5000)。准确的误差曲线应该是多少。
    • 使用随机初始权重。看看这个链接:stackoverflow.com/questions/20027598/…
    • 我对 0 到 5000 的范围做了直接将它除以 5000 并在得到结果乘以 5000 之后。我的错误被最小化了,但是在训练时,结果只出现在给定的输入上,而训练它是在输入之间没有提供所需的输出。请建议...
    • 您是否尝试过按照上面的建议将输入缩放到 -1 到 +1 的范围?你是如何实现你的网络的? MATLAB 还是其他工具?还是编写自己的代码?激活函数的实现相当简单——只要你正确地实现了它,你的问题很可能存在于其他地方。
    【解决方案2】:

    vanilla sigmoid 函数是:

    def sigmoid(x):
        return 1/(1+math.e**-x)
    

    您可以将其转换为:

    def mySigmoid(x):
        return 2.5/(1+math.e**-x)
    

    为了做出你想要的转变

    【讨论】:

    • 我尝试了您建议的选项,但它给出的错误为:OverflowError: (34, 'Numerical result out of range')
    • 是这样的,我可以通过除以某个数字将所需的值设置在 -1 到 1 之间,在得到结果后,我可以再次使用 sigmoid 函数再次将该结果乘以相同的数字。
    • @Latik:您可能无法对 [-1, 1] 输出应用线性变换,因为这会消除激活函数的“sigmoidness”。请将对 mySigmoid 的调用包装在 try/catch 中,并在异常时打印 x 的值。我想知道x 的值是什么导致了这个错误
    猜你喜欢
    • 2014-01-18
    • 2017-12-08
    • 2013-08-20
    • 2014-03-15
    • 2012-12-14
    • 2013-12-20
    • 2019-07-03
    • 2021-02-10
    相关资源
    最近更新 更多