class_docstr: Biased matrix factorization for implicit feedback using SciKit-Learn's SVD
  solver (:class:`sklearn.decomposition.TruncatedSVD`).  It operates by first
  computing the bias, then computing the SVD of the bias residuals.
  
  You'll generally want one of the iterative SVD implementations such as
  :class:`lennskit.algorithms.als.BiasedMF`; this is here primarily as an
  example and for cases where you want to evaluate a pure SVD implementation.
code: def fit(self, ratings, **kwargs):
      timer = Stopwatch()
      _log.info("[%s] computing bias", timer)
      self.bias.fit(ratings)
  
      g_bias = self.bias.mean_
      u_bias = self.bias.user_offsets_
      i_bias = self.bias.item_offsets_
  
      _log.info("[%s] sparsifying and normalizing matrix", timer)
      r_mat, users, items = sparse_ratings(
          ratings, users=u_bias.index, items=i_bias.index
      )
      # global
      r_mat.values -= g_bias
      r_mat.values -= i_bias.values[r_mat.colinds]
      r_mat.values -= u_bias.values[r_mat.rowinds()]
      r_mat = r_mat.to_scipy()
      assert r_mat.shape == (len(u_bias), len(i_bias))
  
      _log.info(
          "[%s] training SVD (k=%d)",
          timer,
          self.factorization.n_components,
      )
      Xt = self.factorization.fit_transform(r_mat)
      self.user_components_ = Xt
      _log.info("finished model training in %s", timer)
  
file_path: lkpy/lenskit/algorithms/svd.py
imports: import logging
  import pandas
  import numpy
  from .None import Predictor
  from .bias import Bias
  from ..data import sparse_ratings
  from ..util import Stopwatch
label_desc: Use image node_id 2 for calling the BiasedSVD obj's underlying member method code with example usage: obj.fit(ratings) without return types