class_docstr: Do various flavours of stochastic gradient descent, with first and
  second order momentum. Currently support 'vanilla' SGD, Adam, and RAdam.
class_docstr_tok: ["Do","various","flavours","of","stochastic","gradient","descent",",","with","first","and","second","order","momentum",".","Currently","support","'vanilla","'","SGD",",","Adam",",","and","RAdam","."]
docstr: Call the optimizer with weights and a gradient. The key is the
  identifier for the parameter, usually the node ID and parameter name.
docstr_tok: ["Call","the","optimizer","with","weights","and","a","gradient",".","The","key","is","the","identifier","for","the","parameter",",","usually","the","node","ID","and","parameter","name","."]
code: def __call__(
      self,
      key: Tuple[int, str],
      weights: FloatsXd,
      gradient: FloatsXd,
      *,
      lr_scale: float = 1.0,
  ):
      """Call the optimizer with weights and a gradient. The key is the
      identifier for the parameter, usually the node ID and parameter name.
      """
      if len(gradient) < 1:
          return weights, gradient
      ops = get_array_ops(weights)
      self.nr_update[key] += 1
      nr_upd = self.nr_update[key]
      if self.L2 != 0 and not self.L2_is_weight_decay:
          gradient += self.L2 * weights
      if self.grad_clip:
          gradient = ops.clip_gradient(gradient, self.grad_clip)
      if self.use_radam:
          weights, gradient = self._radam(
              ops, weights, gradient, lr_scale, key, nr_upd
          )
      elif self.b1 > 0.0 and self.b2 > 0.0:
          weights, gradient = self._adam(
              ops, weights, gradient, lr_scale, key, nr_upd
          )
      elif self.b2 > 0.0:  # pragma: no cover
          raise NotImplementedError  # TODO: error message
      else:
          weights -= lr_scale * self.learn_rate * gradient
      gradient *= 0
      if self.L2 != 0 and self.L2_is_weight_decay:
          weights -= lr_scale * self.learn_rate * self.L2 * weights
      if self.averages is not None:
          if key not in self.averages:
              self.averages[key] = ops.alloc(
                  weights.shape, dtype="float32"
              )
          ops.update_averages(self.averages[key], weights, nr_upd)
      return weights, gradient
  
file_path: thinc/thinc/optimizers.py
imports: import math
  from collections import defaultdict
  from typing import Dict, List, Optional, Tuple, Union, cast
  from .backends import get_array_ops
  from .config import registry
  from .types import FloatsXd, Generator
label_desc: Use image node_id 4 for calling the Optimizer obj's underlying member method code with example usage: obj.__call__(key, weights, gradient) and returns: weights,  gradient, weights,  gradient