神经网络示例不使用 sigmoid 激活函数

数据挖掘 Python 神经网络 麻木的 激活函数
2022-03-11 04:35:43

我正在运行用 BogoToBogo 编写的神经网络示例

该程序运行良好:

(array([0, 0]), array([  2.55772644e-08]))
(array([0, 1]), array([ 0.99649732]))
(array([1, 0]), array([ 0.99677086]))
(array([1, 1]), array([-0.00028738]))

神经网络学习 XOR,默认使用 tanh 作为激活函数。但是,在我将激活函数更改为“sigmoid”之后

nn = NeuralNetwork([2,2,1], 'sigmoid')

现在程序输出:

epochs: 0
...
epochs: 90000
(array([0, 0]), array([ 0.45784467]))
(array([0, 1]), array([ 0.48245772]))
(array([1, 0]), array([ 0.47365194]))
(array([1, 1]), array([ 0.48966856]))

4 个输入的输出均接近 0.5。结果表明神经网络(具有 sigmoid 函数)没有学习 XOR。

我期待程序会输出:

  • ~0 表示 (0, 0) 和 (1, 1)
  • ~1 表示 (0, 1) 和 (1, 0)

有人可以解释为什么这个带有 sigmoid 的例子不适用于 XOR 吗?

1个回答

我自己找到了答案。差异的原因是 BogoToBogo ( ) 中 tanh 素数的定义tanh_prime采用了已经应用于激活函数的参数:

def tanh_prime(x):
    return 1.0 - x**2

sigmoid_prime不是。它在其中调用 sigmoid:

def sigmoid_prime(x):
    return sigmoid(x)*(1.0-sigmoid(x))

所以 的定义sigmoid_prime似乎更准确tanh_prime那为什么不sigmoid工作呢?这是因为它们的参数已经与激活函数一起应用。

背景

sigmoid ( ) 和 tanh 的导数具有相同的属性,这些导数可以用 sigmoid 和 tanh 函数本身来表示。σ

dtanh(x)d(x)=1tanh(x)2
dσ(x)d(x)=σ(x)(1σ(x))

在执行反向传播以调整其权重时,神经网络将导数 ( ) 应用于之前应用激活函数的值。在 BogoToBogo 的解释中,这是变量gz(2)

δ(2)=(Θ(2))Tδ(3)g(z(2)).

在其源代码中,变量dot_value保存了这些值。然而,Python 实现使用存储在变量中的向量调用导数a向量在应用激活函数后。为什么?

我将此解释为优化,以利用其导数sigmoidtanh使用其参数仅应用原始函数这一事实。由于神经网络已经保存了激活函数后的值(as a),它可以跳过不必要的调用计算sigmoidtanh计算导数时。这就是为什么tanh_primeBogoToBogo 中的定义在其中不调用 originaltanh的原因。然而,sigmoid_prime另一方面,的定义sigmoid却意外调用函数,导致导函数计算错误。

解决方案

一旦我sigmoid_prime以这样一种方式定义它假设参数已经与 sigmoid 一起应用,那么它就可以正常工作。

def sigmoid_prime(x):
    return x*(1.0-x)

然后调用实现

nn = NeuralNetwork([2,2,1], 'sigmoid', 500000)

成功输出:

(array([0, 0]), array([ 0.00597638]))
(array([0, 1]), array([ 0.99216467]))
(array([1, 0]), array([ 0.99332048]))
(array([1, 1]), array([ 0.00717885]))