优化器
此页部分伪代码图片来源于 https://blog.csdn.net/qq_39332551/article/details/123440318
基类
struct optimizer {
virtual void upd(vecmap, const vecmap &) = 0;
};
template <const int N>
struct optimizer_holder : public optimizer {
unordered_map<const float *, vec> V[N];
template <const int I>
vec &get(const vecmap &x) {
auto it = V[I].find(x.data());
if (it != V[I].end())
return it->second;
else
return V[I][x.data()] = vec::Zero(x.size());
}
};
optimizer- 所有优化器的基类,包含一个虚函数
void upd(vecmap, const vecmap &)。这个函数传入两个Eigen::Map<VectorXf>类型变量,第一个是系数向量,第二个是系数的梯度向量。需要在这个函数里实现权值更新。 optimizer_holder<int N>- 一个类,对每一个系数矩阵维护对应的 N 个额外矩阵,可以用于维护动量之类的东西
sgd
nesterov
struct nesterov : public optimizer_holder<1> {
float alpha, mu, lambda;
nesterov(float alpha = 0.01, float mu = 0.9, float lambda = 0) : alpha(alpha), mu(mu), lambda(lambda) {}
void upd(vecmap w, const vecmap &gw) {
vec &v = get<0>(w);
w -= mu * v;
v = mu * v - (gw + lambda * w) * alpha;
w += (1. + mu) * v;
}
};

Adam
struct adam : public optimizer_holder<2> {
float lr, rho1, rho2, eps, lambda;
float mult1, mult2;
adam(float lr = 0.001, float rho1 = 0.9, float rho2 = 0.999, float eps = 1e-6, float lambda = 0)
: lr(lr), rho1(rho1), rho2(rho2), eps(eps), lambda(lambda), mult1(1), mult2(1) {}
void upd(vecmap w, const vecmap &gw) {
vec &s = get<0>(w), &r = get<1>(w);
mult1 *= rho1, mult2 *= rho2;
s = s * rho1 + (gw + w * lambda) * (1. - rho1);
r = r * rho2 + (gw + w * lambda).cwiseAbs2() * (1. - rho2);
w.array() -= lr * s.array() / (sqrt(r.array() / (1. - mult2) + eps)) / (1. - mult1);
}
};
adam 伪代码:

