class_docstr: Resilient backpropagation (RPROP) is an optimization
  algorithm for supervised learning.
  
  RPROP algorithm takes into account only direction of the gradient
  and completely ignores its magnitude. Every weight values has a unique
  step size associated with it (by default all of the are equal to ``step``).
  
  The rule is following, when gradient direction changes (sign of the
  gradient) we decrease step size for specific weight multiplying it by
  ``decrease_factor`` and if sign stays the same than we increase step
  size for this specific weight multiplying it by ``increase_factor``.
  
  The step size is always bounded by ``minstep`` and ``maxstep``.
  
  Notes
  -----
  Algorithm doesn't work with mini-batches.
  
  Parameters
  ----------
  minstep : float
      Minimum possible value for step. Defaults to ``0.001``.
  
  maxstep : float
      Maximum possible value for step. Defaults to ``10``.
  
  increase_factor : float
      Increase factor for step in case when gradient doesn't change
      sign compare to previous epoch.
  
  decrease_factor : float
      Decrease factor for step in case when gradient changes sign
      compare to previous epoch.
  
  {BaseOptimizer.Parameters}
  
  Attributes
  ----------
  {BaseOptimizer.Attributes}
  
  Methods
  -------
  {BaseOptimizer.Methods}
  
  Examples
  --------
  >>> import numpy as np
  >>> from neupy import algorithms
  >>> from neupy.layers import *
  >>>
  >>> x_train = np.array([[1, 2], [3, 4]])
  >>> y_train = np.array([[1], [0]])
  >>>
  >>> network = Input(2) >> Sigmoid(3) >> Sigmoid(1)
  >>> optimizer = algorithms.RPROP(network)
  >>> optimizer.train(x_train, y_train)
  
  See Also
  --------
  :network:`IRPROPPlus` : iRPROP+ algorithm.
  :network:`GradientDescent` : GradientDescent algorithm.
code: def init_train_updates(self):
      updates = []
  
      variables = []
      for (_, _), variable in self.network.variables.items():
          if variable.trainable:
              variables.append(variable)
  
      gradients = tf.gradients(self.variables.loss, variables)
  
      for parameter, gradient in zip(variables, gradients):
          with tf.variable_scope(parameter.op.name):
              steps = tf.Variable(
                  # Steps will be decreased after the first iteration,
                  # because all previous gradients are equal to zero.
                  # In order to make sure that network will use the same
                  # step per every weight we re-scale step and after the
                  # first iteration it will be multiplied by
                  # ``decrease_factor`` and scaled back to the default
                  # step value.
                  tf.ones_like(parameter) * self.step,
                  name="steps",
                  dtype=tf.float32,
              )
              prev_delta = tf.Variable(
                  tf.zeros(parameter.shape),
                  name="prev-delta",
                  dtype=tf.float32,
              )
              # We collect only signs since it ensures numerical stability
              # after multiplication when we deal with small numbers.
              prev_gradient_sign = tf.Variable(
                  tf.zeros(parameter.shape),
                  name="prev-grad-sign",
                  dtype=tf.float32,
              )
  
          updated_prev_delta = self.update_prev_delta(prev_delta)
          gradient_sign = tf.sign(gradient)
  
          grad_sign_product = gradient_sign * prev_gradient_sign
          gradient_changed_sign = tf.equal(grad_sign_product, -1)
  
          updated_steps = tf.clip_by_value(
              tf.where(
                  tf.equal(grad_sign_product, 1),
                  steps * self.increase_factor,
                  tf.where(
                      gradient_changed_sign,
                      steps * self.decrease_factor,
                      steps,
                  ),
              ),
              self.minstep,
              self.maxstep,
          )
          parameter_delta = tf.where(
              gradient_changed_sign,
              # If we subtract previous negative weight update it means
              # that we will revert weight update that has been  applied
              # in the previous iteration.
              -updated_prev_delta,
              updated_steps * gradient_sign,
          )
          # Making sure that during the next iteration sign, after
          # we multiplied by the new gradient, won't be negative.
          # Otherwise, the same roll back using previous delta
          # won't make much sense.
          clipped_gradient_sign = tf.where(
              gradient_changed_sign,
              tf.zeros_like(gradient_sign),
              gradient_sign,
          )
  
          updates.extend(
              [
                  (parameter, parameter - parameter_delta),
                  (steps, updated_steps),
                  (prev_gradient_sign, clipped_gradient_sign),
                  (prev_delta, parameter_delta),
              ]
          )
  
      return updates
  
file_path: neupy/neupy/algorithms/gd/rprop.py
imports: import tensorflow
  import numpy
  from neupy.utils import tensorflow_session
  from neupy.core.properties import BoundedProperty, ProperFractionProperty
  from .base import BaseOptimizer
label_desc: Use image node_id 2 for calling the RPROP obj's underlying member method code with example usage: obj.init_train_updates() and returns: updates