0

我尝试使用 sigmoid 和 relu 函数来实现一个简单的神经网络。使用 sigmoid 函数,我得到了一些不错的输出。但是当使用 relu 时,我得到了 0 或 1 的数组。(我需要 relu 函数,因为我愿意将代码用于某些输出>1)。

def relu(x):
return np.maximum(0,x)

def reluDerivative(x):
  x[x<=0] = 0
  x[x>0] = 1
  return x
training_inputs = np.array([[9, 0 , 1],
[7, 1, 1],
[8, 0, 1],
[5, 1, 1]
])

training_outputs = np.array([[9, 7, 8, 5]]).T

np.random.seed(1)

synaptic_weights = 2 * np.random.random((3,1)) - 1


for iteration in range(100000):

   outputs = relu(np.dot(training_inputs, synaptic_weights))


   error = training_outputs - outputs
   adjustments = error * reluDerivative(outputs)
   synaptic_weights += np.dot(training_inputs.T, adjustments )

print("output after training: \n" , outputs)
4

1 回答 1

1

更新

(感谢包含 relu 和 reluDerivative 方法)

错误确实在reluDerivative(x)方法中。

当你这样做时,x[x<=0] = 0你正在修改给定的 numpy 数组。该参数x不是 的克隆/深层副本outputs,它是完全相同的 numpy 数组。所以当你修改时x,你也在修改outputs

我希望您能弄清楚为什么这会导致错误 - 但如果您需要进一步的解释,请告诉我。

更新 2

看起来代码比上面的问题更多,而且这些问题有点棘手:

  • 如果您使用调试器单步执行代码,您会注意到,不幸的是,使用当前随机种子 (1),突触权重被初始化,这样您的所有训练示例都会产生负点积,然后 ReLU 将其设置为零. 零的梯度为零,这是使用 ReLU 的风险之一。如何减轻这种情况?

    • 好吧,您可以使用其他种子(例如,seed=10),但这不是一个令人满意的解决方案
    • 如果你有一个更大的训练集(例如 100 而不是只有 4 个),这个问题的可能性就会小得多,因为所有 100 个都不太可能导致负点积。
    • 我注意到每个数据行中的第一项都比其他项大得多。对数据集执行“标准化”可以避免这个问题。您可以阅读有关如何规范化输入的更多信息。
    • 最后,ReLU 的这种“零梯度”问题正是“LeakyReLU”被发明的原因。在较大的神经网络中,常规 ReLU 可能就足够了,但在您的简单示例中,LeaklyReLU 肯定会避免这个问题。
  • 一旦你解决了上述这些问题,你仍然会注意到另一个问题。错误和梯度将在几次迭代中爆炸。这是因为您尚未使用“学习率”参数来限制权重更新的速率。阅读如何使用学习率(或 alpha)参数。

祝你好运!

于 2019-09-26T02:15:35.563 回答