我也在 Keras 中寻找 RProp 算法并发现了这个问题。我冒昧地根据我的目的调整了您的代码,现在将其发布回此处。到目前为止,它似乎工作得很好,但我没有对其进行广泛的测试。
免责声明:我对 keras 很陌生,但对 theano (和块)有很多经验。此外,我仅使用 theano 作为后端进行了测试,但没有使用张量流。
class RProp(Optimizer):
def __init__(self, init_alpha=1e-3, scale_up=1.2, scale_down=0.5, min_alpha=1e-6, max_alpha=50., **kwargs):
super(RProp, self).__init__(**kwargs)
self.init_alpha = K.variable(init_alpha, name='init_alpha')
self.scale_up = K.variable(scale_up, name='scale_up')
self.scale_down = K.variable(scale_down, name='scale_down')
self.min_alpha = K.variable(min_alpha, name='min_alpha')
self.max_alpha = K.variable(max_alpha, name='max_alpha')
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
shapes = [K.get_variable_shape(p) for p in params]
alphas = [K.variable(numpy.ones(shape) * self.init_alpha) for shape in shapes]
old_grads = [K.zeros(shape) for shape in shapes]
self.weights = alphas + old_grads
self.updates = []
for param, grad, old_grad, alpha in zip(params, grads, old_grads, alphas):
new_alpha = K.switch(
K.greater(grad * old_grad, 0),
K.minimum(alpha * self.scale_up, self.max_alpha),
K.maximum(alpha * self.scale_down, self.min_alpha)
)
new_param = param - K.sign(grad) * new_alpha
# Apply constraints
if param in constraints:
c = constraints[param]
new_param = c(new_param)
self.updates.append(K.update(param, new_param))
self.updates.append(K.update(alpha, new_alpha))
self.updates.append(K.update(old_grad, grad))
return self.updates
def get_config(self):
config = {
'init_alpha': float(K.get_value(self.init_alpha)),
'scale_up': float(K.get_value(self.scale_up)),
'scale_down': float(K.get_value(self.scale_down)),
'min_alpha': float(K.get_value(self.min_alpha)),
'max_alpha': float(K.get_value(self.max_alpha)),
}
base_config = super(RProp, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
重要笔记:
- RProp 通常不包含在机器学习库中,原因是:除非您使用全批量学习,否则它根本不起作用。仅当训练集较小时,全批量学习才有用。
- Adam(Keras 内置)优于此 RProp 算法。也许是因为事情就是这样,或者也许是因为我犯了一个错误:)
关于您的代码的一些评论(指您的原始变量名称):
-
wChange
永远不会在迭代中使用,因此您不需要将它们存储在永久变量中。
-
change > 0
没有做你认为它会做的事情,因为change
是一个张量变量。您想要的是逐元素比较,使用K.switch()
反而。
- 你用过
maxStep
两次而不是使用minStep
另一次。
- 情况在哪里
change
为零是可以忽略不计的,因为这在实践中几乎不会发生。
-
g_new = 0
and g_new = p
都是完全伪造的,应该是g_new = g
就像第一个 if 分支一样。