【问题标题】:relu function neural network outputting 0 or 1relu 函数神经网络输出 0 或 1
【发布时间】:2020-01-26 05:45:23
【问题描述】:

我尝试使用 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)

【问题讨论】:

    标签: python machine-learning neural-network sigmoid relu


    【解决方案1】:

    更新

    (感谢包含 relu 和 reluDerivative 方法)

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

    当您执行x[x&lt;=0] = 0 时,您正在修改给定的 numpy 数组。参数x 不是outputs 的克隆/深拷贝,它是完全相同的numpy 数组。所以当你修改x的时候,你也同时修改了outputs

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

    更新 2

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

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

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

    祝你好运!

    【讨论】:

    • 如果我理解你的评论,我应该修改我的 relu 导数函数,这样它就不会改变我的输出。谢谢
    • 我已经尝试过了,但它一直在输出中给我 0
    • 好吧,我自己测试了代码并更新了答案。
    • 非常感谢,我会尝试实现这个并弄清楚发生了什么
    • 我想我已经解决了你之前提到的前四个问题。但是关于学习率和它的效果我没有弄清楚....事实上在我纠正了这四个问题之后仍然有相同的输出