【发布时间】:2016-11-22 20:45:00
【问题描述】:
我正在尝试在我的简单前馈神经网络中实现 adadelta
但我认为我在理解这篇文章时遇到了一些麻烦。
http://arxiv.org/pdf/1212.5701v1.pdf
这是一篇解释/介绍 adadelta 算法的小文章。
只有一页半的篇幅是关于公式的。
从零件开始:
算法 1 在时间 t 计算 ADADELTA 更新
问题 1 部分:'3:计算梯度:gt'
我如何在这里计算梯度? 我的方法正确吗:
/* calculating gradient value for neuron what is inside the hidden layer
gradient = sum of ( outcoming connection target's gradient * outcoming connection's weight ) * derivative function */
double CalculatHiddenGradient() {
double sum = 0.0;
for (int i = 0; i < OutcomingConnections.size(); i++) {
sum += OutcomingConnections[i]->weight * OutcomingConnections[i]->target->gradient;
}
return (1.0 - output * output) * sum; // tanh's derivative function
}
// calculating gradient value for output neurons where we know the desired output value
double CalculatGradient(double TargetOutput) {
return (TargetOutput - output) * (1.0 - output * output);
}
问题 2 部分:'5:计算更新:Δxt'
公式 (14) 说如下:
Δxt = -( RMS[Δx]t−1) / RMS[g]t) * gt;
是RMS[Δx]t−1,计算如下:
RMS[Δx]t−1 = sqrt( E[Δx²]t-1 + e )
从公式(9)中取出身体?
根据我目前的理解,我能够写出这段代码:
class AdaDelta {
private:
vector<double> Eg; // E[g²]
vector<double> Ex; // E[∆x²]
vector<double> g; // gradient
int windowsize;
double p; // Decay rate ρ
double e; // Constant e, epsilon?
public:
AdaDelta(int WindowSize = 32, double DecayRate = 0.95, double ConstantE = 0.001) { // initalizing variables
Eg.reserve(WindowSize + 1);
Ex.reserve(WindowSize + 1);
Eg.push_back(0.0); // E[g²]t
Ex.push_back(0.0); // E[∆x²]t
g.push_back(0.0); // (gradient)t
windowsize = WindowSize; // common value:?
p = DecayRate; // common value:0.95
e = ConstantE; // common value:0.001
}
// Does it return weight update value?
double CalculateUpdated(double gradient) {
double dx; // ∆xt
int t;
// for t = 1 : T do %% Loop over # of updates
for (t = 1; t < Eg.size(); t++) {
// Accumulate Gradient
Eg[t] = (p * Eg[t - 1] + (1.0 - p) * (g[t] * g[t]));
// Compute Update
dx = -(sqrt(Ex[t - 1] + e) / sqrt(Eg[t] + e)) * g[t];
// Accumulate Updates
Ex[t] = Ex[t - 1] + (1.0 - p) * (dx * dx);
}
/* calculate new update
=================================== */
t = g.size();
g.push_back(gradient);
// Accumulate Gradient
Eg.push_back((p * Eg[t - 1] + (1.0 - p) * (g[t] * g[t])));
// Compute Update
dx = -(sqrt(Ex[t - 1] + e) / sqrt(Eg[t] + e)) * g[t];
// Accumulate Updates
Ex.push_back(Ex[t - 1] + (1.0 - p) * (dx * dx));
// Deleting adadelta update when window has grown bigger than we allow
if (g.size() >= windowsize) {
Eg[1] = 0.0;
Ex[1] = 0.0;
Eg.erase(Eg.begin());
Ex.erase(Ex.begin());
g.erase(g.begin());
}
return dx;
}
};
问题 3
在反向传播中,更新权重是这样的
目标的梯度 * 源的输出 * 学习率
但在 adadelta 算法中我看不到那个动作。 我应该在调用之前将源的输出与目标的梯度混合吗 CalculateUpdated() 函数还是应该将输出与返回值混合以获得新的权重值?
问题 4
让我一直困惑的部分
3.2。想法 2:使用 Hessian 近似校正单位
我不太明白我们在此处更新了哪些公式部分或发生了哪些变化。 我们在哪里应用下面的公式?
公式 (13) Δx = (Δx/∂f)/∂x;
问题 5
式(13)中的Δx,∂f,∂x分别代表什么?
谢谢!
【问题讨论】:
-
说明您的网络拓扑也很有帮助。有多少层,每层有多少个神经元?
-
我将使用简单的网络来解决异或问题,以便稍后我可以了解如何制作更复杂的网络。一个隐藏层,两个输入,两个隐藏神经元和一个输出。输入和隐藏层具有一个偏置神经元。
-
大卫米勒做了同样的事情所以也许你应该看看他的Tutorial
-
如果我没记错的话,David Miller 使用了某种动量项来优化梯度体面算法,但我正在尝试理解 Adadelta。
标签: c++ machine-learning neural-network