'Construct a new YellowFin optimizer.
Args:
learning_rate: A Tensor or a floating point value.  The learning rate.
momentum: A Tensor or a floating point value.  The momentum.
clip_thresh: A Tensor or a floating point value. The cliping threshold for
tf.clip_by_global_norm.  If None, no clipping will be carried out.
beta: A float value or a constant float tensor.  The smoothing parameter
for estimations.
curvature_window_width: A int value or a constant int tensor.
The curvature window width.
zero_debias: A boolean, zero debias moving-averages.
delta_mu: For extensions. Not necessary in the basic use.
Note:
clip_thresh is the threshold value on ||lr * gradient||,
delta_mu can be place holder/variable/tensor scalar.
They are used for additional momentum in situations such as
asynchronous-parallel training.
The default is 0.0(or None) for basic usage of the optimizer.
Other features:
If you want to manually control the learning rates, self.lr_factor is
an interface to the outside, it is an multiplier for the internal
learning rate in YellowFin. It is helpful when you want to do additional
hand tuning or some decaying scheme to the tuned learning rate in
YellowFin.
Example on using lr_factor can be found here:
https://github.com/JianGoForIt/YellowFin/blob/master/char-rnn-tensorflow/train_YF.py#L140'

def __init__(self, learning_rate=1.0, momentum=0.0, clip_thresh=None, beta=0.999, curvature_window_width=20, zero_debias=True, delta_mu=0.0):

    self._lr = learning_rate
    self._mu = momentum
    self._lr_var = tf.Variable(learning_rate, dtype=tf.float32, name='YF_lr', trainable=False)
    self._mu_var = tf.Variable(momentum, dtype=tf.float32, name='YF_mu', trainable=False)
    self.lr_factor = tf.Variable(1.0, dtype=tf.float32, name='YF_lr_factor', trainable=False)
    if (clip_thresh is not None):
        self._clip_thresh_var = tf.Variable(clip_thresh, dtype=tf.float32, name='YF_clip_thresh', trainable=False)
    else:
        self._clip_thresh_var = None
    self._lr_m = (self._lr_var * self.lr_factor)
    self._mu_m = (self._mu_var + delta_mu)
    self._momentum_optimizer = tf.train.MomentumOptimizer(self._lr_m, self._mu_m)
    self._beta = beta
    self._moving_averager = None
    self._step = tf.Variable(0, dtype=tf.int32, name='YF_step', trainable=False)
    self._increment_step_op = None
    self._do_tune = tf.greater(self._step, tf.constant(0))
    self._zero_debias = zero_debias
    self.curvature_window_width = curvature_window_width
    self._curv_win = None
    self._grad = None
    self._vars = None
    self._grad_squared = None
    self._grad_norm_squared = None
    self._grad_norm_squared_avg = None
    self._grad_avg = None
    self._grad_avg_squared = None
    self._h_max_t = None
    self._h_min_t = None
    self._h_min = None
    self._h_max = None
    self._grad_var = None
    self._grad_norm = None
    self._grad_norm_avg = None
    self._d_t = None
    self._dist_to_opt_avg = None
    self._moving_averager = None
