2017-05-03 3 views
3

Keras (link)에 대한 탄력적 인 backpropagation 최적화 프로그램을 구현하려고했지만 도전적인 부분은 해당하는 그래디언트가 양수인지 여부에 따라 개별 매개 변수를 업데이트 할 수 있었지만, 음 또는 0입니다. 아래 코드를 Rprop 최적화 프로그램을 구현하기위한 시작으로 작성했습니다. 그러나 매개 변수에 개별적으로 액세스하는 방법을 찾지 못하는 것 같습니다. params (아래 코드와 같이) 이상의 루핑은 모든 행렬 인 각 반복마다 p, g, g_old, s, wChangeOld을 반환합니다.Keras - Rprop 알고리즘을 구현할 때 발생하는 문제

개별 매개 변수를 반복하고 업데이트 할 수있는 방법이 있습니까? 그래디언트의 부호에 따라 매개 변수 벡터를 인덱싱 할 수도 있습니다. 감사!

class Rprop(Optimizer): 
    def __init__(self, init_step=0.01, **kwargs): 
     super(Rprop, self).__init__(**kwargs) 
     self.init_step = K.variable(init_step, name='init_step') 
     self.iterations = K.variable(0., name='iterations') 

     self.posStep = 1.2 
     self.negStep = 0.5 
     self.minStep = 1e-6 
     self.maxStep = 50. 

    def get_updates(self, params, constraints, loss): 
     grads = self.get_gradients(loss, params) 
     self.updates = [K.update_add(self.iterations, 1)] 

     shapes = [K.get_variable_shape(p) for p in params] 
     stepList = [K.ones(shape)*self.init_step for shape in shapes] 
     wChangeOldList = [K.zeros(shape) for shape in shapes] 
     grads_old = [K.zeros(shape) for shape in shapes] 

     self.weights = stepList + grads_old + wChangeOldList 
     self.updates = [] 

     for p, g, g_old, s, wChangeOld in zip(params, grads, grads_old, 
                    stepList, wChangeOldList): 
      change = K.sign(g * g_old) 

      if change > 0: 
       s_new = K.minimum(s * self.posStep, self.maxStep) 
       wChange = s_new * K.sign(g) 
       g_new = g 

      elif change < 0: 
       s_new = K.maximum(s * self.posStep, self.maxStep) 
       wChange = - wChangeOld 
       g_new = 0 

      else: 
       s_new = s 
       wChange = s_new * K.sign(g) 
       g_new = p 

      self.updates.append(K.update(g_old, g_new)) 
      self.updates.append(K.update(wChangeOld, wChange)) 
      self.updates.append(K.update(s, s_new)) 

      new_p = p - wChange 

      # Apply constraints 
      if p in constraints: 
       c = constraints[p] 
       new_p = c(new_p) 

      self.updates.append(K.update(p, new_p)) 
     return self.updates 

    def get_config(self): 
     config = {'init_step': float(K.get_value(self.init_step))} 
     base_config = super(Rprop, self).get_config() 
     return dict(list(base_config.items()) + list(config.items())) 
+0

은 (0) ... K.equal (변경) 여기가 아닌 경우/ELIF/다른 사람을 K.switch 필요하지 않습니다? – gkcn

답변

0

저는 Keras에서도 RProp 알고리즘을 찾고 있었고이 질문을 발견했습니다. 나는 당신의 코드를 나의 목적에 맞게 자유롭게 바꾸어 여기에 다시 게시했다. 지금까지는 꽤 잘 작동하는 것으로 보이지만 광범위하게 테스트하지는 않았습니다.

면책 조항 : 저는 keras에 새로 왔지만 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 builtin)은이 RProp 알고리즘을 능가합니다. 그게 내가 실수 : 당신의 코드에 대한

몇 가지 코멘트를 한 것으로 나타났습니다 때문에 어쩌면 나, 얼마나 어쩌면 때문에 (원래 변수 이름을 참조) :

  • wChange이 반복을 통해 사용되지 않습니다 따라서 영구 변수에 저장하지 않아도됩니다.
  • change > 0change은 텐서 변수이기 때문에 사용자가 생각하는대로 작동하지 않습니다. 여기서 원하는 것은 요소별로 비교하는 것입니다. 대신 K.switch()을 사용하십시오.
  • 다른 번에 minStep을 사용하는 대신 maxStep을 두 번 사용했습니다.
  • change이 0 인 상황은 거의 발생하지 않으므로 무시할 수 있습니다.
  • g_new = 0g_new = p은 모두 완전히 가짜이며 첫 번째 if 분기와 마찬가지로 g_new = g이어야합니다.
0

저는 keras와 Pyhton을 처음 사용했지만 위의 코드를 약간 수정했습니다. 전체 배치 학습 및 부분 파생어 사용으로 인해 매우 빠르고 간단한 알고리즘입니다. 테스트에서 Adam을 포함한 다른 모든 역 전파 알고리즘보다 성능이 우수했습니다. Tensorflow와 CNTK를 백엔드로 테스트했습니다.체중 역행없이 Rprop 수정

: https://pdfs.semanticscholar.org/df9c/6a3843d54a28138a596acc85a96367a064c2.pdf

class iRprop_(Optimizer): 
def __init__(self, init_alpha=0.01, scale_up=1.2, scale_down=0.5, min_alpha=0.00001, max_alpha=50., **kwargs): 
    super(iRprop_, 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, loss): 
    grads = self.get_gradients(loss, params) 
    shapes = [K.get_variable_shape(p) for p in params] 
    alphas = [K.variable(K.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 p, grad, old_grad, alpha in zip(params, grads, old_grads, alphas): 
     grad = K.sign(grad) 
     new_alpha = K.switch(
      K.greater(grad * old_grad, 0), 
      K.minimum(alpha * self.scale_up, self.max_alpha), 
      K.switch(K.less(grad * old_grad, 0),K.maximum(alpha * self.scale_down, self.min_alpha),alpha)  
     ) 

     grad = K.switch(K.less(grad * old_grad, 0),K.zeros_like(grad),grad) 
     new_p = p - grad * new_alpha 

     # Apply constraints. 
     if getattr(p, 'constraint', None) is not None: 
      new_p = p.constraint(new_p) 
     self.updates.append(K.update(p, new_p)) 
     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(iRprop_, self).get_config() 
    return dict(list(base_config.items()) + list(config.items())) 
+0

그것을 사용하려고했습니다. 하지만 오류가 발생합니다 : TypeError : get_updates() 정확히 3 인수 (주어진 4) –