使用适当的 ReLU 导数会阻止学习
Using the Proper ReLU derivative prevents learning
我正在尝试使用 ReLU 作为激活函数来实现反向传播。
如果我没记错的话,该函数的导数对于 x > 0 为 1,对于 x < 0 为 0。
使用这个导数,网络根本不会学习。
在搜索其他示例时,我发现大多数忽略了 X > 0 部分的 1 并将其保留在 x 处,这会导致更好的结果。
我想知道为什么会这样。
为了确保我没有其他错误,这里是训练 1 输入,1 输出无隐藏神经元网络的代码。
我使用均方误差作为误差函数
import random
x = random.uniform(0, 1)
y = random.uniform(0, 1)
w = random.uniform(0, 1)
lr = 0.1
for i in range(500):
z = x * w
yP = z
if yP < 0:
yP = 0
loss = (yP - y)**2
print(i, loss)
grad_y=2.0*(yP - y)
grad_z = grad_y
if z < 0:
grad_z = 0
else :
grad_z = grad_y
grad_w = grad_z * x
w -= lr * grad_w
请注意,这不太可能与网络的大小有关我还在具有 1000 个输入神经元、1 个隐藏层、100 个神经元和 10 个输出神经元的网络上进行了测试。我使用了 64 和 500 个纪元的批量大小。它有同样的问题。
我刚刚意识到我犯了一个多么愚蠢的错误。
根据链式法则grad_y应该乘以ReLU在h处的导数为0或1。这当然相当于如果导数为0就将其设置为0。
我正在尝试使用 ReLU 作为激活函数来实现反向传播。 如果我没记错的话,该函数的导数对于 x > 0 为 1,对于 x < 0 为 0。 使用这个导数,网络根本不会学习。 在搜索其他示例时,我发现大多数忽略了 X > 0 部分的 1 并将其保留在 x 处,这会导致更好的结果。 我想知道为什么会这样。
为了确保我没有其他错误,这里是训练 1 输入,1 输出无隐藏神经元网络的代码。 我使用均方误差作为误差函数
import random
x = random.uniform(0, 1)
y = random.uniform(0, 1)
w = random.uniform(0, 1)
lr = 0.1
for i in range(500):
z = x * w
yP = z
if yP < 0:
yP = 0
loss = (yP - y)**2
print(i, loss)
grad_y=2.0*(yP - y)
grad_z = grad_y
if z < 0:
grad_z = 0
else :
grad_z = grad_y
grad_w = grad_z * x
w -= lr * grad_w
请注意,这不太可能与网络的大小有关我还在具有 1000 个输入神经元、1 个隐藏层、100 个神经元和 10 个输出神经元的网络上进行了测试。我使用了 64 和 500 个纪元的批量大小。它有同样的问题。
我刚刚意识到我犯了一个多么愚蠢的错误。 根据链式法则grad_y应该乘以ReLU在h处的导数为0或1。这当然相当于如果导数为0就将其设置为0。