使用小批量时如何更新权重?

C G*_*eee 3 c backpropagation neural-network mini-batch

我正在尝试对我的神经网络实施小批量训练,而不是更新每个训练样本权重的“在线”随机方法。

\n\n

我用 C 开发了一个有点新手的神经网络,我可以调整每层的神经元数量、激活函数等。这是为了帮助我理解神经网络。我已经在 mnist 数据集上训练了网络,但需要大约 200 个 epoch 才能在训练集上实现 20% 的错误率,这对我来说非常糟糕。我目前正在使用在线随机梯度下降来训练网络。我想尝试的是使用小批量。我理解这样的概念:在将误差传播回去之前,我必须累积并平均每个训练样本的误差。当我想计算必须对权重进行的更改时,我的问题就出现了。为了更好地解释这一点,请考虑一个非常简单的感知器模型。一个输入,一个隐藏层,一个输出。为了计算我需要对输入和隐藏单元之间的权重进行的更改,我将使用以下方程:

\n\n

\xe2\x88\x82C/\xe2\x88\x82w1= \xe2\x88\x82C/\xe2\x88\x82O*\xe2\x88\x82O/\xe2\x88\x82h*\xe2\x88\x82h/\ xe2\x88\x82w1

\n\n

如果你进行偏导数,你会得到:

\n\n

\xe2\x88\x82C/\xe2\x88\x82w1=(输出预期答案)(w2)(输入)

\n\n

现在这个公式表示您需要将反向传播误差乘以输入。对于在线随机训练来说这是有意义的,因为每次权重更新您使用 1 个输入。对于小批量训练,您使用了许多输入,那么错误会乘以哪个输入?\n我希望您能帮助我。

\n\n
void propogateBack(void){\n\n\n    //calculate 6C/6G\n    for (count=0;count<network.outputs;count++){\n            network.g_error[count] = derive_cost((training.answer[training_current])-(network.g[count]));\n    }\n\n\n\n    //calculate 6G/6O\n    for (count=0;count<network.outputs;count++){\n        network.o_error[count] = derive_activation(network.g[count])*(network.g_error[count]);\n    }\n\n\n    //calculate 6O/6S3\n    for (count=0;count<network.h3_neurons;count++){\n        network.s3_error[count] = 0;\n        for (count2=0;count2<network.outputs;count2++){\n            network.s3_error[count] += (network.w4[count2][count])*(network.o_error[count2]);\n        }\n    }\n\n\n    //calculate 6S3/6H3\n    for (count=0;count<network.h3_neurons;count++){\n        network.h3_error[count] = (derive_activation(network.s3[count]))*(network.s3_error[count]);\n    }\n\n\n    //calculate 6H3/6S2\n    network.s2_error[count] = = 0;\n    for (count=0;count<network.h2_neurons;count++){\n        for (count2=0;count2<network.h3_neurons;count2++){ \n            network.s2_error[count] = += (network.w3[count2][count])*(network.h3_error[count2]);\n        }\n    }\n\n\n\n    //calculate 6S2/6H2\n    for (count=0;count<network.h2_neurons;count++){\n        network.h2_error[count] = (derive_activation(network.s2[count]))*(network.s2_error[count]);\n    }\n\n\n    //calculate 6H2/6S1\n    network.s1_error[count] = 0;\n    for (count=0;count<network.h1_neurons;count++){\n        for (count2=0;count2<network.h2_neurons;count2++){\n            buffer += (network.w2[count2][count])*network.h2_error[count2];\n        }\n    }\n\n\n    //calculate 6S1/6H1\n    for (count=0;count<network.h1_neurons;count++){\n        network.h1_error[count] = (derive_activation(network.s1[count]))*(network.s1_error[count]);\n\n    }\n\n\n}\n\n\n\n\n\nvoid updateWeights(void){\n\n\n    //////////////////w1\n    for(count=0;count<network.h1_neurons;count++){\n        for(count2=0;count2<network.inputs;count2++){\n            network.w1[count][count2] -= learning_rate*(network.h1_error[count]*network.input[count2]);\n        }\n\n    }\n\n\n\n\n\n    //////////////////w2\n    for(count=0;count<network.h2_neurons;count++){\n        for(count2=0;count2<network.h1_neurons;count2++){\n            network.w2[count][count2] -= learning_rate*(network.h2_error[count]*network.s1[count2]);\n        }\n\n    }\n\n\n\n    //////////////////w3\n    for(count=0;count<network.h3_neurons;count++){\n        for(count2=0;count2<network.h2_neurons;count2++){\n            network.w3[count][count2] -= learning_rate*(network.h3_error[count]*network.s2[count2]);\n        }\n\n    }\n\n\n    //////////////////w4\n    for(count=0;count<network.outputs;count++){\n        for(count2=0;count2<network.h3_neurons;count2++){\n            network.w4[count][count2] -= learning_rate*(network.o_error[count]*network.s3[count2]);\n        }\n\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我所附的代码是我如何进行在线随机更新。正如您在 updateWeights() 函数中看到的,权重更新基于输入值(取决于输入的样本)和隐藏单元值(也取决于输入的输入样本值)。那么,当我拥有要传播回来的小批量平均梯度时,我将如何更新权重?我使用哪些输入值?

\n

C G*_*eee 5

好吧,我明白了。使用小批量时,不应累积并平均网络输出处的误差。每个训练示例的错误都会像平常一样传播回来,只不过不是更新权重,而是累积对每个权重所做的更改。当您循环执行小批量后,您可以对累积进行平均并相应地更改权重。

我的印象是,当使用小批量时,您不必传播任何错误,直到循环完小批量为止。我错了,你仍然需要这样做,唯一的区别是你只有在循环完你的小批量大小后才更新权重。

  • 对于小批量,只有在小批量中的所有样本都向前传播并且梯度已向后传播(权重未更新)之前,才会更新权重,因此在这种情况下,网络的状态(权重值)不会改变,直到所有小批量都被传播。批次样品已处理完毕。这允许您运行任意数量的样本,或者可以使用多个 CPU 或 GPU 线程并行运行。由于网络状态保持不变,前向传播和后向传播变得彼此独立。 (2认同)
  • 另一个性能优势是您只需每 N 次更新一次权重。N 是您的小批量的大小。随着 N 变大,性能也会提高 (2认同)