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\nvoid 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}\nRun Code Online (Sandbox Code Playgroud)\n\n我所附的代码是我如何进行在线随机更新。正如您在 updateWeights() 函数中看到的,权重更新基于输入值(取决于输入的样本)和隐藏单元值(也取决于输入的输入样本值)。那么,当我拥有要传播回来的小批量平均梯度时,我将如何更新权重?我使用哪些输入值?
\n好吧,我明白了。使用小批量时,不应累积并平均网络输出处的误差。每个训练示例的错误都会像平常一样传播回来,只不过不是更新权重,而是累积对每个权重所做的更改。当您循环执行小批量后,您可以对累积进行平均并相应地更改权重。
我的印象是,当使用小批量时,您不必传播任何错误,直到循环完小批量为止。我错了,你仍然需要这样做,唯一的区别是你只有在循环完你的小批量大小后才更新权重。