class_docstr: Factorization machine base class.
class_docstr_tok: ["Factorization","machine","base","class","."]
code: def _update_latents(self, x, g_loss):
      # For notational convenience
      v, l1, l2, sign = (
          self.latents,
          self.l1_latent,
          self.l2_latent,
          utils.math.sign,
      )
  
      # Precompute feature independent sum for time efficiency
      precomputed_sum = {
          f: sum(v[j][f] * xj for j, xj in x.items())
          for f in range(self.n_factors)
      }
  
      # Calculate each latent factor gradient before updating any
      gradients = {}
      for j, xj in x.items():
          gradients[j] = {
              f: g_loss * (xj * precomputed_sum[f] - v[j][f] * xj**2)
              + l1 * sign(v[j][f])
              + l2 * v[j][f]
              for f in range(self.n_factors)
          }
  
      # Finally update the latent weights
      for j in x.keys():
          self.latents[j] = self.latent_optimizer.step(
              w=v[j], g=gradients[j]
          )
  
imports: from __future__ import annotations
  import collections
  import functools
  import itertools
  import numpy
  from river import base, optim, utils
  from .base import BaseFM
label_desc: Use image node_id 8 for calling the FM obj's underlying member method code with example usage: obj._update_latents(x, g_loss) without return types