【问题标题】:Neural Network Issue with Back Propagation Calculation反向传播计算的神经网络问题
【发布时间】:2019-11-06 11:19:07
【问题描述】:

我目前正在尝试构建一个简单的神经网络,以使用 MNIST 数字数据库来识别书面数字。当我运行第一个测试时,我在输出数组中得到随机分类的概率,这是预期的。但是,当我多次运行它时,我的输出数组在所有索引位置几乎都降为零。似乎我对正在反向传播的权重调整的计算导致了一个问题,但我似乎无法找出原因。

def sigmoid(x):
    a = 1 / (1 + np.exp(-x))
    return a

def sigmoid_derivative(x):
    return x * (1 - x)

def train(n, inputs):
    input_layer = inputs
    weights1 = 2 * np.random.random ((784 , 16)) - 1
    weights2 = 2 * np.random.random ((16 , 10)) - 1

    for i in range(n):
        trained_hidden = sigmoid(np.dot(input_layer, weights1))
        trained_outputs = sigmoid(np.dot(trained_hidden, weights2))

        o_error = (outputs - trained_outputs)
        o_adjustments = o_error * sigmoid_derivative(trained_outputs)

        h_error = np.dot(o_adjustments, weights2.T)
        h_adjustments = h_error * sigmoid_derivative(trained_hidden)

        w1 = np.dot(input_layer.T, h_adjustments)
        w2 = np.dot(trained_hidden.T, o_adjustments)

        weights1 += w1
        weights2 += w2

    return trained_outputs

我正在使用 Numpy 数组,输入是一个 (10000 x 784) 数组,灰度值为 0 - 1,输出它是一个 (10000 x 10) 数组,实际数字的索引位置为 1。

x_train, t_train, x_test, t_test = mnist.load()

inputs = x_test/256

outputs = np.zeros((10000,10), dtype=int)

for i in range(10000):
    x = t_test[int(i)]
    outputs[i][x] = 1

set = train(10, inputs)

我使用了许多资源来构建它,包括来自 3 blue 1 brown 神经网络系列的理论和紧随此处提供的示例的代码 (https://enlight.nyc/projects/neural-network/)

编辑:根据@9000 的建议,这里是一个示例中每个步骤的打印输出。查看结果,看起来 w1(权重调整计算)是问题所在,但一遍又一遍地查看它,我无法弄清楚它为什么不正确,感谢任何帮助。

编辑 2:我在第二次训练运行中包含了同一示例的第二次打印输出。

首次运行

trained_hidden [0.87880514 0.4789476  0.38500953 0.00142838 0.01373613 0.37572408 0.53673194 0.11774215 0.99989426 0.0547656  0.20645864 0.85484692 0.99903171 0.88929566 0.00673453 0.03816501]

trained_output [0.33244312 0.26289407 0.79917376 0.95143406 0.90780616 0.2100068 0.66253735 0.57961972 0.28231436 0.15963378]

o_error [ 0.66755688 -0.26289407 -0.79917376 -0.95143406 -0.90780616 -0.2100068 -0.66253735 -0.57961972 -0.28231436 -0.15963378]

o-adjustment [ 0.14814735 -0.05094382 -0.12826344 -0.04396319 -0.07597805 -0.03484096 -0.14813117 -0.14123055 -0.05720055 -0.02141501]

h_error [-0.00359599  0.18884347  0.15954247 -0.14839811  0.2081496  -0.01152563 0.03262859 -0.46315722 -0.06974061 -0.46774417 -0.00690463 -0.44303219 -0.16267084 -0.02505235 -0.12866526  0.22212537]

h_adjustment [-3.82997246e-04  4.71271721e-02  3.77760172e-02 -2.11665993e04 2.81989626e-03 -2.70339996e-03  8.11312465e-03 -4.81122794e02 -7.37327102e-06 -2.42134002e-02 -1.13120886e-03 -5.49730579e-02 -1.57359939e-04 -2.46637616e-03 -8.60664795e-04  8.15387570e-03]

w1 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

w2 [-111.70644608 -164.50671691 -254.60942018 -205.06537232 -330.43317768 -94.6976 -346.78221607 -272.22044431 -249.54889015  -75.99543441]

weights1 [-0.09535479 -0.09824519 -0.11582134 -0.65075843 -0.65593035  0.77593957 -0.0406199 0.12669151  0.79979191 -0.52502487 -0.2433578 0.16617536 -0.25711996  0.92995152 -0.40922601 -0.63029133]

weights2 [-112.24597022 -164.86741004 -254.21715269 -205.27326963 -331.18579697 -95.07615178 -347.04311247 -271.82206581 -250.04075852  -76.69273265]

第二次运行

trained_hidden [0.00000000e+000 1.00000000e+000 1.00000000e+000 3.77659154e-181 1.00000000e+000 0.00000000e+000 0.00000000e+000 0.00000000e+000 1.00000000e+000 0.00000000e+000 1.00000000e+000 0.00000000e+000 2.71000625e-055 0.00000000e+000 0.00000000e+000 1.00000000e+000]

trained_output [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

o_error [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

o-adjustment [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

h_error [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

h_adjustment [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

w1 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

w2 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

weights1 [-0.09535479 -0.09824519 -0.11582134 -0.65075843 -0.65593035  0.77593957 -0.0406199   0.12669151  0.79979191 -0.52502487 -0.2433578   0.16617536 -0.25711996  0.92995152 -0.40922601 -0.63029133]

weights2 [-112.24597022 -164.86741004 -254.21715269 -205.27326963 -331.18579697 -95.07615178 -347.04311247 -271.82206581 -250.04075852  -76.69273265]

【问题讨论】:

  • 我会从打印每一步结果的直方图开始,以了解哪个操作最终会产生一些意想不到的结果。
  • 由于 sigmoid 函数,您可能会遇到数值问题。这可能不是您的问题,但您可以检查 sigmoid here 的良好且稳定的实现。
  • @AlCorreia 感谢您的建议,我尝试了您链接到的稳定实现,不幸的是我得到了相同的结果

标签: python numpy neural-network


【解决方案1】:

首先,您确定您打印的 weights1 和 weights2 正确吗?它们在两次运行之间是相同的,但输出非常不同,这对我来说似乎很可疑。

我稍微检查了你的派生词,从我调查的一点点来看,它们看起来是正确的。但是,我看到两个错误。更新权重时,您实际上希望减去权重的导数。因为梯度总是指向上坡,并且您希望最小化损失,因此您希望朝下坡方向前进。第二个可能的错误是您使用全导数作为更新,基本上总是在神经网络中,使用学习率(例如 0.001)作为更新导数的乘数,如果您不按比例缩小您的更新前的梯度,它可能会非常难以过冲,例如将所有权重设置为非常大的值,这会导致优化非常不稳定。

所以我的建议是替换:

weights1 += w1
weights2 += w2

与:

learning_rate = 0.001
weights1 -= w1 * learning_rate
weights2 -= w2 * learning_rate

此外,调试神经网络的一般经验法则是使用适合您的网络的最小示例,因此请从您的数据集中选择一个样本并查看每次迭代中的更新,这会告诉您很多信息(例如,使用调试器)。如果你不能适应单个例子,你就不能适应 10000。

【讨论】:

  • 例如将所有权重设置为非常大的值,这会导致优化非常不稳定。 -- 这正是正在发生的事情,进行了建议的更改,一切似乎都在工作现在!谢谢!
猜你喜欢
  • 2011-10-28
  • 2016-02-19
  • 2015-03-03
  • 2012-02-21
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
  • 2018-05-17
相关资源
最近更新 更多