class_docstr: Iterative estimation of row and column centering/scaling
  using the algorithm from page 31 of:
      Matrix Completion and Low-Rank SVD via Fast Alternating Least Squares
code: def residual(self, X_normalized):
      total = 0
      if self.center_rows:
          row_means = np.nanmean(X_normalized, axis=1)
          total += (row_means**2).sum()
  
      if self.center_columns:
          column_means = np.nanmean(X_normalized, axis=0)
          total += (column_means**2).sum()
  
      if self.scale_rows:
          row_variances = np.nanvar(X_normalized, axis=1)
          row_variances[row_variances == 0] = 1.0
          total += (np.log(row_variances) ** 2).sum()
  
      if self.scale_columns:
          column_variances = np.nanvar(X_normalized, axis=0)
          column_variances[column_variances == 0] = 1.0
          total += (np.log(column_variances) ** 2).sum()
  
      return total
  
imports: import numpy
label_desc: Use image node_id 8 for calling the BiScaler obj's underlying member method code with example usage: obj.residual(X_normalized) and returns: total