我正在尝试将adadelta应用到我的简单前馈神经网络中
但我觉得我在理解这篇文章时遇到了一些麻烦。
http://arxiv.org/pdf/1212.5701v1.pdf
这是一篇解释/介绍adadelta算法的小文章。
只有1.5页专注于公式。
从部分开始:
算法1在时间t计算ADADELTA更新
问题1 part:'3:Compute Gradient: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代表什么?
谢谢!
答案 0 :(得分:2)
您需要了解的关于AdaDelta的事情是在线机器学习的一般背景。 在线机器学习是您一次一个地获取数据(因此必须在数据进入时更新模型的参数),而不是批次机器学习,您可以在其中生成机器学习模型,同时可以访问整个数据集。
基本上,您有一组数据点以及您尝试以表格形式预测的目标
D = {(A_1,b_1), (A_2,b_2), (A_3,b_3), ...}
其中A_k是第k条训练数据,b_k是正确答案。您通常需要您的机器学习模型(例如分类器或回归器,例如神经网络或可能是线性模型)来更新其内部参数
x = (x_1, x_2, ..., x_n)
因为它一次一个地读入数据点(A_k,b_k),即你希望模型在数据进入时“实时”更新x。这与批量学习相反,你的模型可以同时访问整个数据集D.
现在,我们通常有一个“成本”的概念---在线性回归中,我们试图最小化的成本函数是预测目标值与实际值之间差异的均方根(RMS)目标值。
回顾在线线性回归的定义,您有一个基于stochastic gradient descent的更新步骤,其中参数x根据模型到目前为止看到的所有数据进行更新:
x_new <- x_old - gradient(RMS[predicted-actual])
像AdaGrad和AdaDelta这样的更新规则是提供一种“更好”的方式来执行更新 - 这可能意味着确保参数更快地收敛到最佳值,或者在AdaDelta的情况下,这意味着参数x以适当大小的步长“更接近”其最佳值,步长根据过去的表现而变化。
让我们一次回答你的问题:
更高维度的梯度(即当x由数组表示时)定义为
gt = (∂f/∂x_1, ∂f/∂x_2, ..., ∂f/∂x_n) (xt)
其中f(x1,x2,...,x_n)是您尝试最小化的函数;在大多数情况下,它是单个示例的成本函数,作为x的函数,即模型参数。换句话说:获取成本函数的导数,然后在当前参数xt评估它。
根据我的理解,delta-x的RMS定义为
RMS[\Delta x]_{t-1} = \sqrt{ E[\Delta x^2]_{t-1} + \epsilon },
,其中
E[\Delta x^2]_t = \rho E[\Delta x^2]_{t-1} + (1-\rho) g^2_T,
用
初始化E[\Delta x^2]_0 = 0.
AdaDelta纯粹是一个更新规则。一般结构是这样的:
(new_weights @ T) := (old_weights @ T-1) - [adaptive_learning_rate] * (gradient @ T)
,其中
adaptive_learning_rate := -(RMS[Delta-x] @ T-1)/(RMS[gradient] @ T)
因为AdaDelta的观点是将学习率变为动态值而不是强迫我们在开始时为它选择任意值。
“用Hessian逼近校正单位”背后的想法来自于某种意义上的物理直觉;也就是说,如果给每个变量赋予某种单位(长度/米,时间/秒,能量/焦耳等),那么Hessian就有适当的单位来纠正更新项,以便进行维度分析。
Delta-x是更新后x的差异。因此,如果更新前x_i是您的参数,更新后x_ {i + 1}是您的参数,则Delta-x为(x_ {i + 1} - x_i)。
(∂f/∂x)是您尝试最小化的函数的导数(通常在ML中,f是成本函数)。