Generated by Cython 0.29.26

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

Raw output: matrix_factorization.c

+001: """
  __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 002: the :mod:`matrix_factorization` module includes some algorithms using matrix
 003: factorization.
 004: """
 005: 
 006: from __future__ import (absolute_import, division, print_function,
 007:                         unicode_literals)
 008: 
 009: cimport numpy as np  # noqa
+010: import numpy as np
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 10, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+011: from six.moves import range
  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(__pyx_n_s_range);
  __Pyx_GIVEREF(__pyx_n_s_range);
  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_range);
  __pyx_t_2 = __Pyx_Import(__pyx_n_s_six_moves, __pyx_t_1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_range); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_range, __pyx_t_1) < 0) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 012: 
+013: from .algo_base import AlgoBase
  __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_INCREF(__pyx_n_s_AlgoBase);
  __Pyx_GIVEREF(__pyx_n_s_AlgoBase);
  PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_AlgoBase);
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_algo_base, __pyx_t_2, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_AlgoBase); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_AlgoBase, __pyx_t_2) < 0) __PYX_ERR(0, 13, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+014: from .predictions import PredictionImpossible
  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(__pyx_n_s_PredictionImpossible);
  __Pyx_GIVEREF(__pyx_n_s_PredictionImpossible);
  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PredictionImpossible);
  __pyx_t_2 = __Pyx_Import(__pyx_n_s_predictions, __pyx_t_1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_PredictionImpossible); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_PredictionImpossible, __pyx_t_1) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+015: from ..utils import get_rng
  __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 15, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_INCREF(__pyx_n_s_get_rng);
  __Pyx_GIVEREF(__pyx_n_s_get_rng);
  PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_get_rng);
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_utils, __pyx_t_2, 2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 15, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_1, __pyx_n_s_get_rng); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 15, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_rng, __pyx_t_2) < 0) __PYX_ERR(0, 15, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 016: 
 017: from libcpp.map cimport map as mapcpp
 018: from libcpp.vector cimport vector as vectorcpp
 019: from cython.operator import dereference, postincrement
 020: 
 021: 
+022: class SVD(AlgoBase):
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_AlgoBase); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 22, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
  __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_t_2, __pyx_n_s_SVD, __pyx_n_s_SVD, (PyObject *) NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_kp_s_The_famous_SVD_algorithm_as_popu); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 22, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
/* … */
  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_SVD, __pyx_t_2, __pyx_t_3, NULL, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 22, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_SVD, __pyx_t_4) < 0) __PYX_ERR(0, 22, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 023:     """The famous *SVD* algorithm, as popularized by `Simon Funk
 024:     <http://sifter.org/~simon/journal/20061211.html>`_ during the Netflix
 025:     Prize. When baselines are not used, this is equivalent to Probabilistic
 026:     Matrix Factorization :cite:`salakhutdinov2008a` (see :ref:`note
 027:     <unbiased_note>` below).
 028: 
 029:     The prediction :math:`\\hat{r}_{ui}` is set as:
 030: 
 031:     .. math::
 032:         \hat{r}_{ui} = \mu + b_u + b_i + q_i^Tp_u
 033: 
 034:     If user :math:`u` is unknown, then the bias :math:`b_u` and the factors
 035:     :math:`p_u` are assumed to be zero. The same applies for item :math:`i`
 036:     with :math:`b_i` and :math:`q_i`.
 037: 
 038:     For details, see equation (5) from :cite:`Koren:2009`. See also
 039:     :cite:`Ricci:2010`, section 5.3.1.
 040: 
 041:     To estimate all the unknown, we minimize the following regularized squared
 042:     error:
 043: 
 044:     .. math::
 045:         \sum_{r_{ui} \in R_{train}} \left(r_{ui} - \hat{r}_{ui} \\right)^2 +
 046:         \lambda\\left(b_i^2 + b_u^2 + ||q_i||^2 + ||p_u||^2\\right)
 047: 
 048: 
 049:     The minimization is performed by a very straightforward stochastic gradient
 050:     descent:
 051: 
 052:     .. math::
 053:         b_u &\\leftarrow b_u &+ \gamma (e_{ui} - \lambda b_u)\\\\
 054:         b_i &\\leftarrow b_i &+ \gamma (e_{ui} - \lambda b_i)\\\\
 055:         p_u &\\leftarrow p_u &+ \gamma (e_{ui} \\cdot q_i - \lambda p_u)\\\\
 056:         q_i &\\leftarrow q_i &+ \gamma (e_{ui} \\cdot p_u - \lambda q_i)
 057: 
 058:     where :math:`e_{ui} = r_{ui} - \\hat{r}_{ui}`. These steps are performed
 059:     over all the ratings of the trainset and repeated ``n_epochs`` times.
 060:     Baselines are initialized to ``0``. User and item factors are randomly
 061:     initialized according to a normal distribution, which can be tuned using
 062:     the ``init_mean`` and ``init_std_dev`` parameters.
 063: 
 064:     You also have control over the learning rate :math:`\gamma` and the
 065:     regularization term :math:`\lambda`. Both can be different for each
 066:     kind of parameter (see below). By default, learning rates are set to
 067:     ``0.005`` and regularization terms are set to ``0.02``.
 068: 
 069:     .. _unbiased_note:
 070: 
 071:     .. note::
 072:         You can choose to use an unbiased version of this algorithm, simply
 073:         predicting:
 074: 
 075:         .. math::
 076:             \hat{r}_{ui} = q_i^Tp_u
 077: 
 078:         This is equivalent to Probabilistic Matrix Factorization
 079:         (:cite:`salakhutdinov2008a`, section 2) and can be achieved by setting
 080:         the ``biased`` parameter to ``False``.
 081: 
 082: 
 083:     Args:
 084:         n_factors: The number of factors. Default is ``100``.
 085:         n_epochs: The number of iteration of the SGD procedure. Default is
 086:             ``20``.
 087:         biased(bool): Whether to use baselines (or biases). See :ref:`note
 088:             <unbiased_note>` above.  Default is ``True``.
 089:         init_mean: The mean of the normal distribution for factor vectors
 090:             initialization. Default is ``0``.
 091:         init_std_dev: The standard deviation of the normal distribution for
 092:             factor vectors initialization. Default is ``0.1``.
 093:         lr_all: The learning rate for all parameters. Default is ``0.005``.
 094:         reg_all: The regularization term for all parameters. Default is
 095:             ``0.02``.
 096:         lr_bu: The learning rate for :math:`b_u`. Takes precedence over
 097:             ``lr_all`` if set. Default is ``None``.
 098:         lr_bi: The learning rate for :math:`b_i`. Takes precedence over
 099:             ``lr_all`` if set. Default is ``None``.
 100:         lr_pu: The learning rate for :math:`p_u`. Takes precedence over
 101:             ``lr_all`` if set. Default is ``None``.
 102:         lr_qi: The learning rate for :math:`q_i`. Takes precedence over
 103:             ``lr_all`` if set. Default is ``None``.
 104:         reg_bu: The regularization term for :math:`b_u`. Takes precedence
 105:             over ``reg_all`` if set. Default is ``None``.
 106:         reg_bi: The regularization term for :math:`b_i`. Takes precedence
 107:             over ``reg_all`` if set. Default is ``None``.
 108:         reg_pu: The regularization term for :math:`p_u`. Takes precedence
 109:             over ``reg_all`` if set. Default is ``None``.
 110:         reg_qi: The regularization term for :math:`q_i`. Takes precedence
 111:             over ``reg_all`` if set. Default is ``None``.
 112:         random_state(int, RandomState instance from numpy, or ``None``):
 113:             Determines the RNG that will be used for initialization. If
 114:             int, ``random_state`` will be used as a seed for a new RNG. This is
 115:             useful to get the same initialization over multiple calls to
 116:             ``fit()``.  If RandomState instance, this same instance is used as
 117:             RNG. If ``None``, the current RNG from numpy is used.  Default is
 118:             ``None``.
 119:         verbose: If ``True``, prints the current epoch. Default is ``False``.
 120: 
 121:     Attributes:
 122:         pu(numpy array of size (n_users, n_factors)): The user factors (only
 123:             exists if ``fit()`` has been called)
 124:         qi(numpy array of size (n_items, n_factors)): The item factors (only
 125:             exists if ``fit()`` has been called)
 126:         bu(numpy array of size (n_users)): The user biases (only
 127:             exists if ``fit()`` has been called)
 128:         bi(numpy array of size (n_items)): The item biases (only
 129:             exists if ``fit()`` has been called)
 130:     """
 131: 
+132:     def __init__(self, n_factors=100, n_epochs=20, biased=True, init_mean=0,
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_1__init__ = {"__init__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_1__init__, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_n_factors = 0;
  PyObject *__pyx_v_n_epochs = 0;
  PyObject *__pyx_v_biased = 0;
  PyObject *__pyx_v_init_mean = 0;
  PyObject *__pyx_v_init_std_dev = 0;
  PyObject *__pyx_v_lr_all = 0;
  PyObject *__pyx_v_reg_all = 0;
  PyObject *__pyx_v_lr_bu = 0;
  PyObject *__pyx_v_lr_bi = 0;
  PyObject *__pyx_v_lr_pu = 0;
  PyObject *__pyx_v_lr_qi = 0;
  PyObject *__pyx_v_reg_bu = 0;
  PyObject *__pyx_v_reg_bi = 0;
  PyObject *__pyx_v_reg_pu = 0;
  PyObject *__pyx_v_reg_qi = 0;
  PyObject *__pyx_v_random_state = 0;
  PyObject *__pyx_v_verbose = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_n_factors,&__pyx_n_s_n_epochs,&__pyx_n_s_biased,&__pyx_n_s_init_mean,&__pyx_n_s_init_std_dev,&__pyx_n_s_lr_all,&__pyx_n_s_reg_all,&__pyx_n_s_lr_bu,&__pyx_n_s_lr_bi,&__pyx_n_s_lr_pu,&__pyx_n_s_lr_qi,&__pyx_n_s_reg_bu,&__pyx_n_s_reg_bi,&__pyx_n_s_reg_pu,&__pyx_n_s_reg_qi,&__pyx_n_s_random_state,&__pyx_n_s_verbose,0};
    PyObject* values[18] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    values[1] = ((PyObject *)((PyObject *)__pyx_int_100));
    values[2] = ((PyObject *)((PyObject *)__pyx_int_20));
    values[3] = ((PyObject *)((PyObject *)Py_True));
    values[4] = ((PyObject *)((PyObject *)__pyx_int_0));
    values[5] = ((PyObject *)((PyObject*)__pyx_float__1));
    values[6] = ((PyObject *)((PyObject*)__pyx_float__005));
    values[7] = ((PyObject *)((PyObject*)__pyx_float__02));
/* … */
  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3SVD___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_n_factors, PyObject *__pyx_v_n_epochs, PyObject *__pyx_v_biased, PyObject *__pyx_v_init_mean, PyObject *__pyx_v_init_std_dev, PyObject *__pyx_v_lr_all, PyObject *__pyx_v_reg_all, PyObject *__pyx_v_lr_bu, PyObject *__pyx_v_lr_bi, PyObject *__pyx_v_lr_pu, PyObject *__pyx_v_lr_qi, PyObject *__pyx_v_reg_bu, PyObject *__pyx_v_reg_bi, PyObject *__pyx_v_reg_pu, PyObject *__pyx_v_reg_qi, PyObject *__pyx_v_random_state, PyObject *__pyx_v_verbose) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__init__", 0);
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVD.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__4 = PyTuple_Pack(18, __pyx_n_s_self, __pyx_n_s_n_factors, __pyx_n_s_n_epochs, __pyx_n_s_biased, __pyx_n_s_init_mean, __pyx_n_s_init_std_dev, __pyx_n_s_lr_all, __pyx_n_s_reg_all, __pyx_n_s_lr_bu, __pyx_n_s_lr_bi, __pyx_n_s_lr_pu, __pyx_n_s_lr_qi, __pyx_n_s_reg_bu, __pyx_n_s_reg_bi, __pyx_n_s_reg_pu, __pyx_n_s_reg_qi, __pyx_n_s_random_state, __pyx_n_s_verbose); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(0, 132, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__4);
  __Pyx_GIVEREF(__pyx_tuple__4);
  __pyx_codeobj__5 = (PyObject*)__Pyx_PyCode_New(18, 0, 18, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__4, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_init, 132, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__5)) __PYX_ERR(0, 132, __pyx_L1_error)
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_1__init__, 0, __pyx_n_s_SVD___init, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__5)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 132, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_4, __pyx_tuple__6);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_init, __pyx_t_4) < 0) __PYX_ERR(0, 132, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_tuple__6 = PyTuple_Pack(17, ((PyObject *)__pyx_int_100), ((PyObject *)__pyx_int_20), ((PyObject *)Py_True), ((PyObject *)__pyx_int_0), ((PyObject*)__pyx_float__1), ((PyObject*)__pyx_float__005), ((PyObject*)__pyx_float__02), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_False)); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 132, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__6);
  __Pyx_GIVEREF(__pyx_tuple__6);
 133:                  init_std_dev=.1, lr_all=.005,
+134:                  reg_all=.02, lr_bu=None, lr_bi=None, lr_pu=None, lr_qi=None,
    values[8] = ((PyObject *)((PyObject *)Py_None));
    values[9] = ((PyObject *)((PyObject *)Py_None));
    values[10] = ((PyObject *)((PyObject *)Py_None));
    values[11] = ((PyObject *)((PyObject *)Py_None));
+135:                  reg_bu=None, reg_bi=None, reg_pu=None, reg_qi=None,
    values[12] = ((PyObject *)((PyObject *)Py_None));
    values[13] = ((PyObject *)((PyObject *)Py_None));
    values[14] = ((PyObject *)((PyObject *)Py_None));
    values[15] = ((PyObject *)((PyObject *)Py_None));
+136:                  random_state=None, verbose=False):
    values[16] = ((PyObject *)((PyObject *)Py_None));
    values[17] = ((PyObject *)((PyObject *)Py_False));
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case 18: values[17] = PyTuple_GET_ITEM(__pyx_args, 17);
        CYTHON_FALLTHROUGH;
        case 17: values[16] = PyTuple_GET_ITEM(__pyx_args, 16);
        CYTHON_FALLTHROUGH;
        case 16: values[15] = PyTuple_GET_ITEM(__pyx_args, 15);
        CYTHON_FALLTHROUGH;
        case 15: values[14] = PyTuple_GET_ITEM(__pyx_args, 14);
        CYTHON_FALLTHROUGH;
        case 14: values[13] = PyTuple_GET_ITEM(__pyx_args, 13);
        CYTHON_FALLTHROUGH;
        case 13: values[12] = PyTuple_GET_ITEM(__pyx_args, 12);
        CYTHON_FALLTHROUGH;
        case 12: values[11] = PyTuple_GET_ITEM(__pyx_args, 11);
        CYTHON_FALLTHROUGH;
        case 11: values[10] = PyTuple_GET_ITEM(__pyx_args, 10);
        CYTHON_FALLTHROUGH;
        case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9);
        CYTHON_FALLTHROUGH;
        case  9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8);
        CYTHON_FALLTHROUGH;
        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_n_factors);
          if (value) { values[1] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_n_epochs);
          if (value) { values[2] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_biased);
          if (value) { values[3] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  4:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_init_mean);
          if (value) { values[4] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  5:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_init_std_dev);
          if (value) { values[5] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  6:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_all);
          if (value) { values[6] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  7:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_all);
          if (value) { values[7] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  8:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_bu);
          if (value) { values[8] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  9:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_bi);
          if (value) { values[9] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 10:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_pu);
          if (value) { values[10] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 11:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_qi);
          if (value) { values[11] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 12:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_bu);
          if (value) { values[12] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 13:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_bi);
          if (value) { values[13] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 14:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_pu);
          if (value) { values[14] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 15:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_qi);
          if (value) { values[15] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 16:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_random_state);
          if (value) { values[16] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 17:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_verbose);
          if (value) { values[17] = value; kw_args--; }
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 132, __pyx_L3_error)
      }
    } else {
      switch (PyTuple_GET_SIZE(__pyx_args)) {
        case 18: values[17] = PyTuple_GET_ITEM(__pyx_args, 17);
        CYTHON_FALLTHROUGH;
        case 17: values[16] = PyTuple_GET_ITEM(__pyx_args, 16);
        CYTHON_FALLTHROUGH;
        case 16: values[15] = PyTuple_GET_ITEM(__pyx_args, 15);
        CYTHON_FALLTHROUGH;
        case 15: values[14] = PyTuple_GET_ITEM(__pyx_args, 14);
        CYTHON_FALLTHROUGH;
        case 14: values[13] = PyTuple_GET_ITEM(__pyx_args, 13);
        CYTHON_FALLTHROUGH;
        case 13: values[12] = PyTuple_GET_ITEM(__pyx_args, 12);
        CYTHON_FALLTHROUGH;
        case 12: values[11] = PyTuple_GET_ITEM(__pyx_args, 11);
        CYTHON_FALLTHROUGH;
        case 11: values[10] = PyTuple_GET_ITEM(__pyx_args, 10);
        CYTHON_FALLTHROUGH;
        case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9);
        CYTHON_FALLTHROUGH;
        case  9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8);
        CYTHON_FALLTHROUGH;
        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        break;
        default: goto __pyx_L5_argtuple_error;
      }
    }
    __pyx_v_self = values[0];
    __pyx_v_n_factors = values[1];
    __pyx_v_n_epochs = values[2];
    __pyx_v_biased = values[3];
    __pyx_v_init_mean = values[4];
    __pyx_v_init_std_dev = values[5];
    __pyx_v_lr_all = values[6];
    __pyx_v_reg_all = values[7];
    __pyx_v_lr_bu = values[8];
    __pyx_v_lr_bi = values[9];
    __pyx_v_lr_pu = values[10];
    __pyx_v_lr_qi = values[11];
    __pyx_v_reg_bu = values[12];
    __pyx_v_reg_bi = values[13];
    __pyx_v_reg_pu = values[14];
    __pyx_v_reg_qi = values[15];
    __pyx_v_random_state = values[16];
    __pyx_v_verbose = values[17];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("__init__", 0, 1, 18, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 132, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVD.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3SVD___init__(__pyx_self, __pyx_v_self, __pyx_v_n_factors, __pyx_v_n_epochs, __pyx_v_biased, __pyx_v_init_mean, __pyx_v_init_std_dev, __pyx_v_lr_all, __pyx_v_reg_all, __pyx_v_lr_bu, __pyx_v_lr_bi, __pyx_v_lr_pu, __pyx_v_lr_qi, __pyx_v_reg_bu, __pyx_v_reg_bi, __pyx_v_reg_pu, __pyx_v_reg_qi, __pyx_v_random_state, __pyx_v_verbose);
 137: 
+138:         self.n_factors = n_factors
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_n_factors, __pyx_v_n_factors) < 0) __PYX_ERR(0, 138, __pyx_L1_error)
+139:         self.n_epochs = n_epochs
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_n_epochs, __pyx_v_n_epochs) < 0) __PYX_ERR(0, 139, __pyx_L1_error)
+140:         self.biased = biased
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_biased, __pyx_v_biased) < 0) __PYX_ERR(0, 140, __pyx_L1_error)
+141:         self.init_mean = init_mean
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_init_mean, __pyx_v_init_mean) < 0) __PYX_ERR(0, 141, __pyx_L1_error)
+142:         self.init_std_dev = init_std_dev
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_init_std_dev, __pyx_v_init_std_dev) < 0) __PYX_ERR(0, 142, __pyx_L1_error)
+143:         self.lr_bu = lr_bu if lr_bu is not None else lr_all
  __pyx_t_2 = (__pyx_v_lr_bu != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_lr_bu);
    __pyx_t_1 = __pyx_v_lr_bu;
  } else {
    __Pyx_INCREF(__pyx_v_lr_all);
    __pyx_t_1 = __pyx_v_lr_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_bu, __pyx_t_1) < 0) __PYX_ERR(0, 143, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+144:         self.lr_bi = lr_bi if lr_bi is not None else lr_all
  __pyx_t_2 = (__pyx_v_lr_bi != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_lr_bi);
    __pyx_t_1 = __pyx_v_lr_bi;
  } else {
    __Pyx_INCREF(__pyx_v_lr_all);
    __pyx_t_1 = __pyx_v_lr_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_bi, __pyx_t_1) < 0) __PYX_ERR(0, 144, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+145:         self.lr_pu = lr_pu if lr_pu is not None else lr_all
  __pyx_t_2 = (__pyx_v_lr_pu != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_lr_pu);
    __pyx_t_1 = __pyx_v_lr_pu;
  } else {
    __Pyx_INCREF(__pyx_v_lr_all);
    __pyx_t_1 = __pyx_v_lr_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_pu, __pyx_t_1) < 0) __PYX_ERR(0, 145, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+146:         self.lr_qi = lr_qi if lr_qi is not None else lr_all
  __pyx_t_2 = (__pyx_v_lr_qi != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_lr_qi);
    __pyx_t_1 = __pyx_v_lr_qi;
  } else {
    __Pyx_INCREF(__pyx_v_lr_all);
    __pyx_t_1 = __pyx_v_lr_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_qi, __pyx_t_1) < 0) __PYX_ERR(0, 146, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+147:         self.reg_bu = reg_bu if reg_bu is not None else reg_all
  __pyx_t_2 = (__pyx_v_reg_bu != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_reg_bu);
    __pyx_t_1 = __pyx_v_reg_bu;
  } else {
    __Pyx_INCREF(__pyx_v_reg_all);
    __pyx_t_1 = __pyx_v_reg_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_bu, __pyx_t_1) < 0) __PYX_ERR(0, 147, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+148:         self.reg_bi = reg_bi if reg_bi is not None else reg_all
  __pyx_t_2 = (__pyx_v_reg_bi != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_reg_bi);
    __pyx_t_1 = __pyx_v_reg_bi;
  } else {
    __Pyx_INCREF(__pyx_v_reg_all);
    __pyx_t_1 = __pyx_v_reg_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_bi, __pyx_t_1) < 0) __PYX_ERR(0, 148, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+149:         self.reg_pu = reg_pu if reg_pu is not None else reg_all
  __pyx_t_2 = (__pyx_v_reg_pu != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_reg_pu);
    __pyx_t_1 = __pyx_v_reg_pu;
  } else {
    __Pyx_INCREF(__pyx_v_reg_all);
    __pyx_t_1 = __pyx_v_reg_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_pu, __pyx_t_1) < 0) __PYX_ERR(0, 149, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+150:         self.reg_qi = reg_qi if reg_qi is not None else reg_all
  __pyx_t_2 = (__pyx_v_reg_qi != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_reg_qi);
    __pyx_t_1 = __pyx_v_reg_qi;
  } else {
    __Pyx_INCREF(__pyx_v_reg_all);
    __pyx_t_1 = __pyx_v_reg_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_qi, __pyx_t_1) < 0) __PYX_ERR(0, 150, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+151:         self.random_state = random_state
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_random_state, __pyx_v_random_state) < 0) __PYX_ERR(0, 151, __pyx_L1_error)
+152:         self.verbose = verbose
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_verbose, __pyx_v_verbose) < 0) __PYX_ERR(0, 152, __pyx_L1_error)
 153: 
+154:         AlgoBase.__init__(self)
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_AlgoBase); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 154, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_init); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 154, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_3, __pyx_v_self) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_self);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 154, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 155: 
+156:     def fit(self, trainset):
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_3fit(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_3fit = {"fit", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_3fit, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_3fit(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_trainset = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("fit (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_trainset,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_trainset)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("fit", 1, 2, 2, 1); __PYX_ERR(0, 156, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "fit") < 0)) __PYX_ERR(0, 156, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_self = values[0];
    __pyx_v_trainset = values[1];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("fit", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 156, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVD.fit", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_2fit(__pyx_self, __pyx_v_self, __pyx_v_trainset);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_2fit(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_trainset) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("fit", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVD.fit", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__7 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_trainset); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(0, 156, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__7);
  __Pyx_GIVEREF(__pyx_tuple__7);
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_3fit, 0, __pyx_n_s_SVD_fit, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__8)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 156, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_fit, __pyx_t_4) < 0) __PYX_ERR(0, 156, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_codeobj__8 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__7, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_fit, 156, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__8)) __PYX_ERR(0, 156, __pyx_L1_error)
 157: 
+158:         AlgoBase.fit(self, trainset)
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_AlgoBase); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_fit); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = NULL;
  __pyx_t_4 = 0;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_2)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
      __pyx_t_4 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_3)) {
    PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_v_self, __pyx_v_trainset};
    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_4, 2+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 158, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_GOTREF(__pyx_t_1);
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
    PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_v_self, __pyx_v_trainset};
    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_4, 2+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 158, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_GOTREF(__pyx_t_1);
  } else
  #endif
  {
    __pyx_t_5 = PyTuple_New(2+__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 158, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    if (__pyx_t_2) {
      __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2); __pyx_t_2 = NULL;
    }
    __Pyx_INCREF(__pyx_v_self);
    __Pyx_GIVEREF(__pyx_v_self);
    PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_4, __pyx_v_self);
    __Pyx_INCREF(__pyx_v_trainset);
    __Pyx_GIVEREF(__pyx_v_trainset);
    PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_4, __pyx_v_trainset);
    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 158, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+159:         self.sgd(trainset)
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_sgd); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 159, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_v_trainset) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_trainset);
  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 159, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 160: 
+161:         return self
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_self);
  __pyx_r = __pyx_v_self;
  goto __pyx_L0;
 162: 
+163:     def sgd(self, trainset):
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_5sgd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_5sgd = {"sgd", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_5sgd, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_5sgd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_trainset = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("sgd (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_trainset,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_trainset)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("sgd", 1, 2, 2, 1); __PYX_ERR(0, 163, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "sgd") < 0)) __PYX_ERR(0, 163, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_self = values[0];
    __pyx_v_trainset = values[1];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("sgd", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 163, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVD.sgd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_4sgd(__pyx_self, __pyx_v_self, __pyx_v_trainset);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_4sgd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_trainset) {
  PyArrayObject *__pyx_v_bu = 0;
  PyArrayObject *__pyx_v_bi = 0;
  PyArrayObject *__pyx_v_pu = 0;
  PyArrayObject *__pyx_v_qi = 0;
  int __pyx_v_u;
  int __pyx_v_i;
  int __pyx_v_f;
  double __pyx_v_r;
  double __pyx_v_err;
  double __pyx_v_dot;
  double __pyx_v_puf;
  double __pyx_v_qif;
  double __pyx_v_global_mean;
  double __pyx_v_lr_bu;
  double __pyx_v_lr_bi;
  double __pyx_v_lr_pu;
  double __pyx_v_lr_qi;
  double __pyx_v_reg_bu;
  double __pyx_v_reg_bi;
  double __pyx_v_reg_pu;
  double __pyx_v_reg_qi;
  PyObject *__pyx_v_rng = NULL;
  PyObject *__pyx_v_current_epoch = NULL;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_bi;
  __Pyx_Buffer __pyx_pybuffer_bi;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_bu;
  __Pyx_Buffer __pyx_pybuffer_bu;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_pu;
  __Pyx_Buffer __pyx_pybuffer_pu;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_qi;
  __Pyx_Buffer __pyx_pybuffer_qi;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("sgd", 0);
  __pyx_pybuffer_bu.pybuffer.buf = NULL;
  __pyx_pybuffer_bu.refcount = 0;
  __pyx_pybuffernd_bu.data = NULL;
  __pyx_pybuffernd_bu.rcbuffer = &__pyx_pybuffer_bu;
  __pyx_pybuffer_bi.pybuffer.buf = NULL;
  __pyx_pybuffer_bi.refcount = 0;
  __pyx_pybuffernd_bi.data = NULL;
  __pyx_pybuffernd_bi.rcbuffer = &__pyx_pybuffer_bi;
  __pyx_pybuffer_pu.pybuffer.buf = NULL;
  __pyx_pybuffer_pu.refcount = 0;
  __pyx_pybuffernd_pu.data = NULL;
  __pyx_pybuffernd_pu.rcbuffer = &__pyx_pybuffer_pu;
  __pyx_pybuffer_qi.pybuffer.buf = NULL;
  __pyx_pybuffer_qi.refcount = 0;
  __pyx_pybuffernd_qi.data = NULL;
  __pyx_pybuffernd_qi.rcbuffer = &__pyx_pybuffer_qi;
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_14);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bi.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bu.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_pu.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_qi.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVD.sgd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bi.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bu.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_pu.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_qi.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_bu);
  __Pyx_XDECREF((PyObject *)__pyx_v_bi);
  __Pyx_XDECREF((PyObject *)__pyx_v_pu);
  __Pyx_XDECREF((PyObject *)__pyx_v_qi);
  __Pyx_XDECREF(__pyx_v_rng);
  __Pyx_XDECREF(__pyx_v_current_epoch);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__9 = PyTuple_Pack(25, __pyx_n_s_self, __pyx_n_s_trainset, __pyx_n_s_bu, __pyx_n_s_bi, __pyx_n_s_pu, __pyx_n_s_qi, __pyx_n_s_u, __pyx_n_s_i, __pyx_n_s_f, __pyx_n_s_r, __pyx_n_s_err, __pyx_n_s_dot, __pyx_n_s_puf, __pyx_n_s_qif, __pyx_n_s_global_mean, __pyx_n_s_lr_bu, __pyx_n_s_lr_bi, __pyx_n_s_lr_pu, __pyx_n_s_lr_qi, __pyx_n_s_reg_bu, __pyx_n_s_reg_bi, __pyx_n_s_reg_pu, __pyx_n_s_reg_qi, __pyx_n_s_rng, __pyx_n_s_current_epoch); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(0, 163, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__9);
  __Pyx_GIVEREF(__pyx_tuple__9);
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_5sgd, 0, __pyx_n_s_SVD_sgd, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__10)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 163, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_sgd, __pyx_t_4) < 0) __PYX_ERR(0, 163, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_codeobj__10 = (PyObject*)__Pyx_PyCode_New(2, 0, 25, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__9, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_sgd, 163, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__10)) __PYX_ERR(0, 163, __pyx_L1_error)
 164: 
 165:         # OK, let's breath. I've seen so many different implementation of this
 166:         # algorithm that I just not sure anymore of what it should do. I've
 167:         # implemented the version as described in the BellKor papers (RS
 168:         # Handbook, etc.). Mymedialite also does it this way. In his post
 169:         # however, Funk seems to implicitly say that the algo looks like this
 170:         # (see reg below):
 171:         # for f in range(n_factors):
 172:         #       for _ in range(n_iter):
 173:         #           for u, i, r in all_ratings:
 174:         #               err = r_ui - <p[u, :f+1], q[i, :f+1]>
 175:         #               update p[u, f]
 176:         #               update q[i, f]
 177:         # which is also the way https://github.com/aaw/IncrementalSVD.jl
 178:         # implemented it.
 179:         #
 180:         # Funk: "Anyway, this will train one feature (aspect), and in
 181:         # particular will find the most prominent feature remaining (the one
 182:         # that will most reduce the error that's left over after previously
 183:         # trained features have done their best). When it's as good as it's
 184:         # going to get, shift it onto the pile of done features, and start a
 185:         # new one. For efficiency's sake, cache the residuals (all 100 million
 186:         # of them) so when you're training feature 72 you don't have to wait
 187:         # for predictRating() to re-compute the contributions of the previous
 188:         # 71 features. You will need 2 Gig of ram, a C compiler, and good
 189:         # programming habits to do this."
 190: 
 191:         # A note on cythonization: I haven't dived into the details, but
 192:         # accessing 2D arrays like pu using just one of the indices like pu[u]
 193:         # is not efficient. That's why the old (cleaner) version can't be used
 194:         # anymore, we need to compute the dot products by hand, and update
 195:         # user and items factors by iterating over all factors...
 196: 
 197:         # user biases
 198:         cdef np.ndarray[np.double_t] bu
 199:         # item biases
 200:         cdef np.ndarray[np.double_t] bi
 201:         # user factors
 202:         cdef np.ndarray[np.double_t, ndim=2] pu
 203:         # item factors
 204:         cdef np.ndarray[np.double_t, ndim=2] qi
 205: 
 206:         cdef int u, i, f
 207:         cdef double r, err, dot, puf, qif
+208:         cdef double global_mean = self.trainset.global_mean
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 208, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_global_mean); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 208, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 208, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_global_mean = __pyx_t_3;
 209: 
+210:         cdef double lr_bu = self.lr_bu
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_bu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 210, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 210, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_lr_bu = __pyx_t_3;
+211:         cdef double lr_bi = self.lr_bi
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_bi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 211, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 211, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_lr_bi = __pyx_t_3;
+212:         cdef double lr_pu = self.lr_pu
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_pu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 212, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 212, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_lr_pu = __pyx_t_3;
+213:         cdef double lr_qi = self.lr_qi
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_qi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 213, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 213, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_lr_qi = __pyx_t_3;
 214: 
+215:         cdef double reg_bu = self.reg_bu
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_bu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 215, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 215, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_reg_bu = __pyx_t_3;
+216:         cdef double reg_bi = self.reg_bi
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_bi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 216, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 216, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_reg_bi = __pyx_t_3;
+217:         cdef double reg_pu = self.reg_pu
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_pu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_reg_pu = __pyx_t_3;
+218:         cdef double reg_qi = self.reg_qi
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_qi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_reg_qi = __pyx_t_3;
 219: 
+220:         rng = get_rng(self.random_state)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_get_rng); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 220, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_random_state); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 220, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_5 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_1, function);
    }
  }
  __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 220, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_rng = __pyx_t_2;
  __pyx_t_2 = 0;
 221: 
+222:         bu = np.zeros(trainset.n_users, np.double)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 222, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 222, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_users); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 222, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 222, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_double); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 222, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = NULL;
  __pyx_t_7 = 0;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
      __pyx_t_7 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_4)) {
    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_1, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 222, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_1, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 222, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  {
    __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 222, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    if (__pyx_t_5) {
      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_6);
    PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_6);
    __pyx_t_1 = 0;
    __pyx_t_6 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 222, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 222, __pyx_L1_error)
  __pyx_t_9 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bu.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bu.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bu.rcbuffer->pybuffer, (PyObject*)__pyx_v_bu, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_12);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
      }
      __pyx_t_10 = __pyx_t_11 = __pyx_t_12 = 0;
    }
    __pyx_pybuffernd_bu.diminfo[0].strides = __pyx_pybuffernd_bu.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_bu.diminfo[0].shape = __pyx_pybuffernd_bu.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 222, __pyx_L1_error)
  }
  __pyx_t_9 = 0;
  __pyx_v_bu = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+223:         bi = np.zeros(trainset.n_items, np.double)
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_np); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 223, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_zeros); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 223, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_items); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 223, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_np); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 223, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_double); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 223, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_6 = NULL;
  __pyx_t_7 = 0;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_6)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
      __pyx_t_7 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_4, __pyx_t_1};
    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 223, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_4, __pyx_t_1};
    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 223, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else
  #endif
  {
    __pyx_t_5 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 223, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    if (__pyx_t_6) {
      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_6); __pyx_t_6 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_4);
    PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_7, __pyx_t_4);
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_7, __pyx_t_1);
    __pyx_t_4 = 0;
    __pyx_t_1 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 223, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  }
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 223, __pyx_L1_error)
  __pyx_t_13 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bi.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bi.rcbuffer->pybuffer, (PyObject*)__pyx_t_13, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bi.rcbuffer->pybuffer, (PyObject*)__pyx_v_bi, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_10);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_12, __pyx_t_11, __pyx_t_10);
      }
      __pyx_t_12 = __pyx_t_11 = __pyx_t_10 = 0;
    }
    __pyx_pybuffernd_bi.diminfo[0].strides = __pyx_pybuffernd_bi.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_bi.diminfo[0].shape = __pyx_pybuffernd_bi.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 223, __pyx_L1_error)
  }
  __pyx_t_13 = 0;
  __pyx_v_bi = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+224:         pu = rng.normal(self.init_mean, self.init_std_dev,
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_rng, __pyx_n_s_normal); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 224, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_mean); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 224, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_std_dev); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 224, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
/* … */
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 224, __pyx_L1_error)
  __pyx_t_15 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_pu.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_pu.rcbuffer->pybuffer, (PyObject*)__pyx_t_15, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_pu.rcbuffer->pybuffer, (PyObject*)__pyx_v_pu, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_12);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
      }
      __pyx_t_10 = __pyx_t_11 = __pyx_t_12 = 0;
    }
    __pyx_pybuffernd_pu.diminfo[0].strides = __pyx_pybuffernd_pu.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_pu.diminfo[0].shape = __pyx_pybuffernd_pu.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_pu.diminfo[1].strides = __pyx_pybuffernd_pu.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_pu.diminfo[1].shape = __pyx_pybuffernd_pu.rcbuffer->pybuffer.shape[1];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 224, __pyx_L1_error)
  }
  __pyx_t_15 = 0;
  __pyx_v_pu = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+225:                         (trainset.n_users, self.n_factors))
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_users); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 225, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 225, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_14 = PyTuple_New(2); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 225, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_GIVEREF(__pyx_t_4);
  PyTuple_SET_ITEM(__pyx_t_14, 0, __pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_6);
  PyTuple_SET_ITEM(__pyx_t_14, 1, __pyx_t_6);
  __pyx_t_4 = 0;
  __pyx_t_6 = 0;
  __pyx_t_6 = NULL;
  __pyx_t_7 = 0;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_6)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
      __pyx_t_7 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[4] = {__pyx_t_6, __pyx_t_5, __pyx_t_1, __pyx_t_14};
    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 224, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[4] = {__pyx_t_6, __pyx_t_5, __pyx_t_1, __pyx_t_14};
    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 224, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  } else
  #endif
  {
    __pyx_t_4 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 224, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    if (__pyx_t_6) {
      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6); __pyx_t_6 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_5);
    PyTuple_SET_ITEM(__pyx_t_4, 0+__pyx_t_7, __pyx_t_5);
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_4, 1+__pyx_t_7, __pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_14);
    PyTuple_SET_ITEM(__pyx_t_4, 2+__pyx_t_7, __pyx_t_14);
    __pyx_t_5 = 0;
    __pyx_t_1 = 0;
    __pyx_t_14 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 224, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  }
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+226:         qi = rng.normal(self.init_mean, self.init_std_dev,
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_rng, __pyx_n_s_normal); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 226, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_mean); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 226, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_std_dev); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 226, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
/* … */
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 226, __pyx_L1_error)
  __pyx_t_16 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_qi.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_qi.rcbuffer->pybuffer, (PyObject*)__pyx_t_16, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_qi.rcbuffer->pybuffer, (PyObject*)__pyx_v_qi, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_10);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_12, __pyx_t_11, __pyx_t_10);
      }
      __pyx_t_12 = __pyx_t_11 = __pyx_t_10 = 0;
    }
    __pyx_pybuffernd_qi.diminfo[0].strides = __pyx_pybuffernd_qi.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_qi.diminfo[0].shape = __pyx_pybuffernd_qi.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_qi.diminfo[1].strides = __pyx_pybuffernd_qi.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_qi.diminfo[1].shape = __pyx_pybuffernd_qi.rcbuffer->pybuffer.shape[1];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 226, __pyx_L1_error)
  }
  __pyx_t_16 = 0;
  __pyx_v_qi = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+227:                         (trainset.n_items, self.n_factors))
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_5);
  PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_5);
  __pyx_t_1 = 0;
  __pyx_t_5 = 0;
  __pyx_t_5 = NULL;
  __pyx_t_7 = 0;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
      __pyx_t_7 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_t_4, __pyx_t_14, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 226, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_t_4, __pyx_t_14, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 226, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  {
    __pyx_t_1 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 226, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (__pyx_t_5) {
      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5); __pyx_t_5 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_4);
    PyTuple_SET_ITEM(__pyx_t_1, 0+__pyx_t_7, __pyx_t_4);
    __Pyx_GIVEREF(__pyx_t_14);
    PyTuple_SET_ITEM(__pyx_t_1, 1+__pyx_t_7, __pyx_t_14);
    __Pyx_GIVEREF(__pyx_t_6);
    PyTuple_SET_ITEM(__pyx_t_1, 2+__pyx_t_7, __pyx_t_6);
    __pyx_t_4 = 0;
    __pyx_t_14 = 0;
    __pyx_t_6 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 226, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  }
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
 228: 
+229:         if not self.biased:
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_biased); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 229, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_17 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_17 < 0)) __PYX_ERR(0, 229, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_18 = ((!__pyx_t_17) != 0);
  if (__pyx_t_18) {
/* … */
  }
+230:             global_mean = 0
    __pyx_v_global_mean = 0.0;
 231: 
+232:         for current_epoch in range(self.n_epochs):
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_range); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 232, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_epochs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 232, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_6 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_6)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
    }
  }
  __pyx_t_2 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_6, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_1);
  __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 232, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
    __pyx_t_8 = __pyx_t_2; __Pyx_INCREF(__pyx_t_8); __pyx_t_19 = 0;
    __pyx_t_20 = NULL;
  } else {
    __pyx_t_19 = -1; __pyx_t_8 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 232, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __pyx_t_20 = Py_TYPE(__pyx_t_8)->tp_iternext; if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 232, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  for (;;) {
    if (likely(!__pyx_t_20)) {
      if (likely(PyList_CheckExact(__pyx_t_8))) {
        if (__pyx_t_19 >= PyList_GET_SIZE(__pyx_t_8)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyList_GET_ITEM(__pyx_t_8, __pyx_t_19); __Pyx_INCREF(__pyx_t_2); __pyx_t_19++; if (unlikely(0 < 0)) __PYX_ERR(0, 232, __pyx_L1_error)
        #else
        __pyx_t_2 = PySequence_ITEM(__pyx_t_8, __pyx_t_19); __pyx_t_19++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 232, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      } else {
        if (__pyx_t_19 >= PyTuple_GET_SIZE(__pyx_t_8)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_8, __pyx_t_19); __Pyx_INCREF(__pyx_t_2); __pyx_t_19++; if (unlikely(0 < 0)) __PYX_ERR(0, 232, __pyx_L1_error)
        #else
        __pyx_t_2 = PySequence_ITEM(__pyx_t_8, __pyx_t_19); __pyx_t_19++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 232, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      }
    } else {
      __pyx_t_2 = __pyx_t_20(__pyx_t_8);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 232, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_XDECREF_SET(__pyx_v_current_epoch, __pyx_t_2);
    __pyx_t_2 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+233:             if self.verbose:
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_verbose); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 233, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_18 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_18 < 0)) __PYX_ERR(0, 233, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (__pyx_t_18) {
/* … */
    }
+234:                 print("Processing epoch {}".format(current_epoch))
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Processing_epoch, __pyx_n_s_format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 234, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_6 = NULL;
      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) {
        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1);
        if (likely(__pyx_t_6)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
          __Pyx_INCREF(__pyx_t_6);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_1, function);
        }
      }
      __pyx_t_2 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_v_current_epoch) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_current_epoch);
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 234, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 234, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+235:             for u, i, r in trainset.all_ratings():
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_all_ratings); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 235, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_6 = NULL;
    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_2);
      if (likely(__pyx_t_6)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
        __Pyx_INCREF(__pyx_t_6);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_2, function);
      }
    }
    __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_6) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 235, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
      __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_21 = 0;
      __pyx_t_22 = NULL;
    } else {
      __pyx_t_21 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 235, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_22 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 235, __pyx_L1_error)
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    for (;;) {
      if (likely(!__pyx_t_22)) {
        if (likely(PyList_CheckExact(__pyx_t_2))) {
          if (__pyx_t_21 >= PyList_GET_SIZE(__pyx_t_2)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_21); __Pyx_INCREF(__pyx_t_1); __pyx_t_21++; if (unlikely(0 < 0)) __PYX_ERR(0, 235, __pyx_L1_error)
          #else
          __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_21); __pyx_t_21++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 235, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          #endif
        } else {
          if (__pyx_t_21 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_21); __Pyx_INCREF(__pyx_t_1); __pyx_t_21++; if (unlikely(0 < 0)) __PYX_ERR(0, 235, __pyx_L1_error)
          #else
          __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_21); __pyx_t_21++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 235, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          #endif
        }
      } else {
        __pyx_t_1 = __pyx_t_22(__pyx_t_2);
        if (unlikely(!__pyx_t_1)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 235, __pyx_L1_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_1);
      }
      if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
        PyObject* sequence = __pyx_t_1;
        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
        if (unlikely(size != 3)) {
          if (size > 3) __Pyx_RaiseTooManyValuesError(3);
          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
          __PYX_ERR(0, 235, __pyx_L1_error)
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        if (likely(PyTuple_CheckExact(sequence))) {
          __pyx_t_6 = PyTuple_GET_ITEM(sequence, 0); 
          __pyx_t_14 = PyTuple_GET_ITEM(sequence, 1); 
          __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2); 
        } else {
          __pyx_t_6 = PyList_GET_ITEM(sequence, 0); 
          __pyx_t_14 = PyList_GET_ITEM(sequence, 1); 
          __pyx_t_4 = PyList_GET_ITEM(sequence, 2); 
        }
        __Pyx_INCREF(__pyx_t_6);
        __Pyx_INCREF(__pyx_t_14);
        __Pyx_INCREF(__pyx_t_4);
        #else
        __pyx_t_6 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 235, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __pyx_t_14 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 235, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_14);
        __pyx_t_4 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 235, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        #endif
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      } else {
        Py_ssize_t index = -1;
        __pyx_t_5 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 235, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_5);
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_t_23 = Py_TYPE(__pyx_t_5)->tp_iternext;
        index = 0; __pyx_t_6 = __pyx_t_23(__pyx_t_5); if (unlikely(!__pyx_t_6)) goto __pyx_L9_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_6);
        index = 1; __pyx_t_14 = __pyx_t_23(__pyx_t_5); if (unlikely(!__pyx_t_14)) goto __pyx_L9_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_14);
        index = 2; __pyx_t_4 = __pyx_t_23(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L9_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_4);
        if (__Pyx_IternextUnpackEndCheck(__pyx_t_23(__pyx_t_5), 3) < 0) __PYX_ERR(0, 235, __pyx_L1_error)
        __pyx_t_23 = NULL;
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        goto __pyx_L10_unpacking_done;
        __pyx_L9_unpacking_failed:;
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        __pyx_t_23 = NULL;
        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
        __PYX_ERR(0, 235, __pyx_L1_error)
        __pyx_L10_unpacking_done:;
      }
      __pyx_t_7 = __Pyx_PyInt_As_int(__pyx_t_6); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 235, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __pyx_t_24 = __Pyx_PyInt_As_int(__pyx_t_14); if (unlikely((__pyx_t_24 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 235, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
      __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_4); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 235, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __pyx_v_u = __pyx_t_7;
      __pyx_v_i = __pyx_t_24;
      __pyx_v_r = __pyx_t_3;
/* … */
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 236: 
 237:                 # compute current error
+238:                 dot = 0  # <q_i, p_u>
      __pyx_v_dot = 0.0;
+239:                 for f in range(self.n_factors):
      __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_range); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 239, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 239, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_14);
      __pyx_t_6 = NULL;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4);
        if (likely(__pyx_t_6)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
          __Pyx_INCREF(__pyx_t_6);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_4, function);
        }
      }
      __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_14) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_14);
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 239, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
        __pyx_t_4 = __pyx_t_1; __Pyx_INCREF(__pyx_t_4); __pyx_t_25 = 0;
        __pyx_t_26 = NULL;
      } else {
        __pyx_t_25 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 239, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __pyx_t_26 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_26)) __PYX_ERR(0, 239, __pyx_L1_error)
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      for (;;) {
        if (likely(!__pyx_t_26)) {
          if (likely(PyList_CheckExact(__pyx_t_4))) {
            if (__pyx_t_25 >= PyList_GET_SIZE(__pyx_t_4)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_1 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_25); __Pyx_INCREF(__pyx_t_1); __pyx_t_25++; if (unlikely(0 < 0)) __PYX_ERR(0, 239, __pyx_L1_error)
            #else
            __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_25); __pyx_t_25++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 239, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_1);
            #endif
          } else {
            if (__pyx_t_25 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_25); __Pyx_INCREF(__pyx_t_1); __pyx_t_25++; if (unlikely(0 < 0)) __PYX_ERR(0, 239, __pyx_L1_error)
            #else
            __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_25); __pyx_t_25++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 239, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_1);
            #endif
          }
        } else {
          __pyx_t_1 = __pyx_t_26(__pyx_t_4);
          if (unlikely(!__pyx_t_1)) {
            PyObject* exc_type = PyErr_Occurred();
            if (exc_type) {
              if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
              else __PYX_ERR(0, 239, __pyx_L1_error)
            }
            break;
          }
          __Pyx_GOTREF(__pyx_t_1);
        }
        __pyx_t_24 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_24 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 239, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_v_f = __pyx_t_24;
/* … */
      }
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+240:                     dot += qi[i, f] * pu[u, f]
        __pyx_t_27 = __pyx_v_i;
        __pyx_t_28 = __pyx_v_f;
        __pyx_t_24 = -1;
        if (__pyx_t_27 < 0) {
          __pyx_t_27 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_27 < 0)) __pyx_t_24 = 0;
        } else if (unlikely(__pyx_t_27 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_24 = 0;
        if (__pyx_t_28 < 0) {
          __pyx_t_28 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_28 < 0)) __pyx_t_24 = 1;
        } else if (unlikely(__pyx_t_28 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_24 = 1;
        if (unlikely(__pyx_t_24 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_24);
          __PYX_ERR(0, 240, __pyx_L1_error)
        }
        __pyx_t_29 = __pyx_v_u;
        __pyx_t_30 = __pyx_v_f;
        __pyx_t_24 = -1;
        if (__pyx_t_29 < 0) {
          __pyx_t_29 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_29 < 0)) __pyx_t_24 = 0;
        } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_24 = 0;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_24 = 1;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_24 = 1;
        if (unlikely(__pyx_t_24 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_24);
          __PYX_ERR(0, 240, __pyx_L1_error)
        }
        __pyx_v_dot = (__pyx_v_dot + ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_27, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_28, __pyx_pybuffernd_qi.diminfo[1].strides)) * (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_30, __pyx_pybuffernd_pu.diminfo[1].strides))));
+241:                 err = r - (global_mean + bu[u] + bi[i] + dot)
      __pyx_t_30 = __pyx_v_u;
      __pyx_t_24 = -1;
      if (__pyx_t_30 < 0) {
        __pyx_t_30 += __pyx_pybuffernd_bu.diminfo[0].shape;
        if (unlikely(__pyx_t_30 < 0)) __pyx_t_24 = 0;
      } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_bu.diminfo[0].shape)) __pyx_t_24 = 0;
      if (unlikely(__pyx_t_24 != -1)) {
        __Pyx_RaiseBufferIndexError(__pyx_t_24);
        __PYX_ERR(0, 241, __pyx_L1_error)
      }
      __pyx_t_29 = __pyx_v_i;
      __pyx_t_24 = -1;
      if (__pyx_t_29 < 0) {
        __pyx_t_29 += __pyx_pybuffernd_bi.diminfo[0].shape;
        if (unlikely(__pyx_t_29 < 0)) __pyx_t_24 = 0;
      } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_bi.diminfo[0].shape)) __pyx_t_24 = 0;
      if (unlikely(__pyx_t_24 != -1)) {
        __Pyx_RaiseBufferIndexError(__pyx_t_24);
        __PYX_ERR(0, 241, __pyx_L1_error)
      }
      __pyx_v_err = (__pyx_v_r - (((__pyx_v_global_mean + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bu.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_bu.diminfo[0].strides))) + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bi.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_bi.diminfo[0].strides))) + __pyx_v_dot));
 242: 
 243:                 # update biases
+244:                 if self.biased:
      __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_biased); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 244, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __pyx_t_18 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_18 < 0)) __PYX_ERR(0, 244, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (__pyx_t_18) {
/* … */
      }
+245:                     bu[u] += lr_bu * (err - reg_bu * bu[u])
        __pyx_t_29 = __pyx_v_u;
        __pyx_t_24 = -1;
        if (__pyx_t_29 < 0) {
          __pyx_t_29 += __pyx_pybuffernd_bu.diminfo[0].shape;
          if (unlikely(__pyx_t_29 < 0)) __pyx_t_24 = 0;
        } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_bu.diminfo[0].shape)) __pyx_t_24 = 0;
        if (unlikely(__pyx_t_24 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_24);
          __PYX_ERR(0, 245, __pyx_L1_error)
        }
        __pyx_t_30 = __pyx_v_u;
        __pyx_t_24 = -1;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_bu.diminfo[0].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_24 = 0;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_bu.diminfo[0].shape)) __pyx_t_24 = 0;
        if (unlikely(__pyx_t_24 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_24);
          __PYX_ERR(0, 245, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bu.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_bu.diminfo[0].strides) += (__pyx_v_lr_bu * (__pyx_v_err - (__pyx_v_reg_bu * (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bu.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_bu.diminfo[0].strides)))));
+246:                     bi[i] += lr_bi * (err - reg_bi * bi[i])
        __pyx_t_29 = __pyx_v_i;
        __pyx_t_24 = -1;
        if (__pyx_t_29 < 0) {
          __pyx_t_29 += __pyx_pybuffernd_bi.diminfo[0].shape;
          if (unlikely(__pyx_t_29 < 0)) __pyx_t_24 = 0;
        } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_bi.diminfo[0].shape)) __pyx_t_24 = 0;
        if (unlikely(__pyx_t_24 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_24);
          __PYX_ERR(0, 246, __pyx_L1_error)
        }
        __pyx_t_30 = __pyx_v_i;
        __pyx_t_24 = -1;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_bi.diminfo[0].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_24 = 0;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_bi.diminfo[0].shape)) __pyx_t_24 = 0;
        if (unlikely(__pyx_t_24 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_24);
          __PYX_ERR(0, 246, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bi.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_bi.diminfo[0].strides) += (__pyx_v_lr_bi * (__pyx_v_err - (__pyx_v_reg_bi * (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bi.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_bi.diminfo[0].strides)))));
 247: 
 248:                 # update factors
+249:                 for f in range(self.n_factors):
      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_range); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 249, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 249, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_14);
      __pyx_t_6 = NULL;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1);
        if (likely(__pyx_t_6)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
          __Pyx_INCREF(__pyx_t_6);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_1, function);
        }
      }
      __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_14) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_14);
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 249, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (likely(PyList_CheckExact(__pyx_t_4)) || PyTuple_CheckExact(__pyx_t_4)) {
        __pyx_t_1 = __pyx_t_4; __Pyx_INCREF(__pyx_t_1); __pyx_t_25 = 0;
        __pyx_t_26 = NULL;
      } else {
        __pyx_t_25 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 249, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __pyx_t_26 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_26)) __PYX_ERR(0, 249, __pyx_L1_error)
      }
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      for (;;) {
        if (likely(!__pyx_t_26)) {
          if (likely(PyList_CheckExact(__pyx_t_1))) {
            if (__pyx_t_25 >= PyList_GET_SIZE(__pyx_t_1)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_25); __Pyx_INCREF(__pyx_t_4); __pyx_t_25++; if (unlikely(0 < 0)) __PYX_ERR(0, 249, __pyx_L1_error)
            #else
            __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_25); __pyx_t_25++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 249, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_4);
            #endif
          } else {
            if (__pyx_t_25 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_25); __Pyx_INCREF(__pyx_t_4); __pyx_t_25++; if (unlikely(0 < 0)) __PYX_ERR(0, 249, __pyx_L1_error)
            #else
            __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_25); __pyx_t_25++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 249, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_4);
            #endif
          }
        } else {
          __pyx_t_4 = __pyx_t_26(__pyx_t_1);
          if (unlikely(!__pyx_t_4)) {
            PyObject* exc_type = PyErr_Occurred();
            if (exc_type) {
              if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
              else __PYX_ERR(0, 249, __pyx_L1_error)
            }
            break;
          }
          __Pyx_GOTREF(__pyx_t_4);
        }
        __pyx_t_24 = __Pyx_PyInt_As_int(__pyx_t_4); if (unlikely((__pyx_t_24 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 249, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        __pyx_v_f = __pyx_t_24;
/* … */
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+250:                     puf = pu[u, f]
        __pyx_t_29 = __pyx_v_u;
        __pyx_t_30 = __pyx_v_f;
        __pyx_t_24 = -1;
        if (__pyx_t_29 < 0) {
          __pyx_t_29 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_29 < 0)) __pyx_t_24 = 0;
        } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_24 = 0;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_24 = 1;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_24 = 1;
        if (unlikely(__pyx_t_24 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_24);
          __PYX_ERR(0, 250, __pyx_L1_error)
        }
        __pyx_v_puf = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_30, __pyx_pybuffernd_pu.diminfo[1].strides));
+251:                     qif = qi[i, f]
        __pyx_t_30 = __pyx_v_i;
        __pyx_t_29 = __pyx_v_f;
        __pyx_t_24 = -1;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_24 = 0;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_24 = 0;
        if (__pyx_t_29 < 0) {
          __pyx_t_29 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_29 < 0)) __pyx_t_24 = 1;
        } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_24 = 1;
        if (unlikely(__pyx_t_24 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_24);
          __PYX_ERR(0, 251, __pyx_L1_error)
        }
        __pyx_v_qif = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_29, __pyx_pybuffernd_qi.diminfo[1].strides));
+252:                     pu[u, f] += lr_pu * (err * qif - reg_pu * puf)
        __pyx_t_29 = __pyx_v_u;
        __pyx_t_30 = __pyx_v_f;
        __pyx_t_24 = -1;
        if (__pyx_t_29 < 0) {
          __pyx_t_29 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_29 < 0)) __pyx_t_24 = 0;
        } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_24 = 0;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_24 = 1;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_24 = 1;
        if (unlikely(__pyx_t_24 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_24);
          __PYX_ERR(0, 252, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_30, __pyx_pybuffernd_pu.diminfo[1].strides) += (__pyx_v_lr_pu * ((__pyx_v_err * __pyx_v_qif) - (__pyx_v_reg_pu * __pyx_v_puf)));
+253:                     qi[i, f] += lr_qi * (err * puf - reg_qi * qif)
        __pyx_t_30 = __pyx_v_i;
        __pyx_t_29 = __pyx_v_f;
        __pyx_t_24 = -1;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_24 = 0;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_24 = 0;
        if (__pyx_t_29 < 0) {
          __pyx_t_29 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_29 < 0)) __pyx_t_24 = 1;
        } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_24 = 1;
        if (unlikely(__pyx_t_24 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_24);
          __PYX_ERR(0, 253, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_29, __pyx_pybuffernd_qi.diminfo[1].strides) += (__pyx_v_lr_qi * ((__pyx_v_err * __pyx_v_puf) - (__pyx_v_reg_qi * __pyx_v_qif)));
 254: 
+255:         self.bu = bu
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_bu, ((PyObject *)__pyx_v_bu)) < 0) __PYX_ERR(0, 255, __pyx_L1_error)
+256:         self.bi = bi
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_bi, ((PyObject *)__pyx_v_bi)) < 0) __PYX_ERR(0, 256, __pyx_L1_error)
+257:         self.pu = pu
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_pu, ((PyObject *)__pyx_v_pu)) < 0) __PYX_ERR(0, 257, __pyx_L1_error)
+258:         self.qi = qi
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_qi, ((PyObject *)__pyx_v_qi)) < 0) __PYX_ERR(0, 258, __pyx_L1_error)
 259: 
+260:     def estimate(self, u, i):
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_7estimate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_7estimate = {"estimate", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_7estimate, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_7estimate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_u = 0;
  PyObject *__pyx_v_i = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("estimate (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_u,&__pyx_n_s_i,0};
    PyObject* values[3] = {0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_u)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("estimate", 1, 3, 3, 1); __PYX_ERR(0, 260, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_i)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("estimate", 1, 3, 3, 2); __PYX_ERR(0, 260, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "estimate") < 0)) __PYX_ERR(0, 260, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
    }
    __pyx_v_self = values[0];
    __pyx_v_u = values[1];
    __pyx_v_i = values[2];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("estimate", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 260, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVD.estimate", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_6estimate(__pyx_self, __pyx_v_self, __pyx_v_u, __pyx_v_i);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_6estimate(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_u, PyObject *__pyx_v_i) {
  PyObject *__pyx_v_known_user = NULL;
  PyObject *__pyx_v_known_item = NULL;
  PyObject *__pyx_v_est = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("estimate", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVD.estimate", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_known_user);
  __Pyx_XDECREF(__pyx_v_known_item);
  __Pyx_XDECREF(__pyx_v_est);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__11 = PyTuple_Pack(6, __pyx_n_s_self, __pyx_n_s_u, __pyx_n_s_i, __pyx_n_s_known_user, __pyx_n_s_known_item, __pyx_n_s_est); if (unlikely(!__pyx_tuple__11)) __PYX_ERR(0, 260, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__11);
  __Pyx_GIVEREF(__pyx_tuple__11);
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3SVD_7estimate, 0, __pyx_n_s_SVD_estimate, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__12)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 260, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_estimate, __pyx_t_4) < 0) __PYX_ERR(0, 260, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_codeobj__12 = (PyObject*)__Pyx_PyCode_New(3, 0, 6, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__11, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_estimate, 260, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__12)) __PYX_ERR(0, 260, __pyx_L1_error)
 261:         # Should we cythonize this as well?
 262: 
+263:         known_user = self.trainset.knows_user(u)
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 263, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_knows_user); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 263, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_2)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_v_u) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_u);
  __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 263, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_known_user = __pyx_t_1;
  __pyx_t_1 = 0;
+264:         known_item = self.trainset.knows_item(i)
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 264, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_knows_item); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 264, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_2, function);
    }
  }
  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_i) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_i);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 264, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_known_item = __pyx_t_1;
  __pyx_t_1 = 0;
 265: 
+266:         if self.biased:
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_biased); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 266, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 266, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (__pyx_t_4) {
/* … */
    goto __pyx_L3;
  }
+267:             est = self.trainset.global_mean
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 267, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_global_mean); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 267, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_est = __pyx_t_2;
    __pyx_t_2 = 0;
 268: 
+269:             if known_user:
    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_known_user); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 269, __pyx_L1_error)
    if (__pyx_t_4) {
/* … */
    }
+270:                 est += self.bu[u]
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_bu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 270, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_v_u); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 270, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_est, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 270, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF_SET(__pyx_v_est, __pyx_t_2);
      __pyx_t_2 = 0;
 271: 
+272:             if known_item:
    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_known_item); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 272, __pyx_L1_error)
    if (__pyx_t_4) {
/* … */
    }
+273:                 est += self.bi[i]
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_bi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 273, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_v_i); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 273, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_est, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 273, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF_SET(__pyx_v_est, __pyx_t_2);
      __pyx_t_2 = 0;
 274: 
+275:             if known_user and known_item:
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_known_user); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 275, __pyx_L1_error)
    if (__pyx_t_5) {
    } else {
      __pyx_t_4 = __pyx_t_5;
      goto __pyx_L7_bool_binop_done;
    }
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_known_item); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 275, __pyx_L1_error)
    __pyx_t_4 = __pyx_t_5;
    __pyx_L7_bool_binop_done:;
    if (__pyx_t_4) {
/* … */
    }
+276:                 est += np.dot(self.qi[i], self.pu[u])
      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 276, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_dot); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 276, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_qi); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 276, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_v_i); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 276, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_pu); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 276, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_7 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_v_u); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 276, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = NULL;
      __pyx_t_8 = 0;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3);
        if (likely(__pyx_t_1)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
          __Pyx_INCREF(__pyx_t_1);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_3, function);
          __pyx_t_8 = 1;
        }
      }
      #if CYTHON_FAST_PYCALL
      if (PyFunction_Check(__pyx_t_3)) {
        PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_t_6, __pyx_t_7};
        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 276, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      } else
      #endif
      #if CYTHON_FAST_PYCCALL
      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
        PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_t_6, __pyx_t_7};
        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 276, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      } else
      #endif
      {
        __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 276, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_9);
        if (__pyx_t_1) {
          __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_1); __pyx_t_1 = NULL;
        }
        __Pyx_GIVEREF(__pyx_t_6);
        PyTuple_SET_ITEM(__pyx_t_9, 0+__pyx_t_8, __pyx_t_6);
        __Pyx_GIVEREF(__pyx_t_7);
        PyTuple_SET_ITEM(__pyx_t_9, 1+__pyx_t_8, __pyx_t_7);
        __pyx_t_6 = 0;
        __pyx_t_7 = 0;
        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_9, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 276, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_3 = PyNumber_InPlaceAdd(__pyx_v_est, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 276, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF_SET(__pyx_v_est, __pyx_t_3);
      __pyx_t_3 = 0;
 277: 
 278:         else:
+279:             if known_user and known_item:
  /*else*/ {
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_known_user); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 279, __pyx_L1_error)
    if (__pyx_t_5) {
    } else {
      __pyx_t_4 = __pyx_t_5;
      goto __pyx_L10_bool_binop_done;
    }
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_known_item); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 279, __pyx_L1_error)
    __pyx_t_4 = __pyx_t_5;
    __pyx_L10_bool_binop_done:;
    if (likely(__pyx_t_4)) {
/* … */
      goto __pyx_L9;
    }
+280:                 est = np.dot(self.qi[i], self.pu[u])
      __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_dot); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_qi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_7 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_v_i); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_pu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_v_u); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = NULL;
      __pyx_t_8 = 0;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) {
        __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_9);
        if (likely(__pyx_t_2)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9);
          __Pyx_INCREF(__pyx_t_2);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_9, function);
          __pyx_t_8 = 1;
        }
      }
      #if CYTHON_FAST_PYCALL
      if (PyFunction_Check(__pyx_t_9)) {
        PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_t_7, __pyx_t_6};
        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 280, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      } else
      #endif
      #if CYTHON_FAST_PYCCALL
      if (__Pyx_PyFastCFunction_Check(__pyx_t_9)) {
        PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_t_7, __pyx_t_6};
        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 280, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      } else
      #endif
      {
        __pyx_t_1 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 280, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        if (__pyx_t_2) {
          __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2); __pyx_t_2 = NULL;
        }
        __Pyx_GIVEREF(__pyx_t_7);
        PyTuple_SET_ITEM(__pyx_t_1, 0+__pyx_t_8, __pyx_t_7);
        __Pyx_GIVEREF(__pyx_t_6);
        PyTuple_SET_ITEM(__pyx_t_1, 1+__pyx_t_8, __pyx_t_6);
        __pyx_t_7 = 0;
        __pyx_t_6 = 0;
        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 280, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      }
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __pyx_v_est = __pyx_t_3;
      __pyx_t_3 = 0;
 281:             else:
+282:                 raise PredictionImpossible('User and item are unknown.')
    /*else*/ {
      __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_PredictionImpossible); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 282, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __pyx_t_1 = NULL;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) {
        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_9);
        if (likely(__pyx_t_1)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9);
          __Pyx_INCREF(__pyx_t_1);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_9, function);
        }
      }
      __pyx_t_3 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_9, __pyx_t_1, __pyx_kp_u_User_and_item_are_unknown) : __Pyx_PyObject_CallOneArg(__pyx_t_9, __pyx_kp_u_User_and_item_are_unknown);
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 282, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_Raise(__pyx_t_3, 0, 0, 0);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __PYX_ERR(0, 282, __pyx_L1_error)
    }
    __pyx_L9:;
  }
  __pyx_L3:;
 283: 
+284:         return est
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_est);
  __pyx_r = __pyx_v_est;
  goto __pyx_L0;
 285: 
 286: 
+287: class SVDpp(AlgoBase):
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_AlgoBase); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 287, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 287, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_2);
  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
  __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_CalculateMetaclass(NULL, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 287, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_2, __pyx_t_1, __pyx_n_s_SVDpp, __pyx_n_s_SVDpp, (PyObject *) NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_kp_s_The_SVD_algorithm_an_extension_o); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 287, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
/* … */
  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_2, __pyx_n_s_SVDpp, __pyx_t_1, __pyx_t_3, NULL, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 287, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_SVDpp, __pyx_t_4) < 0) __PYX_ERR(0, 287, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 288:     """The *SVD++* algorithm, an extension of :class:`SVD` taking into account
 289:     implicit ratings.
 290: 
 291:     The prediction :math:`\\hat{r}_{ui}` is set as:
 292: 
 293:     .. math::
 294:         \hat{r}_{ui} = \mu + b_u + b_i + q_i^T\\left(p_u +
 295:         |I_u|^{-\\frac{1}{2}} \sum_{j \\in I_u}y_j\\right)
 296: 
 297:     Where the :math:`y_j` terms are a new set of item factors that capture
 298:     implicit ratings. Here, an implicit rating describes the fact that a user
 299:     :math:`u` rated an item :math:`j`, regardless of the rating value.
 300: 
 301:     If user :math:`u` is unknown, then the bias :math:`b_u` and the factors
 302:     :math:`p_u` are assumed to be zero. The same applies for item :math:`i`
 303:     with :math:`b_i`, :math:`q_i` and :math:`y_i`.
 304: 
 305: 
 306:     For details, see section 4 of :cite:`Koren:2008:FMN`. See also
 307:     :cite:`Ricci:2010`, section 5.3.1.
 308: 
 309:     Just as for :class:`SVD`, the parameters are learned using a SGD on the
 310:     regularized squared error objective.
 311: 
 312:     Baselines are initialized to ``0``. User and item factors are randomly
 313:     initialized according to a normal distribution, which can be tuned using
 314:     the ``init_mean`` and ``init_std_dev`` parameters.
 315: 
 316:     You have control over the learning rate :math:`\gamma` and the
 317:     regularization term :math:`\lambda`. Both can be different for each
 318:     kind of parameter (see below). By default, learning rates are set to
 319:     ``0.005`` and regularization terms are set to ``0.02``.
 320: 
 321:     Args:
 322:         n_factors: The number of factors. Default is ``20``.
 323:         n_epochs: The number of iteration of the SGD procedure. Default is
 324:             ``20``.
 325:         init_mean: The mean of the normal distribution for factor vectors
 326:             initialization. Default is ``0``.
 327:         init_std_dev: The standard deviation of the normal distribution for
 328:             factor vectors initialization. Default is ``0.1``.
 329:         lr_all: The learning rate for all parameters. Default is ``0.007``.
 330:         reg_all: The regularization term for all parameters. Default is
 331:             ``0.02``.
 332:         lr_bu: The learning rate for :math:`b_u`. Takes precedence over
 333:             ``lr_all`` if set. Default is ``None``.
 334:         lr_bi: The learning rate for :math:`b_i`. Takes precedence over
 335:             ``lr_all`` if set. Default is ``None``.
 336:         lr_pu: The learning rate for :math:`p_u`. Takes precedence over
 337:             ``lr_all`` if set. Default is ``None``.
 338:         lr_qi: The learning rate for :math:`q_i`. Takes precedence over
 339:             ``lr_all`` if set. Default is ``None``.
 340:         lr_yj: The learning rate for :math:`y_j`. Takes precedence over
 341:             ``lr_all`` if set. Default is ``None``.
 342:         reg_bu: The regularization term for :math:`b_u`. Takes precedence
 343:             over ``reg_all`` if set. Default is ``None``.
 344:         reg_bi: The regularization term for :math:`b_i`. Takes precedence
 345:             over ``reg_all`` if set. Default is ``None``.
 346:         reg_pu: The regularization term for :math:`p_u`. Takes precedence
 347:             over ``reg_all`` if set. Default is ``None``.
 348:         reg_qi: The regularization term for :math:`q_i`. Takes precedence
 349:             over ``reg_all`` if set. Default is ``None``.
 350:         reg_yj: The regularization term for :math:`y_j`. Takes precedence
 351:             over ``reg_all`` if set. Default is ``None``.
 352:         random_state(int, RandomState instance from numpy, or ``None``):
 353:             Determines the RNG that will be used for initialization. If
 354:             int, ``random_state`` will be used as a seed for a new RNG. This is
 355:             useful to get the same initialization over multiple calls to
 356:             ``fit()``.  If RandomState instance, this same instance is used as
 357:             RNG. If ``None``, the current RNG from numpy is used.  Default is
 358:             ``None``.
 359:         verbose: If ``True``, prints the current epoch. Default is ``False``.
 360: 
 361:     Attributes:
 362:         pu(numpy array of size (n_users, n_factors)): The user factors (only
 363:             exists if ``fit()`` has been called)
 364:         qi(numpy array of size (n_items, n_factors)): The item factors (only
 365:             exists if ``fit()`` has been called)
 366:         yj(numpy array of size (n_items, n_factors)): The (implicit) item
 367:             factors (only exists if ``fit()`` has been called)
 368:         bu(numpy array of size (n_users)): The user biases (only
 369:             exists if ``fit()`` has been called)
 370:         bi(numpy array of size (n_items)): The item biases (only
 371:             exists if ``fit()`` has been called)
 372:     """
 373: 
+374:     def __init__(self, n_factors=20, n_epochs=20, init_mean=0, init_std_dev=.1,
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_1__init__ = {"__init__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_1__init__, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_n_factors = 0;
  PyObject *__pyx_v_n_epochs = 0;
  PyObject *__pyx_v_init_mean = 0;
  PyObject *__pyx_v_init_std_dev = 0;
  PyObject *__pyx_v_lr_all = 0;
  PyObject *__pyx_v_reg_all = 0;
  PyObject *__pyx_v_lr_bu = 0;
  PyObject *__pyx_v_lr_bi = 0;
  PyObject *__pyx_v_lr_pu = 0;
  PyObject *__pyx_v_lr_qi = 0;
  PyObject *__pyx_v_lr_yj = 0;
  PyObject *__pyx_v_reg_bu = 0;
  PyObject *__pyx_v_reg_bi = 0;
  PyObject *__pyx_v_reg_pu = 0;
  PyObject *__pyx_v_reg_qi = 0;
  PyObject *__pyx_v_reg_yj = 0;
  PyObject *__pyx_v_random_state = 0;
  PyObject *__pyx_v_verbose = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_n_factors,&__pyx_n_s_n_epochs,&__pyx_n_s_init_mean,&__pyx_n_s_init_std_dev,&__pyx_n_s_lr_all,&__pyx_n_s_reg_all,&__pyx_n_s_lr_bu,&__pyx_n_s_lr_bi,&__pyx_n_s_lr_pu,&__pyx_n_s_lr_qi,&__pyx_n_s_lr_yj,&__pyx_n_s_reg_bu,&__pyx_n_s_reg_bi,&__pyx_n_s_reg_pu,&__pyx_n_s_reg_qi,&__pyx_n_s_reg_yj,&__pyx_n_s_random_state,&__pyx_n_s_verbose,0};
    PyObject* values[19] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    values[1] = ((PyObject *)((PyObject *)__pyx_int_20));
    values[2] = ((PyObject *)((PyObject *)__pyx_int_20));
    values[3] = ((PyObject *)((PyObject *)__pyx_int_0));
    values[4] = ((PyObject *)((PyObject*)__pyx_float__1));
    values[5] = ((PyObject *)((PyObject*)__pyx_float__007));
    values[6] = ((PyObject *)((PyObject*)__pyx_float__02));
/* … */
  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_n_factors, PyObject *__pyx_v_n_epochs, PyObject *__pyx_v_init_mean, PyObject *__pyx_v_init_std_dev, PyObject *__pyx_v_lr_all, PyObject *__pyx_v_reg_all, PyObject *__pyx_v_lr_bu, PyObject *__pyx_v_lr_bi, PyObject *__pyx_v_lr_pu, PyObject *__pyx_v_lr_qi, PyObject *__pyx_v_lr_yj, PyObject *__pyx_v_reg_bu, PyObject *__pyx_v_reg_bi, PyObject *__pyx_v_reg_pu, PyObject *__pyx_v_reg_qi, PyObject *__pyx_v_reg_yj, PyObject *__pyx_v_random_state, PyObject *__pyx_v_verbose) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__init__", 0);
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVDpp.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__13 = PyTuple_Pack(19, __pyx_n_s_self, __pyx_n_s_n_factors, __pyx_n_s_n_epochs, __pyx_n_s_init_mean, __pyx_n_s_init_std_dev, __pyx_n_s_lr_all, __pyx_n_s_reg_all, __pyx_n_s_lr_bu, __pyx_n_s_lr_bi, __pyx_n_s_lr_pu, __pyx_n_s_lr_qi, __pyx_n_s_lr_yj, __pyx_n_s_reg_bu, __pyx_n_s_reg_bi, __pyx_n_s_reg_pu, __pyx_n_s_reg_qi, __pyx_n_s_reg_yj, __pyx_n_s_random_state, __pyx_n_s_verbose); if (unlikely(!__pyx_tuple__13)) __PYX_ERR(0, 374, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__13);
  __Pyx_GIVEREF(__pyx_tuple__13);
  __pyx_codeobj__14 = (PyObject*)__Pyx_PyCode_New(19, 0, 19, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__13, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_init, 374, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__14)) __PYX_ERR(0, 374, __pyx_L1_error)
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_1__init__, 0, __pyx_n_s_SVDpp___init, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__14)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 374, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_4, __pyx_tuple__15);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_init, __pyx_t_4) < 0) __PYX_ERR(0, 374, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_tuple__15 = PyTuple_Pack(18, ((PyObject *)__pyx_int_20), ((PyObject *)__pyx_int_20), ((PyObject *)__pyx_int_0), ((PyObject*)__pyx_float__1), ((PyObject*)__pyx_float__007), ((PyObject*)__pyx_float__02), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_None), ((PyObject *)Py_False)); if (unlikely(!__pyx_tuple__15)) __PYX_ERR(0, 374, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__15);
  __Pyx_GIVEREF(__pyx_tuple__15);
+375:                  lr_all=.007, reg_all=.02, lr_bu=None, lr_bi=None, lr_pu=None,
    values[7] = ((PyObject *)((PyObject *)Py_None));
    values[8] = ((PyObject *)((PyObject *)Py_None));
    values[9] = ((PyObject *)((PyObject *)Py_None));
+376:                  lr_qi=None, lr_yj=None, reg_bu=None, reg_bi=None, reg_pu=None,
    values[10] = ((PyObject *)((PyObject *)Py_None));
    values[11] = ((PyObject *)((PyObject *)Py_None));
    values[12] = ((PyObject *)((PyObject *)Py_None));
    values[13] = ((PyObject *)((PyObject *)Py_None));
    values[14] = ((PyObject *)((PyObject *)Py_None));
+377:                  reg_qi=None, reg_yj=None, random_state=None, verbose=False):
    values[15] = ((PyObject *)((PyObject *)Py_None));
    values[16] = ((PyObject *)((PyObject *)Py_None));
    values[17] = ((PyObject *)((PyObject *)Py_None));
    values[18] = ((PyObject *)((PyObject *)Py_False));
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case 19: values[18] = PyTuple_GET_ITEM(__pyx_args, 18);
        CYTHON_FALLTHROUGH;
        case 18: values[17] = PyTuple_GET_ITEM(__pyx_args, 17);
        CYTHON_FALLTHROUGH;
        case 17: values[16] = PyTuple_GET_ITEM(__pyx_args, 16);
        CYTHON_FALLTHROUGH;
        case 16: values[15] = PyTuple_GET_ITEM(__pyx_args, 15);
        CYTHON_FALLTHROUGH;
        case 15: values[14] = PyTuple_GET_ITEM(__pyx_args, 14);
        CYTHON_FALLTHROUGH;
        case 14: values[13] = PyTuple_GET_ITEM(__pyx_args, 13);
        CYTHON_FALLTHROUGH;
        case 13: values[12] = PyTuple_GET_ITEM(__pyx_args, 12);
        CYTHON_FALLTHROUGH;
        case 12: values[11] = PyTuple_GET_ITEM(__pyx_args, 11);
        CYTHON_FALLTHROUGH;
        case 11: values[10] = PyTuple_GET_ITEM(__pyx_args, 10);
        CYTHON_FALLTHROUGH;
        case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9);
        CYTHON_FALLTHROUGH;
        case  9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8);
        CYTHON_FALLTHROUGH;
        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_n_factors);
          if (value) { values[1] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_n_epochs);
          if (value) { values[2] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_init_mean);
          if (value) { values[3] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  4:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_init_std_dev);
          if (value) { values[4] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  5:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_all);
          if (value) { values[5] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  6:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_all);
          if (value) { values[6] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  7:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_bu);
          if (value) { values[7] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  8:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_bi);
          if (value) { values[8] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  9:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_pu);
          if (value) { values[9] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 10:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_qi);
          if (value) { values[10] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 11:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_yj);
          if (value) { values[11] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 12:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_bu);
          if (value) { values[12] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 13:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_bi);
          if (value) { values[13] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 14:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_pu);
          if (value) { values[14] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 15:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_qi);
          if (value) { values[15] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 16:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_yj);
          if (value) { values[16] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 17:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_random_state);
          if (value) { values[17] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 18:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_verbose);
          if (value) { values[18] = value; kw_args--; }
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 374, __pyx_L3_error)
      }
    } else {
      switch (PyTuple_GET_SIZE(__pyx_args)) {
        case 19: values[18] = PyTuple_GET_ITEM(__pyx_args, 18);
        CYTHON_FALLTHROUGH;
        case 18: values[17] = PyTuple_GET_ITEM(__pyx_args, 17);
        CYTHON_FALLTHROUGH;
        case 17: values[16] = PyTuple_GET_ITEM(__pyx_args, 16);
        CYTHON_FALLTHROUGH;
        case 16: values[15] = PyTuple_GET_ITEM(__pyx_args, 15);
        CYTHON_FALLTHROUGH;
        case 15: values[14] = PyTuple_GET_ITEM(__pyx_args, 14);
        CYTHON_FALLTHROUGH;
        case 14: values[13] = PyTuple_GET_ITEM(__pyx_args, 13);
        CYTHON_FALLTHROUGH;
        case 13: values[12] = PyTuple_GET_ITEM(__pyx_args, 12);
        CYTHON_FALLTHROUGH;
        case 12: values[11] = PyTuple_GET_ITEM(__pyx_args, 11);
        CYTHON_FALLTHROUGH;
        case 11: values[10] = PyTuple_GET_ITEM(__pyx_args, 10);
        CYTHON_FALLTHROUGH;
        case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9);
        CYTHON_FALLTHROUGH;
        case  9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8);
        CYTHON_FALLTHROUGH;
        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        break;
        default: goto __pyx_L5_argtuple_error;
      }
    }
    __pyx_v_self = values[0];
    __pyx_v_n_factors = values[1];
    __pyx_v_n_epochs = values[2];
    __pyx_v_init_mean = values[3];
    __pyx_v_init_std_dev = values[4];
    __pyx_v_lr_all = values[5];
    __pyx_v_reg_all = values[6];
    __pyx_v_lr_bu = values[7];
    __pyx_v_lr_bi = values[8];
    __pyx_v_lr_pu = values[9];
    __pyx_v_lr_qi = values[10];
    __pyx_v_lr_yj = values[11];
    __pyx_v_reg_bu = values[12];
    __pyx_v_reg_bi = values[13];
    __pyx_v_reg_pu = values[14];
    __pyx_v_reg_qi = values[15];
    __pyx_v_reg_yj = values[16];
    __pyx_v_random_state = values[17];
    __pyx_v_verbose = values[18];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("__init__", 0, 1, 19, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 374, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVDpp.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp___init__(__pyx_self, __pyx_v_self, __pyx_v_n_factors, __pyx_v_n_epochs, __pyx_v_init_mean, __pyx_v_init_std_dev, __pyx_v_lr_all, __pyx_v_reg_all, __pyx_v_lr_bu, __pyx_v_lr_bi, __pyx_v_lr_pu, __pyx_v_lr_qi, __pyx_v_lr_yj, __pyx_v_reg_bu, __pyx_v_reg_bi, __pyx_v_reg_pu, __pyx_v_reg_qi, __pyx_v_reg_yj, __pyx_v_random_state, __pyx_v_verbose);
 378: 
+379:         self.n_factors = n_factors
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_n_factors, __pyx_v_n_factors) < 0) __PYX_ERR(0, 379, __pyx_L1_error)
+380:         self.n_epochs = n_epochs
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_n_epochs, __pyx_v_n_epochs) < 0) __PYX_ERR(0, 380, __pyx_L1_error)
+381:         self.init_mean = init_mean
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_init_mean, __pyx_v_init_mean) < 0) __PYX_ERR(0, 381, __pyx_L1_error)
+382:         self.init_std_dev = init_std_dev
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_init_std_dev, __pyx_v_init_std_dev) < 0) __PYX_ERR(0, 382, __pyx_L1_error)
+383:         self.lr_bu = lr_bu if lr_bu is not None else lr_all
  __pyx_t_2 = (__pyx_v_lr_bu != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_lr_bu);
    __pyx_t_1 = __pyx_v_lr_bu;
  } else {
    __Pyx_INCREF(__pyx_v_lr_all);
    __pyx_t_1 = __pyx_v_lr_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_bu, __pyx_t_1) < 0) __PYX_ERR(0, 383, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+384:         self.lr_bi = lr_bi if lr_bi is not None else lr_all
  __pyx_t_2 = (__pyx_v_lr_bi != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_lr_bi);
    __pyx_t_1 = __pyx_v_lr_bi;
  } else {
    __Pyx_INCREF(__pyx_v_lr_all);
    __pyx_t_1 = __pyx_v_lr_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_bi, __pyx_t_1) < 0) __PYX_ERR(0, 384, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+385:         self.lr_pu = lr_pu if lr_pu is not None else lr_all
  __pyx_t_2 = (__pyx_v_lr_pu != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_lr_pu);
    __pyx_t_1 = __pyx_v_lr_pu;
  } else {
    __Pyx_INCREF(__pyx_v_lr_all);
    __pyx_t_1 = __pyx_v_lr_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_pu, __pyx_t_1) < 0) __PYX_ERR(0, 385, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+386:         self.lr_qi = lr_qi if lr_qi is not None else lr_all
  __pyx_t_2 = (__pyx_v_lr_qi != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_lr_qi);
    __pyx_t_1 = __pyx_v_lr_qi;
  } else {
    __Pyx_INCREF(__pyx_v_lr_all);
    __pyx_t_1 = __pyx_v_lr_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_qi, __pyx_t_1) < 0) __PYX_ERR(0, 386, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+387:         self.lr_yj = lr_yj if lr_yj is not None else lr_all
  __pyx_t_2 = (__pyx_v_lr_yj != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_lr_yj);
    __pyx_t_1 = __pyx_v_lr_yj;
  } else {
    __Pyx_INCREF(__pyx_v_lr_all);
    __pyx_t_1 = __pyx_v_lr_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_yj, __pyx_t_1) < 0) __PYX_ERR(0, 387, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+388:         self.reg_bu = reg_bu if reg_bu is not None else reg_all
  __pyx_t_2 = (__pyx_v_reg_bu != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_reg_bu);
    __pyx_t_1 = __pyx_v_reg_bu;
  } else {
    __Pyx_INCREF(__pyx_v_reg_all);
    __pyx_t_1 = __pyx_v_reg_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_bu, __pyx_t_1) < 0) __PYX_ERR(0, 388, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+389:         self.reg_bi = reg_bi if reg_bi is not None else reg_all
  __pyx_t_2 = (__pyx_v_reg_bi != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_reg_bi);
    __pyx_t_1 = __pyx_v_reg_bi;
  } else {
    __Pyx_INCREF(__pyx_v_reg_all);
    __pyx_t_1 = __pyx_v_reg_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_bi, __pyx_t_1) < 0) __PYX_ERR(0, 389, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+390:         self.reg_pu = reg_pu if reg_pu is not None else reg_all
  __pyx_t_2 = (__pyx_v_reg_pu != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_reg_pu);
    __pyx_t_1 = __pyx_v_reg_pu;
  } else {
    __Pyx_INCREF(__pyx_v_reg_all);
    __pyx_t_1 = __pyx_v_reg_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_pu, __pyx_t_1) < 0) __PYX_ERR(0, 390, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+391:         self.reg_qi = reg_qi if reg_qi is not None else reg_all
  __pyx_t_2 = (__pyx_v_reg_qi != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_reg_qi);
    __pyx_t_1 = __pyx_v_reg_qi;
  } else {
    __Pyx_INCREF(__pyx_v_reg_all);
    __pyx_t_1 = __pyx_v_reg_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_qi, __pyx_t_1) < 0) __PYX_ERR(0, 391, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+392:         self.reg_yj = reg_yj if reg_yj is not None else reg_all
  __pyx_t_2 = (__pyx_v_reg_yj != Py_None);
  if ((__pyx_t_2 != 0)) {
    __Pyx_INCREF(__pyx_v_reg_yj);
    __pyx_t_1 = __pyx_v_reg_yj;
  } else {
    __Pyx_INCREF(__pyx_v_reg_all);
    __pyx_t_1 = __pyx_v_reg_all;
  }
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_yj, __pyx_t_1) < 0) __PYX_ERR(0, 392, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+393:         self.random_state = random_state
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_random_state, __pyx_v_random_state) < 0) __PYX_ERR(0, 393, __pyx_L1_error)
+394:         self.verbose = verbose
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_verbose, __pyx_v_verbose) < 0) __PYX_ERR(0, 394, __pyx_L1_error)
 395: 
+396:         AlgoBase.__init__(self)
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_AlgoBase); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 396, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_init); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 396, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_3, __pyx_v_self) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_self);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 396, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 397: 
+398:     def fit(self, trainset):
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_3fit(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_3fit = {"fit", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_3fit, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_3fit(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_trainset = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("fit (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_trainset,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_trainset)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("fit", 1, 2, 2, 1); __PYX_ERR(0, 398, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "fit") < 0)) __PYX_ERR(0, 398, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_self = values[0];
    __pyx_v_trainset = values[1];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("fit", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 398, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVDpp.fit", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_2fit(__pyx_self, __pyx_v_self, __pyx_v_trainset);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_2fit(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_trainset) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("fit", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVDpp.fit", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__16 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_trainset); if (unlikely(!__pyx_tuple__16)) __PYX_ERR(0, 398, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__16);
  __Pyx_GIVEREF(__pyx_tuple__16);
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_3fit, 0, __pyx_n_s_SVDpp_fit, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__17)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 398, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_fit, __pyx_t_4) < 0) __PYX_ERR(0, 398, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_codeobj__17 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__16, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_fit, 398, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__17)) __PYX_ERR(0, 398, __pyx_L1_error)
 399: 
+400:         AlgoBase.fit(self, trainset)
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_AlgoBase); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 400, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_fit); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 400, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = NULL;
  __pyx_t_4 = 0;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_2)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
      __pyx_t_4 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_3)) {
    PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_v_self, __pyx_v_trainset};
    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_4, 2+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 400, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_GOTREF(__pyx_t_1);
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
    PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_v_self, __pyx_v_trainset};
    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_4, 2+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 400, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_GOTREF(__pyx_t_1);
  } else
  #endif
  {
    __pyx_t_5 = PyTuple_New(2+__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 400, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    if (__pyx_t_2) {
      __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2); __pyx_t_2 = NULL;
    }
    __Pyx_INCREF(__pyx_v_self);
    __Pyx_GIVEREF(__pyx_v_self);
    PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_4, __pyx_v_self);
    __Pyx_INCREF(__pyx_v_trainset);
    __Pyx_GIVEREF(__pyx_v_trainset);
    PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_4, __pyx_v_trainset);
    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 400, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+401:         self.sgd(trainset)
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_sgd); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 401, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_v_trainset) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_trainset);
  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 401, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 402: 
+403:         return self
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_self);
  __pyx_r = __pyx_v_self;
  goto __pyx_L0;
 404: 
+405:     def sgd(self, trainset):
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_5sgd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_5sgd = {"sgd", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_5sgd, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_5sgd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_trainset = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("sgd (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_trainset,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_trainset)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("sgd", 1, 2, 2, 1); __PYX_ERR(0, 405, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "sgd") < 0)) __PYX_ERR(0, 405, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_self = values[0];
    __pyx_v_trainset = values[1];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("sgd", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 405, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVDpp.sgd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_4sgd(__pyx_self, __pyx_v_self, __pyx_v_trainset);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_4sgd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_trainset) {
  PyArrayObject *__pyx_v_bu = 0;
  PyArrayObject *__pyx_v_bi = 0;
  PyArrayObject *__pyx_v_pu = 0;
  PyArrayObject *__pyx_v_qi = 0;
  PyArrayObject *__pyx_v_yj = 0;
  int __pyx_v_u;
  int __pyx_v_i;
  int __pyx_v_j;
  int __pyx_v_f;
  double __pyx_v_r;
  double __pyx_v_err;
  double __pyx_v_dot;
  double __pyx_v_puf;
  double __pyx_v_qif;
  double __pyx_v_sqrt_Iu;
  CYTHON_UNUSED double __pyx_v__;
  double __pyx_v_global_mean;
  PyArrayObject *__pyx_v_u_impl_fdb = 0;
  double __pyx_v_lr_bu;
  double __pyx_v_lr_bi;
  double __pyx_v_lr_pu;
  double __pyx_v_lr_qi;
  double __pyx_v_lr_yj;
  double __pyx_v_reg_bu;
  double __pyx_v_reg_bi;
  double __pyx_v_reg_pu;
  double __pyx_v_reg_qi;
  double __pyx_v_reg_yj;
  PyObject *__pyx_v_rng = NULL;
  std::map<int,std::vector<int> >  __pyx_v_Iu_items;
  std::map<int,double>  __pyx_v_Iu_len_sqrts;
  std::map<int,std::vector<int> > ::iterator __pyx_v_it;
  int __pyx_v_facts;
  double __pyx_v_err_qif_sqrt;
  PyObject *__pyx_v_current_epoch = NULL;
  std::vector<int>  __pyx_v_Iu;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_bi;
  __Pyx_Buffer __pyx_pybuffer_bi;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_bu;
  __Pyx_Buffer __pyx_pybuffer_bu;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_pu;
  __Pyx_Buffer __pyx_pybuffer_pu;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_qi;
  __Pyx_Buffer __pyx_pybuffer_qi;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_u_impl_fdb;
  __Pyx_Buffer __pyx_pybuffer_u_impl_fdb;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_yj;
  __Pyx_Buffer __pyx_pybuffer_yj;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("sgd", 0);
  __pyx_pybuffer_bu.pybuffer.buf = NULL;
  __pyx_pybuffer_bu.refcount = 0;
  __pyx_pybuffernd_bu.data = NULL;
  __pyx_pybuffernd_bu.rcbuffer = &__pyx_pybuffer_bu;
  __pyx_pybuffer_bi.pybuffer.buf = NULL;
  __pyx_pybuffer_bi.refcount = 0;
  __pyx_pybuffernd_bi.data = NULL;
  __pyx_pybuffernd_bi.rcbuffer = &__pyx_pybuffer_bi;
  __pyx_pybuffer_pu.pybuffer.buf = NULL;
  __pyx_pybuffer_pu.refcount = 0;
  __pyx_pybuffernd_pu.data = NULL;
  __pyx_pybuffernd_pu.rcbuffer = &__pyx_pybuffer_pu;
  __pyx_pybuffer_qi.pybuffer.buf = NULL;
  __pyx_pybuffer_qi.refcount = 0;
  __pyx_pybuffernd_qi.data = NULL;
  __pyx_pybuffernd_qi.rcbuffer = &__pyx_pybuffer_qi;
  __pyx_pybuffer_yj.pybuffer.buf = NULL;
  __pyx_pybuffer_yj.refcount = 0;
  __pyx_pybuffernd_yj.data = NULL;
  __pyx_pybuffernd_yj.rcbuffer = &__pyx_pybuffer_yj;
  __pyx_pybuffer_u_impl_fdb.pybuffer.buf = NULL;
  __pyx_pybuffer_u_impl_fdb.refcount = 0;
  __pyx_pybuffernd_u_impl_fdb.data = NULL;
  __pyx_pybuffernd_u_impl_fdb.rcbuffer = &__pyx_pybuffer_u_impl_fdb;
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_14);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bi.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bu.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_pu.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_qi.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_yj.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVDpp.sgd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bi.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bu.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_pu.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_qi.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_yj.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_bu);
  __Pyx_XDECREF((PyObject *)__pyx_v_bi);
  __Pyx_XDECREF((PyObject *)__pyx_v_pu);
  __Pyx_XDECREF((PyObject *)__pyx_v_qi);
  __Pyx_XDECREF((PyObject *)__pyx_v_yj);
  __Pyx_XDECREF((PyObject *)__pyx_v_u_impl_fdb);
  __Pyx_XDECREF(__pyx_v_rng);
  __Pyx_XDECREF(__pyx_v_current_epoch);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__19 = PyTuple_Pack(38, __pyx_n_s_self, __pyx_n_s_trainset, __pyx_n_s_bu, __pyx_n_s_bi, __pyx_n_s_pu, __pyx_n_s_qi, __pyx_n_s_yj, __pyx_n_s_u, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_f, __pyx_n_s_r, __pyx_n_s_err, __pyx_n_s_dot, __pyx_n_s_puf, __pyx_n_s_qif, __pyx_n_s_sqrt_Iu, __pyx_n_s__18, __pyx_n_s_global_mean, __pyx_n_s_u_impl_fdb, __pyx_n_s_lr_bu, __pyx_n_s_lr_bi, __pyx_n_s_lr_pu, __pyx_n_s_lr_qi, __pyx_n_s_lr_yj, __pyx_n_s_reg_bu, __pyx_n_s_reg_bi, __pyx_n_s_reg_pu, __pyx_n_s_reg_qi, __pyx_n_s_reg_yj, __pyx_n_s_rng, __pyx_n_s_Iu_items, __pyx_n_s_Iu_len_sqrts, __pyx_n_s_it, __pyx_n_s_facts, __pyx_n_s_err_qif_sqrt, __pyx_n_s_current_epoch, __pyx_n_s_Iu); if (unlikely(!__pyx_tuple__19)) __PYX_ERR(0, 405, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__19);
  __Pyx_GIVEREF(__pyx_tuple__19);
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_5sgd, 0, __pyx_n_s_SVDpp_sgd, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__20)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 405, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_sgd, __pyx_t_4) < 0) __PYX_ERR(0, 405, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_codeobj__20 = (PyObject*)__Pyx_PyCode_New(2, 0, 38, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__19, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_sgd, 405, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__20)) __PYX_ERR(0, 405, __pyx_L1_error)
 406: 
 407:         # user biases
 408:         cdef np.ndarray[np.double_t] bu
 409:         # item biases
 410:         cdef np.ndarray[np.double_t] bi
 411:         # user factors
 412:         cdef np.ndarray[np.double_t, ndim=2] pu
 413:         # item factors
 414:         cdef np.ndarray[np.double_t, ndim=2] qi
 415:         # item implicit factors
 416:         cdef np.ndarray[np.double_t, ndim=2] yj
 417: 
 418:         cdef int u, i, j, f
 419:         cdef double r, err, dot, puf, qif, sqrt_Iu, _
+420:         cdef double global_mean = self.trainset.global_mean
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 420, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_global_mean); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 420, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 420, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_global_mean = __pyx_t_3;
 421:         cdef np.ndarray[np.double_t] u_impl_fdb
 422: 
+423:         cdef double lr_bu = self.lr_bu
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_bu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 423, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 423, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_lr_bu = __pyx_t_3;
+424:         cdef double lr_bi = self.lr_bi
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_bi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 424, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 424, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_lr_bi = __pyx_t_3;
+425:         cdef double lr_pu = self.lr_pu
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_pu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 425, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 425, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_lr_pu = __pyx_t_3;
+426:         cdef double lr_qi = self.lr_qi
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_qi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 426, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 426, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_lr_qi = __pyx_t_3;
+427:         cdef double lr_yj = self.lr_yj
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_yj); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 427, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 427, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_lr_yj = __pyx_t_3;
 428: 
+429:         cdef double reg_bu = self.reg_bu
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_bu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 429, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 429, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_reg_bu = __pyx_t_3;
+430:         cdef double reg_bi = self.reg_bi
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_bi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 430, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 430, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_reg_bi = __pyx_t_3;
+431:         cdef double reg_pu = self.reg_pu
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_pu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 431, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 431, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_reg_pu = __pyx_t_3;
+432:         cdef double reg_qi = self.reg_qi
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_qi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 432, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 432, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_reg_qi = __pyx_t_3;
+433:         cdef double reg_yj = self.reg_yj
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_yj); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 433, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 433, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_reg_yj = __pyx_t_3;
 434: 
+435:         bu = np.zeros(trainset.n_users, np.double)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 435, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 435, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_users); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 435, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 435, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_double); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 435, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = NULL;
  __pyx_t_7 = 0;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
      __pyx_t_7 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_4)) {
    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_1, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 435, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_1, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 435, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  {
    __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 435, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    if (__pyx_t_5) {
      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_6);
    PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_6);
    __pyx_t_1 = 0;
    __pyx_t_6 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 435, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 435, __pyx_L1_error)
  __pyx_t_9 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bu.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bu.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bu.rcbuffer->pybuffer, (PyObject*)__pyx_v_bu, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_12);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
      }
      __pyx_t_10 = __pyx_t_11 = __pyx_t_12 = 0;
    }
    __pyx_pybuffernd_bu.diminfo[0].strides = __pyx_pybuffernd_bu.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_bu.diminfo[0].shape = __pyx_pybuffernd_bu.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 435, __pyx_L1_error)
  }
  __pyx_t_9 = 0;
  __pyx_v_bu = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+436:         bi = np.zeros(trainset.n_items, np.double)
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_np); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 436, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_zeros); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 436, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_items); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 436, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_np); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 436, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_double); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 436, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_6 = NULL;
  __pyx_t_7 = 0;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_6)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
      __pyx_t_7 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_4, __pyx_t_1};
    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 436, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_4, __pyx_t_1};
    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 436, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else
  #endif
  {
    __pyx_t_5 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 436, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    if (__pyx_t_6) {
      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_6); __pyx_t_6 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_4);
    PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_7, __pyx_t_4);
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_7, __pyx_t_1);
    __pyx_t_4 = 0;
    __pyx_t_1 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 436, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  }
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 436, __pyx_L1_error)
  __pyx_t_13 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bi.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bi.rcbuffer->pybuffer, (PyObject*)__pyx_t_13, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bi.rcbuffer->pybuffer, (PyObject*)__pyx_v_bi, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_10);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_12, __pyx_t_11, __pyx_t_10);
      }
      __pyx_t_12 = __pyx_t_11 = __pyx_t_10 = 0;
    }
    __pyx_pybuffernd_bi.diminfo[0].strides = __pyx_pybuffernd_bi.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_bi.diminfo[0].shape = __pyx_pybuffernd_bi.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 436, __pyx_L1_error)
  }
  __pyx_t_13 = 0;
  __pyx_v_bi = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
 437: 
+438:         rng = get_rng(self.random_state)
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_get_rng); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 438, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_random_state); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 438, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_1 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_1)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
    }
  }
  __pyx_t_2 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_1, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_t_5);
  __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 438, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_v_rng = __pyx_t_2;
  __pyx_t_2 = 0;
 439: 
+440:         pu = rng.normal(self.init_mean, self.init_std_dev,
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_rng, __pyx_n_s_normal); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 440, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_mean); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 440, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_std_dev); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 440, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
/* … */
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 440, __pyx_L1_error)
  __pyx_t_15 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_pu.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_pu.rcbuffer->pybuffer, (PyObject*)__pyx_t_15, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_pu.rcbuffer->pybuffer, (PyObject*)__pyx_v_pu, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_12);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
      }
      __pyx_t_10 = __pyx_t_11 = __pyx_t_12 = 0;
    }
    __pyx_pybuffernd_pu.diminfo[0].strides = __pyx_pybuffernd_pu.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_pu.diminfo[0].shape = __pyx_pybuffernd_pu.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_pu.diminfo[1].strides = __pyx_pybuffernd_pu.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_pu.diminfo[1].shape = __pyx_pybuffernd_pu.rcbuffer->pybuffer.shape[1];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 440, __pyx_L1_error)
  }
  __pyx_t_15 = 0;
  __pyx_v_pu = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+441:                         (trainset.n_users, self.n_factors))
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_users); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 441, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 441, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_14 = PyTuple_New(2); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 441, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_GIVEREF(__pyx_t_4);
  PyTuple_SET_ITEM(__pyx_t_14, 0, __pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_6);
  PyTuple_SET_ITEM(__pyx_t_14, 1, __pyx_t_6);
  __pyx_t_4 = 0;
  __pyx_t_6 = 0;
  __pyx_t_6 = NULL;
  __pyx_t_7 = 0;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_6)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
      __pyx_t_7 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[4] = {__pyx_t_6, __pyx_t_5, __pyx_t_1, __pyx_t_14};
    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 440, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[4] = {__pyx_t_6, __pyx_t_5, __pyx_t_1, __pyx_t_14};
    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 440, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  } else
  #endif
  {
    __pyx_t_4 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 440, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    if (__pyx_t_6) {
      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6); __pyx_t_6 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_5);
    PyTuple_SET_ITEM(__pyx_t_4, 0+__pyx_t_7, __pyx_t_5);
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_4, 1+__pyx_t_7, __pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_14);
    PyTuple_SET_ITEM(__pyx_t_4, 2+__pyx_t_7, __pyx_t_14);
    __pyx_t_5 = 0;
    __pyx_t_1 = 0;
    __pyx_t_14 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 440, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  }
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+442:         qi = rng.normal(self.init_mean, self.init_std_dev,
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_rng, __pyx_n_s_normal); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 442, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_mean); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 442, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_std_dev); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 442, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
/* … */
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 442, __pyx_L1_error)
  __pyx_t_16 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_qi.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_qi.rcbuffer->pybuffer, (PyObject*)__pyx_t_16, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_qi.rcbuffer->pybuffer, (PyObject*)__pyx_v_qi, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_10);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_12, __pyx_t_11, __pyx_t_10);
      }
      __pyx_t_12 = __pyx_t_11 = __pyx_t_10 = 0;
    }
    __pyx_pybuffernd_qi.diminfo[0].strides = __pyx_pybuffernd_qi.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_qi.diminfo[0].shape = __pyx_pybuffernd_qi.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_qi.diminfo[1].strides = __pyx_pybuffernd_qi.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_qi.diminfo[1].shape = __pyx_pybuffernd_qi.rcbuffer->pybuffer.shape[1];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 442, __pyx_L1_error)
  }
  __pyx_t_16 = 0;
  __pyx_v_qi = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+443:                         (trainset.n_items, self.n_factors))
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 443, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 443, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 443, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_5);
  PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_5);
  __pyx_t_1 = 0;
  __pyx_t_5 = 0;
  __pyx_t_5 = NULL;
  __pyx_t_7 = 0;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
      __pyx_t_7 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_t_4, __pyx_t_14, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 442, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[4] = {__pyx_t_5, __pyx_t_4, __pyx_t_14, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 442, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  {
    __pyx_t_1 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 442, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (__pyx_t_5) {
      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5); __pyx_t_5 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_4);
    PyTuple_SET_ITEM(__pyx_t_1, 0+__pyx_t_7, __pyx_t_4);
    __Pyx_GIVEREF(__pyx_t_14);
    PyTuple_SET_ITEM(__pyx_t_1, 1+__pyx_t_7, __pyx_t_14);
    __Pyx_GIVEREF(__pyx_t_6);
    PyTuple_SET_ITEM(__pyx_t_1, 2+__pyx_t_7, __pyx_t_6);
    __pyx_t_4 = 0;
    __pyx_t_14 = 0;
    __pyx_t_6 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 442, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  }
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+444:         yj = rng.normal(self.init_mean, self.init_std_dev,
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_rng, __pyx_n_s_normal); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 444, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_mean); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 444, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_std_dev); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 444, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
/* … */
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 444, __pyx_L1_error)
  __pyx_t_17 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_yj.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_yj.rcbuffer->pybuffer, (PyObject*)__pyx_t_17, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_yj.rcbuffer->pybuffer, (PyObject*)__pyx_v_yj, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_12);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
      }
      __pyx_t_10 = __pyx_t_11 = __pyx_t_12 = 0;
    }
    __pyx_pybuffernd_yj.diminfo[0].strides = __pyx_pybuffernd_yj.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_yj.diminfo[0].shape = __pyx_pybuffernd_yj.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_yj.diminfo[1].strides = __pyx_pybuffernd_yj.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_yj.diminfo[1].shape = __pyx_pybuffernd_yj.rcbuffer->pybuffer.shape[1];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 444, __pyx_L1_error)
  }
  __pyx_t_17 = 0;
  __pyx_v_yj = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+445:                         (trainset.n_items, self.n_factors))
  __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_items); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 445, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 445, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 445, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_GIVEREF(__pyx_t_14);
  PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_14);
  __Pyx_GIVEREF(__pyx_t_4);
  PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4);
  __pyx_t_14 = 0;
  __pyx_t_4 = 0;
  __pyx_t_4 = NULL;
  __pyx_t_7 = 0;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_4)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_4);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
      __pyx_t_7 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[4] = {__pyx_t_4, __pyx_t_1, __pyx_t_6, __pyx_t_5};
    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 444, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) {
    PyObject *__pyx_temp[4] = {__pyx_t_4, __pyx_t_1, __pyx_t_6, __pyx_t_5};
    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 444, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  } else
  #endif
  {
    __pyx_t_14 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 444, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_14);
    if (__pyx_t_4) {
      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_14, 0, __pyx_t_4); __pyx_t_4 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_14, 0+__pyx_t_7, __pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_6);
    PyTuple_SET_ITEM(__pyx_t_14, 1+__pyx_t_7, __pyx_t_6);
    __Pyx_GIVEREF(__pyx_t_5);
    PyTuple_SET_ITEM(__pyx_t_14, 2+__pyx_t_7, __pyx_t_5);
    __pyx_t_1 = 0;
    __pyx_t_6 = 0;
    __pyx_t_5 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_14, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 444, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  }
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+446:         u_impl_fdb = np.zeros(self.n_factors, np.double)
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_np); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 446, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_zeros); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 446, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 446, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 446, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_double); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 446, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = NULL;
  __pyx_t_7 = 0;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_14))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_14);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_14);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_14, function);
      __pyx_t_7 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_14)) {
    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_8, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_14, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 446, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_14)) {
    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_8, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_14, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 446, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  {
    __pyx_t_1 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 446, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (__pyx_t_5) {
      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5); __pyx_t_5 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_8);
    PyTuple_SET_ITEM(__pyx_t_1, 0+__pyx_t_7, __pyx_t_8);
    __Pyx_GIVEREF(__pyx_t_6);
    PyTuple_SET_ITEM(__pyx_t_1, 1+__pyx_t_7, __pyx_t_6);
    __pyx_t_8 = 0;
    __pyx_t_6 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_14, __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 446, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  }
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 446, __pyx_L1_error)
  __pyx_t_18 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer, (PyObject*)__pyx_t_18, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer, (PyObject*)__pyx_v_u_impl_fdb, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_10);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_12, __pyx_t_11, __pyx_t_10);
      }
      __pyx_t_12 = __pyx_t_11 = __pyx_t_10 = 0;
    }
    __pyx_pybuffernd_u_impl_fdb.diminfo[0].strides = __pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_u_impl_fdb.diminfo[0].shape = __pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 446, __pyx_L1_error)
  }
  __pyx_t_18 = 0;
  __pyx_v_u_impl_fdb = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
 447: 
 448:         cdef mapcpp[int, vectorcpp[int]] Iu_items
 449:         cdef mapcpp[int, double] Iu_len_sqrts
 450: 
+451:         for i in range(trainset.n_users):
  __Pyx_GetModuleGlobalName(__pyx_t_14, __pyx_n_s_range); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 451, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_users); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 451, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_6 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_14))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_14);
    if (likely(__pyx_t_6)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_14);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_14, function);
    }
  }
  __pyx_t_2 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_14, __pyx_t_6, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_14, __pyx_t_1);
  __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 451, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
    __pyx_t_14 = __pyx_t_2; __Pyx_INCREF(__pyx_t_14); __pyx_t_19 = 0;
    __pyx_t_20 = NULL;
  } else {
    __pyx_t_19 = -1; __pyx_t_14 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 451, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_14);
    __pyx_t_20 = Py_TYPE(__pyx_t_14)->tp_iternext; if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 451, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  for (;;) {
    if (likely(!__pyx_t_20)) {
      if (likely(PyList_CheckExact(__pyx_t_14))) {
        if (__pyx_t_19 >= PyList_GET_SIZE(__pyx_t_14)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyList_GET_ITEM(__pyx_t_14, __pyx_t_19); __Pyx_INCREF(__pyx_t_2); __pyx_t_19++; if (unlikely(0 < 0)) __PYX_ERR(0, 451, __pyx_L1_error)
        #else
        __pyx_t_2 = PySequence_ITEM(__pyx_t_14, __pyx_t_19); __pyx_t_19++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 451, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      } else {
        if (__pyx_t_19 >= PyTuple_GET_SIZE(__pyx_t_14)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_14, __pyx_t_19); __Pyx_INCREF(__pyx_t_2); __pyx_t_19++; if (unlikely(0 < 0)) __PYX_ERR(0, 451, __pyx_L1_error)
        #else
        __pyx_t_2 = PySequence_ITEM(__pyx_t_14, __pyx_t_19); __pyx_t_19++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 451, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      }
    } else {
      __pyx_t_2 = __pyx_t_20(__pyx_t_14);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 451, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_2);
    }
    __pyx_t_7 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 451, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_i = __pyx_t_7;
/* … */
  }
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
+452:             for j, _ in trainset.ur[i]:
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_ur); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 452, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_2, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 452, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
      __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_21 = 0;
      __pyx_t_22 = NULL;
    } else {
      __pyx_t_21 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 452, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_22 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 452, __pyx_L1_error)
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    for (;;) {
      if (likely(!__pyx_t_22)) {
        if (likely(PyList_CheckExact(__pyx_t_2))) {
          if (__pyx_t_21 >= PyList_GET_SIZE(__pyx_t_2)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_21); __Pyx_INCREF(__pyx_t_1); __pyx_t_21++; if (unlikely(0 < 0)) __PYX_ERR(0, 452, __pyx_L1_error)
          #else
          __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_21); __pyx_t_21++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 452, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          #endif
        } else {
          if (__pyx_t_21 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_21); __Pyx_INCREF(__pyx_t_1); __pyx_t_21++; if (unlikely(0 < 0)) __PYX_ERR(0, 452, __pyx_L1_error)
          #else
          __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_21); __pyx_t_21++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 452, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          #endif
        }
      } else {
        __pyx_t_1 = __pyx_t_22(__pyx_t_2);
        if (unlikely(!__pyx_t_1)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 452, __pyx_L1_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_1);
      }
      if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
        PyObject* sequence = __pyx_t_1;
        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
        if (unlikely(size != 2)) {
          if (size > 2) __Pyx_RaiseTooManyValuesError(2);
          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
          __PYX_ERR(0, 452, __pyx_L1_error)
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        if (likely(PyTuple_CheckExact(sequence))) {
          __pyx_t_6 = PyTuple_GET_ITEM(sequence, 0); 
          __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); 
        } else {
          __pyx_t_6 = PyList_GET_ITEM(sequence, 0); 
          __pyx_t_8 = PyList_GET_ITEM(sequence, 1); 
        }
        __Pyx_INCREF(__pyx_t_6);
        __Pyx_INCREF(__pyx_t_8);
        #else
        __pyx_t_6 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 452, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 452, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_8);
        #endif
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      } else {
        Py_ssize_t index = -1;
        __pyx_t_5 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 452, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_5);
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_t_23 = Py_TYPE(__pyx_t_5)->tp_iternext;
        index = 0; __pyx_t_6 = __pyx_t_23(__pyx_t_5); if (unlikely(!__pyx_t_6)) goto __pyx_L7_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_6);
        index = 1; __pyx_t_8 = __pyx_t_23(__pyx_t_5); if (unlikely(!__pyx_t_8)) goto __pyx_L7_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_8);
        if (__Pyx_IternextUnpackEndCheck(__pyx_t_23(__pyx_t_5), 2) < 0) __PYX_ERR(0, 452, __pyx_L1_error)
        __pyx_t_23 = NULL;
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        goto __pyx_L8_unpacking_done;
        __pyx_L7_unpacking_failed:;
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        __pyx_t_23 = NULL;
        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
        __PYX_ERR(0, 452, __pyx_L1_error)
        __pyx_L8_unpacking_done:;
      }
      __pyx_t_7 = __Pyx_PyInt_As_int(__pyx_t_6); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 452, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_8); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 452, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __pyx_v_j = __pyx_t_7;
      __pyx_v__ = __pyx_t_3;
/* … */
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+453:                 Iu_items[i].push_back(j)
      try {
        (__pyx_v_Iu_items[__pyx_v_i]).push_back(__pyx_v_j);
      } catch(...) {
        __Pyx_CppExn2PyErr();
        __PYX_ERR(0, 453, __pyx_L1_error)
      }
 454: 
+455:         cdef mapcpp[int, vectorcpp[int]].iterator it = Iu_items.begin()
  __pyx_v_it = __pyx_v_Iu_items.begin();
 456: 
+457:         while(it != Iu_items.end()):
  while (1) {
    __pyx_t_24 = ((__pyx_v_it != __pyx_v_Iu_items.end()) != 0);
    if (!__pyx_t_24) break;
+458:             Iu_len_sqrts[dereference(it).first] = 1.0 / np.sqrt(dereference(it).second.size())
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 458, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_sqrt); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 458, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyInt_FromSize_t((*__pyx_v_it).second.size()); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 458, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_8 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_1);
      if (likely(__pyx_t_8)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
        __Pyx_INCREF(__pyx_t_8);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_1, function);
      }
    }
    __pyx_t_14 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_8, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_2);
    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 458, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_14);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_1 = __Pyx_PyFloat_TrueDivideCObj(__pyx_float_1_0, __pyx_t_14, 1.0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 458, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 458, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    (__pyx_v_Iu_len_sqrts[(*__pyx_v_it).first]) = __pyx_t_3;
+459:             postincrement(it)
    (void)((__pyx_v_it++));
  }
 460: 
+461:         cdef int facts = self.n_factors
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 461, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_7 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 461, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_facts = __pyx_t_7;
 462: 
+463:         cdef double err_qif_sqrt = 0.0
  __pyx_v_err_qif_sqrt = 0.0;
 464: 
+465:         for current_epoch in range(self.n_epochs):
  __Pyx_GetModuleGlobalName(__pyx_t_14, __pyx_n_s_range); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 465, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_epochs); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 465, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_8 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_14))) {
    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_14);
    if (likely(__pyx_t_8)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_14);
      __Pyx_INCREF(__pyx_t_8);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_14, function);
    }
  }
  __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_14, __pyx_t_8, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_14, __pyx_t_2);
  __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 465, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
    __pyx_t_14 = __pyx_t_1; __Pyx_INCREF(__pyx_t_14); __pyx_t_19 = 0;
    __pyx_t_20 = NULL;
  } else {
    __pyx_t_19 = -1; __pyx_t_14 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 465, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_14);
    __pyx_t_20 = Py_TYPE(__pyx_t_14)->tp_iternext; if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 465, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    if (likely(!__pyx_t_20)) {
      if (likely(PyList_CheckExact(__pyx_t_14))) {
        if (__pyx_t_19 >= PyList_GET_SIZE(__pyx_t_14)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = PyList_GET_ITEM(__pyx_t_14, __pyx_t_19); __Pyx_INCREF(__pyx_t_1); __pyx_t_19++; if (unlikely(0 < 0)) __PYX_ERR(0, 465, __pyx_L1_error)
        #else
        __pyx_t_1 = PySequence_ITEM(__pyx_t_14, __pyx_t_19); __pyx_t_19++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 465, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
      } else {
        if (__pyx_t_19 >= PyTuple_GET_SIZE(__pyx_t_14)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_14, __pyx_t_19); __Pyx_INCREF(__pyx_t_1); __pyx_t_19++; if (unlikely(0 < 0)) __PYX_ERR(0, 465, __pyx_L1_error)
        #else
        __pyx_t_1 = PySequence_ITEM(__pyx_t_14, __pyx_t_19); __pyx_t_19++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 465, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
      }
    } else {
      __pyx_t_1 = __pyx_t_20(__pyx_t_14);
      if (unlikely(!__pyx_t_1)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 465, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_XDECREF_SET(__pyx_v_current_epoch, __pyx_t_1);
    __pyx_t_1 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
+466:             if self.verbose:
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_verbose); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 466, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_24 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_24 < 0)) __PYX_ERR(0, 466, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (__pyx_t_24) {
/* … */
    }
+467:                 print(" processing epoch {}".format(current_epoch))
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_processing_epoch, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 467, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_8 = NULL;
      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
        __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_2);
        if (likely(__pyx_t_8)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
          __Pyx_INCREF(__pyx_t_8);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_2, function);
        }
      }
      __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_8, __pyx_v_current_epoch) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_current_epoch);
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 467, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 467, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 468: 
+469:             for u, i, r in trainset.all_ratings():
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_all_ratings); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 469, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_8 = NULL;
    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_1);
      if (likely(__pyx_t_8)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
        __Pyx_INCREF(__pyx_t_8);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_1, function);
      }
    }
    __pyx_t_2 = (__pyx_t_8) ? __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_8) : __Pyx_PyObject_CallNoArg(__pyx_t_1);
    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 469, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
      __pyx_t_1 = __pyx_t_2; __Pyx_INCREF(__pyx_t_1); __pyx_t_21 = 0;
      __pyx_t_22 = NULL;
    } else {
      __pyx_t_21 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 469, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_22 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 469, __pyx_L1_error)
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    for (;;) {
      if (likely(!__pyx_t_22)) {
        if (likely(PyList_CheckExact(__pyx_t_1))) {
          if (__pyx_t_21 >= PyList_GET_SIZE(__pyx_t_1)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_21); __Pyx_INCREF(__pyx_t_2); __pyx_t_21++; if (unlikely(0 < 0)) __PYX_ERR(0, 469, __pyx_L1_error)
          #else
          __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_21); __pyx_t_21++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 469, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_2);
          #endif
        } else {
          if (__pyx_t_21 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_21); __Pyx_INCREF(__pyx_t_2); __pyx_t_21++; if (unlikely(0 < 0)) __PYX_ERR(0, 469, __pyx_L1_error)
          #else
          __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_21); __pyx_t_21++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 469, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_2);
          #endif
        }
      } else {
        __pyx_t_2 = __pyx_t_22(__pyx_t_1);
        if (unlikely(!__pyx_t_2)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 469, __pyx_L1_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_2);
      }
      if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
        PyObject* sequence = __pyx_t_2;
        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
        if (unlikely(size != 3)) {
          if (size > 3) __Pyx_RaiseTooManyValuesError(3);
          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
          __PYX_ERR(0, 469, __pyx_L1_error)
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        if (likely(PyTuple_CheckExact(sequence))) {
          __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); 
          __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); 
          __pyx_t_5 = PyTuple_GET_ITEM(sequence, 2); 
        } else {
          __pyx_t_8 = PyList_GET_ITEM(sequence, 0); 
          __pyx_t_6 = PyList_GET_ITEM(sequence, 1); 
          __pyx_t_5 = PyList_GET_ITEM(sequence, 2); 
        }
        __Pyx_INCREF(__pyx_t_8);
        __Pyx_INCREF(__pyx_t_6);
        __Pyx_INCREF(__pyx_t_5);
        #else
        __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 469, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_8);
        __pyx_t_6 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 469, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __pyx_t_5 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 469, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_5);
        #endif
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      } else {
        Py_ssize_t index = -1;
        __pyx_t_4 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 469, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_23 = Py_TYPE(__pyx_t_4)->tp_iternext;
        index = 0; __pyx_t_8 = __pyx_t_23(__pyx_t_4); if (unlikely(!__pyx_t_8)) goto __pyx_L16_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_8);
        index = 1; __pyx_t_6 = __pyx_t_23(__pyx_t_4); if (unlikely(!__pyx_t_6)) goto __pyx_L16_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_6);
        index = 2; __pyx_t_5 = __pyx_t_23(__pyx_t_4); if (unlikely(!__pyx_t_5)) goto __pyx_L16_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_5);
        if (__Pyx_IternextUnpackEndCheck(__pyx_t_23(__pyx_t_4), 3) < 0) __PYX_ERR(0, 469, __pyx_L1_error)
        __pyx_t_23 = NULL;
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        goto __pyx_L17_unpacking_done;
        __pyx_L16_unpacking_failed:;
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        __pyx_t_23 = NULL;
        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
        __PYX_ERR(0, 469, __pyx_L1_error)
        __pyx_L17_unpacking_done:;
      }
      __pyx_t_7 = __Pyx_PyInt_As_int(__pyx_t_8); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 469, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __pyx_t_25 = __Pyx_PyInt_As_int(__pyx_t_6); if (unlikely((__pyx_t_25 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 469, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_5); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 469, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
      __pyx_v_u = __pyx_t_7;
      __pyx_v_i = __pyx_t_25;
      __pyx_v_r = __pyx_t_3;
/* … */
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 470: 
 471:                 # items rated by u.
+472:                 Iu = Iu_items[u]
      __pyx_v_Iu = (__pyx_v_Iu_items[__pyx_v_u]);
+473:                 sqrt_Iu = Iu_len_sqrts[u]
      __pyx_v_sqrt_Iu = (__pyx_v_Iu_len_sqrts[__pyx_v_u]);
 474: 
 475:                 # compute user implicit feedback
+476:                 f = 0
      __pyx_v_f = 0;
+477:                 while f < facts:
      while (1) {
        __pyx_t_24 = ((__pyx_v_f < __pyx_v_facts) != 0);
        if (!__pyx_t_24) break;
+478:                     u_impl_fdb[f] = 0
        __pyx_t_26 = __pyx_v_f;
        __pyx_t_25 = -1;
        if (__pyx_t_26 < 0) {
          __pyx_t_26 += __pyx_pybuffernd_u_impl_fdb.diminfo[0].shape;
          if (unlikely(__pyx_t_26 < 0)) __pyx_t_25 = 0;
        } else if (unlikely(__pyx_t_26 >= __pyx_pybuffernd_u_impl_fdb.diminfo[0].shape)) __pyx_t_25 = 0;
        if (unlikely(__pyx_t_25 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_25);
          __PYX_ERR(0, 478, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer.buf, __pyx_t_26, __pyx_pybuffernd_u_impl_fdb.diminfo[0].strides) = 0.0;
+479:                     f += 1
        __pyx_v_f = (__pyx_v_f + 1);
      }
 480: 
+481:                 for j in Iu:
      __pyx_t_27 = __pyx_v_Iu.begin();
      for (;;) {
        if (!(__pyx_t_27 != __pyx_v_Iu.end())) break;
        __pyx_t_25 = *__pyx_t_27;
        ++__pyx_t_27;
        __pyx_v_j = __pyx_t_25;
/* … */
      }
+482:                     f = 0
        __pyx_v_f = 0;
+483:                     while f < facts:
        while (1) {
          __pyx_t_24 = ((__pyx_v_f < __pyx_v_facts) != 0);
          if (!__pyx_t_24) break;
+484:                         u_impl_fdb[f] += yj[j, f] * sqrt_Iu
          __pyx_t_26 = __pyx_v_j;
          __pyx_t_28 = __pyx_v_f;
          __pyx_t_25 = -1;
          if (__pyx_t_26 < 0) {
            __pyx_t_26 += __pyx_pybuffernd_yj.diminfo[0].shape;
            if (unlikely(__pyx_t_26 < 0)) __pyx_t_25 = 0;
          } else if (unlikely(__pyx_t_26 >= __pyx_pybuffernd_yj.diminfo[0].shape)) __pyx_t_25 = 0;
          if (__pyx_t_28 < 0) {
            __pyx_t_28 += __pyx_pybuffernd_yj.diminfo[1].shape;
            if (unlikely(__pyx_t_28 < 0)) __pyx_t_25 = 1;
          } else if (unlikely(__pyx_t_28 >= __pyx_pybuffernd_yj.diminfo[1].shape)) __pyx_t_25 = 1;
          if (unlikely(__pyx_t_25 != -1)) {
            __Pyx_RaiseBufferIndexError(__pyx_t_25);
            __PYX_ERR(0, 484, __pyx_L1_error)
          }
          __pyx_t_29 = __pyx_v_f;
          __pyx_t_25 = -1;
          if (__pyx_t_29 < 0) {
            __pyx_t_29 += __pyx_pybuffernd_u_impl_fdb.diminfo[0].shape;
            if (unlikely(__pyx_t_29 < 0)) __pyx_t_25 = 0;
          } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_u_impl_fdb.diminfo[0].shape)) __pyx_t_25 = 0;
          if (unlikely(__pyx_t_25 != -1)) {
            __Pyx_RaiseBufferIndexError(__pyx_t_25);
            __PYX_ERR(0, 484, __pyx_L1_error)
          }
          *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_u_impl_fdb.diminfo[0].strides) += ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_yj.rcbuffer->pybuffer.buf, __pyx_t_26, __pyx_pybuffernd_yj.diminfo[0].strides, __pyx_t_28, __pyx_pybuffernd_yj.diminfo[1].strides)) * __pyx_v_sqrt_Iu);
+485:                         f += 1
          __pyx_v_f = (__pyx_v_f + 1);
        }
 486: 
 487:                 # compute current error
+488:                 dot = 0
      __pyx_v_dot = 0.0;
+489:                 f = 0
      __pyx_v_f = 0;
+490:                 while f < facts:
      while (1) {
        __pyx_t_24 = ((__pyx_v_f < __pyx_v_facts) != 0);
        if (!__pyx_t_24) break;
+491:                     dot += qi[i, f] * (pu[u, f] + u_impl_fdb[f])
        __pyx_t_28 = __pyx_v_i;
        __pyx_t_26 = __pyx_v_f;
        __pyx_t_25 = -1;
        if (__pyx_t_28 < 0) {
          __pyx_t_28 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_28 < 0)) __pyx_t_25 = 0;
        } else if (unlikely(__pyx_t_28 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_25 = 0;
        if (__pyx_t_26 < 0) {
          __pyx_t_26 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_26 < 0)) __pyx_t_25 = 1;
        } else if (unlikely(__pyx_t_26 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_25 = 1;
        if (unlikely(__pyx_t_25 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_25);
          __PYX_ERR(0, 491, __pyx_L1_error)
        }
        __pyx_t_29 = __pyx_v_u;
        __pyx_t_30 = __pyx_v_f;
        __pyx_t_25 = -1;
        if (__pyx_t_29 < 0) {
          __pyx_t_29 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_29 < 0)) __pyx_t_25 = 0;
        } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_25 = 0;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_25 = 1;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_25 = 1;
        if (unlikely(__pyx_t_25 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_25);
          __PYX_ERR(0, 491, __pyx_L1_error)
        }
        __pyx_t_31 = __pyx_v_f;
        __pyx_t_25 = -1;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_u_impl_fdb.diminfo[0].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_25 = 0;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_u_impl_fdb.diminfo[0].shape)) __pyx_t_25 = 0;
        if (unlikely(__pyx_t_25 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_25);
          __PYX_ERR(0, 491, __pyx_L1_error)
        }
        __pyx_v_dot = (__pyx_v_dot + ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_28, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_26, __pyx_pybuffernd_qi.diminfo[1].strides)) * ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_29, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_30, __pyx_pybuffernd_pu.diminfo[1].strides)) + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_u_impl_fdb.diminfo[0].strides)))));
+492:                     f += 1
        __pyx_v_f = (__pyx_v_f + 1);
      }
 493: 
+494:                 err = r - (global_mean + bu[u] + bi[i] + dot)
      __pyx_t_31 = __pyx_v_u;
      __pyx_t_25 = -1;
      if (__pyx_t_31 < 0) {
        __pyx_t_31 += __pyx_pybuffernd_bu.diminfo[0].shape;
        if (unlikely(__pyx_t_31 < 0)) __pyx_t_25 = 0;
      } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_bu.diminfo[0].shape)) __pyx_t_25 = 0;
      if (unlikely(__pyx_t_25 != -1)) {
        __Pyx_RaiseBufferIndexError(__pyx_t_25);
        __PYX_ERR(0, 494, __pyx_L1_error)
      }
      __pyx_t_30 = __pyx_v_i;
      __pyx_t_25 = -1;
      if (__pyx_t_30 < 0) {
        __pyx_t_30 += __pyx_pybuffernd_bi.diminfo[0].shape;
        if (unlikely(__pyx_t_30 < 0)) __pyx_t_25 = 0;
      } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_bi.diminfo[0].shape)) __pyx_t_25 = 0;
      if (unlikely(__pyx_t_25 != -1)) {
        __Pyx_RaiseBufferIndexError(__pyx_t_25);
        __PYX_ERR(0, 494, __pyx_L1_error)
      }
      __pyx_v_err = (__pyx_v_r - (((__pyx_v_global_mean + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bu.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_bu.diminfo[0].strides))) + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bi.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_bi.diminfo[0].strides))) + __pyx_v_dot));
 495: 
 496:                 # update biases
+497:                 bu[u] += lr_bu * (err - reg_bu * bu[u])
      __pyx_t_30 = __pyx_v_u;
      __pyx_t_25 = -1;
      if (__pyx_t_30 < 0) {
        __pyx_t_30 += __pyx_pybuffernd_bu.diminfo[0].shape;
        if (unlikely(__pyx_t_30 < 0)) __pyx_t_25 = 0;
      } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_bu.diminfo[0].shape)) __pyx_t_25 = 0;
      if (unlikely(__pyx_t_25 != -1)) {
        __Pyx_RaiseBufferIndexError(__pyx_t_25);
        __PYX_ERR(0, 497, __pyx_L1_error)
      }
      __pyx_t_31 = __pyx_v_u;
      __pyx_t_25 = -1;
      if (__pyx_t_31 < 0) {
        __pyx_t_31 += __pyx_pybuffernd_bu.diminfo[0].shape;
        if (unlikely(__pyx_t_31 < 0)) __pyx_t_25 = 0;
      } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_bu.diminfo[0].shape)) __pyx_t_25 = 0;
      if (unlikely(__pyx_t_25 != -1)) {
        __Pyx_RaiseBufferIndexError(__pyx_t_25);
        __PYX_ERR(0, 497, __pyx_L1_error)
      }
      *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bu.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_bu.diminfo[0].strides) += (__pyx_v_lr_bu * (__pyx_v_err - (__pyx_v_reg_bu * (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bu.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_bu.diminfo[0].strides)))));
+498:                 bi[i] += lr_bi * (err - reg_bi * bi[i])
      __pyx_t_30 = __pyx_v_i;
      __pyx_t_25 = -1;
      if (__pyx_t_30 < 0) {
        __pyx_t_30 += __pyx_pybuffernd_bi.diminfo[0].shape;
        if (unlikely(__pyx_t_30 < 0)) __pyx_t_25 = 0;
      } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_bi.diminfo[0].shape)) __pyx_t_25 = 0;
      if (unlikely(__pyx_t_25 != -1)) {
        __Pyx_RaiseBufferIndexError(__pyx_t_25);
        __PYX_ERR(0, 498, __pyx_L1_error)
      }
      __pyx_t_31 = __pyx_v_i;
      __pyx_t_25 = -1;
      if (__pyx_t_31 < 0) {
        __pyx_t_31 += __pyx_pybuffernd_bi.diminfo[0].shape;
        if (unlikely(__pyx_t_31 < 0)) __pyx_t_25 = 0;
      } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_bi.diminfo[0].shape)) __pyx_t_25 = 0;
      if (unlikely(__pyx_t_25 != -1)) {
        __Pyx_RaiseBufferIndexError(__pyx_t_25);
        __PYX_ERR(0, 498, __pyx_L1_error)
      }
      *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bi.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_bi.diminfo[0].strides) += (__pyx_v_lr_bi * (__pyx_v_err - (__pyx_v_reg_bi * (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bi.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_bi.diminfo[0].strides)))));
 499: 
 500:                 # update factors
+501:                 f = 0
      __pyx_v_f = 0;
+502:                 while f < facts:
      while (1) {
        __pyx_t_24 = ((__pyx_v_f < __pyx_v_facts) != 0);
        if (!__pyx_t_24) break;
+503:                     puf = pu[u, f]
        __pyx_t_30 = __pyx_v_u;
        __pyx_t_31 = __pyx_v_f;
        __pyx_t_25 = -1;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_25 = 0;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_25 = 0;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_25 = 1;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_25 = 1;
        if (unlikely(__pyx_t_25 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_25);
          __PYX_ERR(0, 503, __pyx_L1_error)
        }
        __pyx_v_puf = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_pu.diminfo[1].strides));
+504:                     qif = qi[i, f]
        __pyx_t_31 = __pyx_v_i;
        __pyx_t_30 = __pyx_v_f;
        __pyx_t_25 = -1;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_25 = 0;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_25 = 0;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_25 = 1;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_25 = 1;
        if (unlikely(__pyx_t_25 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_25);
          __PYX_ERR(0, 504, __pyx_L1_error)
        }
        __pyx_v_qif = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_30, __pyx_pybuffernd_qi.diminfo[1].strides));
+505:                     pu[u, f] += lr_pu * (err * qif - reg_pu * puf)
        __pyx_t_30 = __pyx_v_u;
        __pyx_t_31 = __pyx_v_f;
        __pyx_t_25 = -1;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_25 = 0;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_25 = 0;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_25 = 1;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_25 = 1;
        if (unlikely(__pyx_t_25 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_25);
          __PYX_ERR(0, 505, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_pu.diminfo[1].strides) += (__pyx_v_lr_pu * ((__pyx_v_err * __pyx_v_qif) - (__pyx_v_reg_pu * __pyx_v_puf)));
+506:                     qi[i, f] += lr_qi * (err * (puf + u_impl_fdb[f]) - reg_qi * qif)
        __pyx_t_31 = __pyx_v_f;
        __pyx_t_25 = -1;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_u_impl_fdb.diminfo[0].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_25 = 0;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_u_impl_fdb.diminfo[0].shape)) __pyx_t_25 = 0;
        if (unlikely(__pyx_t_25 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_25);
          __PYX_ERR(0, 506, __pyx_L1_error)
        }
        __pyx_t_30 = __pyx_v_i;
        __pyx_t_29 = __pyx_v_f;
        __pyx_t_25 = -1;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_25 = 0;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_25 = 0;
        if (__pyx_t_29 < 0) {
          __pyx_t_29 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_29 < 0)) __pyx_t_25 = 1;
        } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_25 = 1;
        if (unlikely(__pyx_t_25 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_25);
          __PYX_ERR(0, 506, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_29, __pyx_pybuffernd_qi.diminfo[1].strides) += (__pyx_v_lr_qi * ((__pyx_v_err * (__pyx_v_puf + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_u_impl_fdb.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_u_impl_fdb.diminfo[0].strides)))) - (__pyx_v_reg_qi * __pyx_v_qif)));
+507:                     err_qif_sqrt = err * qif * sqrt_Iu
        __pyx_v_err_qif_sqrt = ((__pyx_v_err * __pyx_v_qif) * __pyx_v_sqrt_Iu);
+508:                     for j in Iu:
        __pyx_t_27 = __pyx_v_Iu.begin();
        for (;;) {
          if (!(__pyx_t_27 != __pyx_v_Iu.end())) break;
          __pyx_t_25 = *__pyx_t_27;
          ++__pyx_t_27;
          __pyx_v_j = __pyx_t_25;
/* … */
        }
+509:                         yj[j, f] += lr_yj * (err_qif_sqrt - reg_yj * yj[j, f])
          __pyx_t_31 = __pyx_v_j;
          __pyx_t_29 = __pyx_v_f;
          __pyx_t_25 = -1;
          if (__pyx_t_31 < 0) {
            __pyx_t_31 += __pyx_pybuffernd_yj.diminfo[0].shape;
            if (unlikely(__pyx_t_31 < 0)) __pyx_t_25 = 0;
          } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_yj.diminfo[0].shape)) __pyx_t_25 = 0;
          if (__pyx_t_29 < 0) {
            __pyx_t_29 += __pyx_pybuffernd_yj.diminfo[1].shape;
            if (unlikely(__pyx_t_29 < 0)) __pyx_t_25 = 1;
          } else if (unlikely(__pyx_t_29 >= __pyx_pybuffernd_yj.diminfo[1].shape)) __pyx_t_25 = 1;
          if (unlikely(__pyx_t_25 != -1)) {
            __Pyx_RaiseBufferIndexError(__pyx_t_25);
            __PYX_ERR(0, 509, __pyx_L1_error)
          }
          __pyx_t_30 = __pyx_v_j;
          __pyx_t_26 = __pyx_v_f;
          __pyx_t_25 = -1;
          if (__pyx_t_30 < 0) {
            __pyx_t_30 += __pyx_pybuffernd_yj.diminfo[0].shape;
            if (unlikely(__pyx_t_30 < 0)) __pyx_t_25 = 0;
          } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_yj.diminfo[0].shape)) __pyx_t_25 = 0;
          if (__pyx_t_26 < 0) {
            __pyx_t_26 += __pyx_pybuffernd_yj.diminfo[1].shape;
            if (unlikely(__pyx_t_26 < 0)) __pyx_t_25 = 1;
          } else if (unlikely(__pyx_t_26 >= __pyx_pybuffernd_yj.diminfo[1].shape)) __pyx_t_25 = 1;
          if (unlikely(__pyx_t_25 != -1)) {
            __Pyx_RaiseBufferIndexError(__pyx_t_25);
            __PYX_ERR(0, 509, __pyx_L1_error)
          }
          *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_yj.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_yj.diminfo[0].strides, __pyx_t_26, __pyx_pybuffernd_yj.diminfo[1].strides) += (__pyx_v_lr_yj * (__pyx_v_err_qif_sqrt - (__pyx_v_reg_yj * (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_yj.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_yj.diminfo[0].strides, __pyx_t_29, __pyx_pybuffernd_yj.diminfo[1].strides)))));
+510:                     f += 1
        __pyx_v_f = (__pyx_v_f + 1);
      }
 511: 
+512:         self.bu = bu
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_bu, ((PyObject *)__pyx_v_bu)) < 0) __PYX_ERR(0, 512, __pyx_L1_error)
+513:         self.bi = bi
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_bi, ((PyObject *)__pyx_v_bi)) < 0) __PYX_ERR(0, 513, __pyx_L1_error)
+514:         self.pu = pu
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_pu, ((PyObject *)__pyx_v_pu)) < 0) __PYX_ERR(0, 514, __pyx_L1_error)
+515:         self.qi = qi
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_qi, ((PyObject *)__pyx_v_qi)) < 0) __PYX_ERR(0, 515, __pyx_L1_error)
+516:         self.yj = yj
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_yj, ((PyObject *)__pyx_v_yj)) < 0) __PYX_ERR(0, 516, __pyx_L1_error)
 517: 
+518:     def estimate(self, u, i):
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_7estimate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_7estimate = {"estimate", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_7estimate, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_7estimate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_u = 0;
  PyObject *__pyx_v_i = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("estimate (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_u,&__pyx_n_s_i,0};
    PyObject* values[3] = {0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_u)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("estimate", 1, 3, 3, 1); __PYX_ERR(0, 518, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_i)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("estimate", 1, 3, 3, 2); __PYX_ERR(0, 518, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "estimate") < 0)) __PYX_ERR(0, 518, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
    }
    __pyx_v_self = values[0];
    __pyx_v_u = values[1];
    __pyx_v_i = values[2];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("estimate", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 518, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVDpp.estimate", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_6estimate(__pyx_self, __pyx_v_self, __pyx_v_u, __pyx_v_i);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
static PyObject *__pyx_gb_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_8estimate_2generator(__pyx_CoroutineObject *__pyx_generator, CYTHON_UNUSED PyThreadState *__pyx_tstate, PyObject *__pyx_sent_value); /* proto */
/* … */
static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_6estimate(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_u, PyObject *__pyx_v_i) {
  struct __pyx_obj_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct__estimate *__pyx_cur_scope;
  PyObject *__pyx_v_est = NULL;
  PyObject *__pyx_v_Iu = NULL;
  PyObject *__pyx_v_u_impl_feedback = NULL;
  PyObject *__pyx_gb_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_8estimate_2generator = 0;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("estimate", 0);
  __pyx_cur_scope = (struct __pyx_obj_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct__estimate *)__pyx_tp_new_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct__estimate(__pyx_ptype_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct__estimate, __pyx_empty_tuple, NULL);
  if (unlikely(!__pyx_cur_scope)) {
    __pyx_cur_scope = ((struct __pyx_obj_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct__estimate *)Py_None);
    __Pyx_INCREF(Py_None);
    __PYX_ERR(0, 518, __pyx_L1_error)
  } else {
    __Pyx_GOTREF(__pyx_cur_scope);
  }
  __pyx_cur_scope->__pyx_v_self = __pyx_v_self;
  __Pyx_INCREF(__pyx_cur_scope->__pyx_v_self);
  __Pyx_GIVEREF(__pyx_cur_scope->__pyx_v_self);
  __pyx_cur_scope->__pyx_v_u = __pyx_v_u;
  __Pyx_INCREF(__pyx_cur_scope->__pyx_v_u);
  __Pyx_GIVEREF(__pyx_cur_scope->__pyx_v_u);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_10);
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVDpp.estimate", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_est);
  __Pyx_XDECREF(__pyx_v_Iu);
  __Pyx_XDECREF(__pyx_v_u_impl_feedback);
  __Pyx_XDECREF(__pyx_gb_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_8estimate_2generator);
  __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__21 = PyTuple_Pack(8, __pyx_n_s_self, __pyx_n_s_u, __pyx_n_s_i, __pyx_n_s_est, __pyx_n_s_Iu, __pyx_n_s_u_impl_feedback, __pyx_n_s_genexpr, __pyx_n_s_genexpr); if (unlikely(!__pyx_tuple__21)) __PYX_ERR(0, 518, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__21);
  __Pyx_GIVEREF(__pyx_tuple__21);
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_7estimate, 0, __pyx_n_s_SVDpp_estimate, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__22)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 518, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_estimate, __pyx_t_4) < 0) __PYX_ERR(0, 518, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_codeobj__22 = (PyObject*)__Pyx_PyCode_New(3, 0, 8, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__21, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_estimate, 518, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__22)) __PYX_ERR(0, 518, __pyx_L1_error)
/* … */
struct __pyx_obj_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct__estimate {
  PyObject_HEAD
  PyObject *__pyx_v_self;
  PyObject *__pyx_v_u;
};

 519: 
+520:         est = self.trainset.global_mean
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 520, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_global_mean); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 520, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_est = __pyx_t_2;
  __pyx_t_2 = 0;
 521: 
+522:         if self.trainset.knows_user(u):
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 522, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_knows_user); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 522, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_1)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_2 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_1, __pyx_cur_scope->__pyx_v_u) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_cur_scope->__pyx_v_u);
  __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 522, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 522, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (__pyx_t_4) {
/* … */
  }
+523:             est += self.bu[u]
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_self, __pyx_n_s_bu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 523, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_3 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_cur_scope->__pyx_v_u); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 523, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_est, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 523, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF_SET(__pyx_v_est, __pyx_t_2);
    __pyx_t_2 = 0;
 524: 
+525:         if self.trainset.knows_item(i):
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 525, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_knows_item); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 525, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_1, function);
    }
  }
  __pyx_t_2 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_3, __pyx_v_i) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_i);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 525, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 525, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (__pyx_t_4) {
/* … */
  }
+526:             est += self.bi[i]
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_self, __pyx_n_s_bi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 526, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_v_i); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 526, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_est, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 526, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF_SET(__pyx_v_est, __pyx_t_2);
    __pyx_t_2 = 0;
 527: 
+528:         if self.trainset.knows_user(u) and self.trainset.knows_item(i):
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 528, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_knows_user); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 528, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_1)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_2 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_1, __pyx_cur_scope->__pyx_v_u) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_cur_scope->__pyx_v_u);
  __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 528, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 528, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (__pyx_t_5) {
  } else {
    __pyx_t_4 = __pyx_t_5;
    goto __pyx_L6_bool_binop_done;
  }
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 528, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_knows_item); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 528, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_1, function);
    }
  }
  __pyx_t_2 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_3, __pyx_v_i) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_i);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 528, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 528, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_4 = __pyx_t_5;
  __pyx_L6_bool_binop_done:;
  if (__pyx_t_4) {
/* … */
  }
+529:             Iu = len(self.trainset.ur[u])  # nb of items rated by u
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 529, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ur); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 529, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_cur_scope->__pyx_v_u); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 529, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_6 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_6 == ((Py_ssize_t)-1))) __PYX_ERR(0, 529, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = PyInt_FromSsize_t(__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 529, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_v_Iu = __pyx_t_2;
    __pyx_t_2 = 0;
+530:             u_impl_feedback = (sum(self.yj[j] for (j, _)
static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_8estimate_genexpr(PyObject *__pyx_self) {
  struct __pyx_obj_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct_1_genexpr *__pyx_cur_scope;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("genexpr", 0);
  __pyx_cur_scope = (struct __pyx_obj_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct_1_genexpr *)__pyx_tp_new_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct_1_genexpr(__pyx_ptype_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct_1_genexpr, __pyx_empty_tuple, NULL);
  if (unlikely(!__pyx_cur_scope)) {
    __pyx_cur_scope = ((struct __pyx_obj_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct_1_genexpr *)Py_None);
    __Pyx_INCREF(Py_None);
    __PYX_ERR(0, 530, __pyx_L1_error)
  } else {
    __Pyx_GOTREF(__pyx_cur_scope);
  }
  __pyx_cur_scope->__pyx_outer_scope = (struct __pyx_obj_8surprise_21prediction_algorithms_20matrix_factorization___pyx_scope_struct__estimate *) __pyx_self;
  __Pyx_INCREF(((PyObject *)__pyx_cur_scope->__pyx_outer_scope));
  __Pyx_GIVEREF(__pyx_cur_scope->__pyx_outer_scope);
  {
    __pyx_CoroutineObject *gen = __Pyx_Generator_New((__pyx_coroutine_body_t) __pyx_gb_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_8estimate_2generator, NULL, (PyObject *) __pyx_cur_scope, __pyx_n_s_genexpr, __pyx_n_s_SVDpp_estimate_locals_genexpr, __pyx_n_s_surprise_prediction_algorithms_m); if (unlikely(!gen)) __PYX_ERR(0, 530, __pyx_L1_error)
    __Pyx_DECREF(__pyx_cur_scope);
    __Pyx_RefNannyFinishContext();
    return (PyObject *) gen;
  }

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.SVDpp.estimate.genexpr", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_gb_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_8estimate_2generator(__pyx_CoroutineObject *__pyx_generator, CYTHON_UNUSED PyThreadState *__pyx_tstate, PyObject *__pyx_sent_value) /* generator body */
{
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("genexpr", 0);
  __pyx_L3_first_run:;
  if (unlikely(!__pyx_sent_value)) __PYX_ERR(0, 530, __pyx_L1_error)
/* … */
    __Pyx_XGOTREF(__pyx_cur_scope->__pyx_v_j);
    __Pyx_XDECREF_SET(__pyx_cur_scope->__pyx_v_j, __pyx_t_5);
    __Pyx_GIVEREF(__pyx_t_5);
    __pyx_t_5 = 0;
    __Pyx_XGOTREF(__pyx_cur_scope->__pyx_v__);
    __Pyx_XDECREF_SET(__pyx_cur_scope->__pyx_v__, __pyx_t_6);
    __Pyx_GIVEREF(__pyx_t_6);
    __pyx_t_6 = 0;
    if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self)) { __Pyx_RaiseClosureNameError("self"); __PYX_ERR(0, 530, __pyx_L1_error) }
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self, __pyx_n_s_yj); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 530, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_cur_scope->__pyx_v_j); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 530, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_r = __pyx_t_6;
    __pyx_t_6 = 0;
    __Pyx_XGIVEREF(__pyx_t_2);
    __pyx_cur_scope->__pyx_t_0 = __pyx_t_2;
    __pyx_cur_scope->__pyx_t_1 = __pyx_t_3;
    __pyx_cur_scope->__pyx_t_2 = __pyx_t_4;
    __Pyx_XGIVEREF(__pyx_r);
    __Pyx_RefNannyFinishContext();
    __Pyx_Coroutine_ResetAndClearException(__pyx_generator);
    /* return from generator, yielding value */
    __pyx_generator->resume_label = 1;
    return __pyx_r;
    __pyx_L8_resume_from_yield:;
    __pyx_t_2 = __pyx_cur_scope->__pyx_t_0;
    __pyx_cur_scope->__pyx_t_0 = 0;
    __Pyx_XGOTREF(__pyx_t_2);
    __pyx_t_3 = __pyx_cur_scope->__pyx_t_1;
    __pyx_t_4 = __pyx_cur_scope->__pyx_t_2;
    if (unlikely(!__pyx_sent_value)) __PYX_ERR(0, 530, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  CYTHON_MAYBE_UNUSED_VAR(__pyx_cur_scope);

  /* function exit code */
  PyErr_SetNone(PyExc_StopIteration);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_AddTraceback("genexpr", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_r); __pyx_r = 0;
  #if !CYTHON_USE_EXC_INFO_STACK
  __Pyx_Coroutine_ResetAndClearException(__pyx_generator);
  #endif
  __pyx_generator->resume_label = -1;
  __Pyx_Coroutine_clear((PyObject*)__pyx_generator);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
    __pyx_t_2 = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_5SVDpp_8estimate_genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 530, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_sum, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 530, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+531:                                in self.trainset.ur[u]) / np.sqrt(Iu))
  if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self)) { __Pyx_RaiseClosureNameError("self"); __PYX_ERR(0, 531, __pyx_L1_error) }
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 531, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ur); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 531, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_u)) { __Pyx_RaiseClosureNameError("u"); __PYX_ERR(0, 531, __pyx_L1_error) }
  __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_cur_scope->__pyx_outer_scope->__pyx_v_u); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 531, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
    __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;
    __pyx_t_4 = NULL;
  } else {
    __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 531, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 531, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    if (likely(!__pyx_t_4)) {
      if (likely(PyList_CheckExact(__pyx_t_2))) {
        if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_1); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 531, __pyx_L1_error)
        #else
        __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 531, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
      } else {
        if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_1); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 531, __pyx_L1_error)
        #else
        __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 531, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
      }
    } else {
      __pyx_t_1 = __pyx_t_4(__pyx_t_2);
      if (unlikely(!__pyx_t_1)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 531, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_1);
    }
    if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
      PyObject* sequence = __pyx_t_1;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 530, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); 
        __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); 
      } else {
        __pyx_t_5 = PyList_GET_ITEM(sequence, 0); 
        __pyx_t_6 = PyList_GET_ITEM(sequence, 1); 
      }
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(__pyx_t_6);
      #else
      __pyx_t_5 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 530, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __pyx_t_6 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 530, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      #endif
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_7 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 530, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_8 = Py_TYPE(__pyx_t_7)->tp_iternext;
      index = 0; __pyx_t_5 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_5)) goto __pyx_L6_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_5);
      index = 1; __pyx_t_6 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_6)) goto __pyx_L6_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_6);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_7), 2) < 0) __PYX_ERR(0, 530, __pyx_L1_error)
      __pyx_t_8 = NULL;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      goto __pyx_L7_unpacking_done;
      __pyx_L6_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_t_8 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 530, __pyx_L1_error)
      __pyx_L7_unpacking_done:;
    }
/* … */
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 531, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_sqrt); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 531, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_7);
      if (likely(__pyx_t_3)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_7, function);
      }
    }
    __pyx_t_2 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_3, __pyx_v_Iu) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_Iu);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 531, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_t_7 = __Pyx_PyNumber_Divide(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 531, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_u_impl_feedback = __pyx_t_7;
    __pyx_t_7 = 0;
+532:             est += np.dot(self.qi[i], self.pu[u] + u_impl_feedback)
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 532, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_dot); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 532, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_self, __pyx_n_s_qi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 532, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_3 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_v_i); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 532, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_cur_scope->__pyx_v_self, __pyx_n_s_pu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 532, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_8 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_cur_scope->__pyx_v_u); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 532, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = PyNumber_Add(__pyx_t_8, __pyx_v_u_impl_feedback); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 532, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __pyx_t_8 = NULL;
    __pyx_t_9 = 0;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_1);
      if (likely(__pyx_t_8)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
        __Pyx_INCREF(__pyx_t_8);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_1, function);
        __pyx_t_9 = 1;
      }
    }
    #if CYTHON_FAST_PYCALL
    if (PyFunction_Check(__pyx_t_1)) {
      PyObject *__pyx_temp[3] = {__pyx_t_8, __pyx_t_3, __pyx_t_2};
      __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_9, 2+__pyx_t_9); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 532, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    } else
    #endif
    #if CYTHON_FAST_PYCCALL
    if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) {
      PyObject *__pyx_temp[3] = {__pyx_t_8, __pyx_t_3, __pyx_t_2};
      __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_9, 2+__pyx_t_9); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 532, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    } else
    #endif
    {
      __pyx_t_10 = PyTuple_New(2+__pyx_t_9); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 532, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      if (__pyx_t_8) {
        __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_8); __pyx_t_8 = NULL;
      }
      __Pyx_GIVEREF(__pyx_t_3);
      PyTuple_SET_ITEM(__pyx_t_10, 0+__pyx_t_9, __pyx_t_3);
      __Pyx_GIVEREF(__pyx_t_2);
      PyTuple_SET_ITEM(__pyx_t_10, 1+__pyx_t_9, __pyx_t_2);
      __pyx_t_3 = 0;
      __pyx_t_2 = 0;
      __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_10, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 532, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_1 = PyNumber_InPlaceAdd(__pyx_v_est, __pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 532, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF_SET(__pyx_v_est, __pyx_t_1);
    __pyx_t_1 = 0;
 533: 
+534:         return est
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_est);
  __pyx_r = __pyx_v_est;
  goto __pyx_L0;
 535: 
 536: 
+537: class NMF(AlgoBase):
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_AlgoBase); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 537, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 537, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
  __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 537, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_t_2, __pyx_n_s_NMF, __pyx_n_s_NMF, (PyObject *) NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_kp_s_A_collaborative_filtering_algori); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 537, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
/* … */
  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_NMF, __pyx_t_2, __pyx_t_3, NULL, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 537, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NMF, __pyx_t_4) < 0) __PYX_ERR(0, 537, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 538:     """A collaborative filtering algorithm based on Non-negative Matrix
 539:     Factorization.
 540: 
 541:     This algorithm is very similar to :class:`SVD`. The prediction
 542:     :math:`\\hat{r}_{ui}` is set as:
 543: 
 544:     .. math::
 545:         \hat{r}_{ui} = q_i^Tp_u,
 546: 
 547:     where user and item factors are kept **positive**. Our implementation
 548:     follows that suggested in :cite:`NMF:2014`, which is equivalent to
 549:     :cite:`Zhang96` in its non-regularized form. Both are direct applications
 550:     of NMF for dense matrices :cite:`NMF_algo`.
 551: 
 552:     The optimization procedure is a (regularized) stochastic gradient descent
 553:     with a specific choice of step size that ensures non-negativity of factors,
 554:     provided that their initial values are also positive.
 555: 
 556:     At each step of the SGD procedure, the factors :math:`f` or user :math:`u`
 557:     and item :math:`i` are updated as follows:
 558: 
 559:     .. math::
 560:         p_{uf} &\\leftarrow p_{uf} &\cdot \\frac{\\sum_{i \in I_u} q_{if}
 561:         \\cdot r_{ui}}{\\sum_{i \in I_u} q_{if} \\cdot \\hat{r_{ui}} +
 562:         \\lambda_u |I_u| p_{uf}}\\\\
 563:         q_{if} &\\leftarrow q_{if} &\cdot \\frac{\\sum_{u \in U_i} p_{uf}
 564:         \\cdot r_{ui}}{\\sum_{u \in U_i} p_{uf} \\cdot \\hat{r_{ui}} +
 565:         \lambda_i |U_i| q_{if}}\\\\
 566: 
 567:     where :math:`\lambda_u` and :math:`\lambda_i` are regularization
 568:     parameters.
 569: 
 570:     This algorithm is highly dependent on initial values. User and item factors
 571:     are uniformly initialized between ``init_low`` and ``init_high``. Change
 572:     them at your own risks!
 573: 
 574:     A biased version is available by setting the ``biased`` parameter to
 575:     ``True``. In this case, the prediction is set as
 576: 
 577:     .. math::
 578:         \hat{r}_{ui} = \mu + b_u + b_i + q_i^Tp_u,
 579: 
 580:     still ensuring positive factors. Baselines are optimized in the same way as
 581:     in the :class:`SVD` algorithm. While yielding better accuracy, the biased
 582:     version seems highly prone to overfitting so you may want to reduce the
 583:     number of factors (or increase regularization).
 584: 
 585:     Args:
 586:         n_factors: The number of factors. Default is ``15``.
 587:         n_epochs: The number of iteration of the SGD procedure. Default is
 588:             ``50``.
 589:         biased(bool): Whether to use baselines (or biases). Default is
 590:             ``False``.
 591:         reg_pu: The regularization term for users :math:`\lambda_u`. Default is
 592:             ``0.06``.
 593:         reg_qi: The regularization term for items :math:`\lambda_i`. Default is
 594:             ``0.06``.
 595:         reg_bu: The regularization term for :math:`b_u`. Only relevant for
 596:             biased version. Default is ``0.02``.
 597:         reg_bi: The regularization term for :math:`b_i`. Only relevant for
 598:             biased version. Default is ``0.02``.
 599:         lr_bu: The learning rate for :math:`b_u`. Only relevant for biased
 600:             version. Default is ``0.005``.
 601:         lr_bi: The learning rate for :math:`b_i`. Only relevant for biased
 602:             version. Default is ``0.005``.
 603:         init_low: Lower bound for random initialization of factors. Must be
 604:             greater than ``0`` to ensure non-negative factors. Default is
 605:             ``0``.
 606:         init_high: Higher bound for random initialization of factors. Default
 607:             is ``1``.
 608:         random_state(int, RandomState instance from numpy, or ``None``):
 609:             Determines the RNG that will be used for initialization. If
 610:             int, ``random_state`` will be used as a seed for a new RNG. This is
 611:             useful to get the same initialization over multiple calls to
 612:             ``fit()``.  If RandomState instance, this same instance is used as
 613:             RNG. If ``None``, the current RNG from numpy is used.  Default is
 614:             ``None``.
 615:         verbose: If ``True``, prints the current epoch. Default is ``False``.
 616: 
 617:     Attributes:
 618:         pu(numpy array of size (n_users, n_factors)): The user factors (only
 619:             exists if ``fit()`` has been called)
 620:         qi(numpy array of size (n_items, n_factors)): The item factors (only
 621:             exists if ``fit()`` has been called)
 622:         bu(numpy array of size (n_users)): The user biases (only
 623:             exists if ``fit()`` has been called)
 624:         bi(numpy array of size (n_items)): The item biases (only
 625:             exists if ``fit()`` has been called)
 626:     """
 627: 
+628:     def __init__(self, n_factors=15, n_epochs=50, biased=False, reg_pu=.06,
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_1__init__ = {"__init__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_1__init__, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_n_factors = 0;
  PyObject *__pyx_v_n_epochs = 0;
  PyObject *__pyx_v_biased = 0;
  PyObject *__pyx_v_reg_pu = 0;
  PyObject *__pyx_v_reg_qi = 0;
  PyObject *__pyx_v_reg_bu = 0;
  PyObject *__pyx_v_reg_bi = 0;
  PyObject *__pyx_v_lr_bu = 0;
  PyObject *__pyx_v_lr_bi = 0;
  PyObject *__pyx_v_init_low = 0;
  PyObject *__pyx_v_init_high = 0;
  PyObject *__pyx_v_random_state = 0;
  PyObject *__pyx_v_verbose = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_n_factors,&__pyx_n_s_n_epochs,&__pyx_n_s_biased,&__pyx_n_s_reg_pu,&__pyx_n_s_reg_qi,&__pyx_n_s_reg_bu,&__pyx_n_s_reg_bi,&__pyx_n_s_lr_bu,&__pyx_n_s_lr_bi,&__pyx_n_s_init_low,&__pyx_n_s_init_high,&__pyx_n_s_random_state,&__pyx_n_s_verbose,0};
    PyObject* values[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    values[1] = ((PyObject *)((PyObject *)__pyx_int_15));
    values[2] = ((PyObject *)((PyObject *)__pyx_int_50));
    values[3] = ((PyObject *)((PyObject *)Py_False));
    values[4] = ((PyObject *)((PyObject*)__pyx_float__06));
    values[5] = ((PyObject *)((PyObject*)__pyx_float__06));
    values[6] = ((PyObject *)((PyObject*)__pyx_float__02));
    values[7] = ((PyObject *)((PyObject*)__pyx_float__02));
    values[8] = ((PyObject *)((PyObject*)__pyx_float__005));
    values[9] = ((PyObject *)((PyObject*)__pyx_float__005));
    values[10] = ((PyObject *)((PyObject *)__pyx_int_0));
    values[11] = ((PyObject *)((PyObject *)__pyx_int_1));
/* … */
  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3NMF___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_n_factors, PyObject *__pyx_v_n_epochs, PyObject *__pyx_v_biased, PyObject *__pyx_v_reg_pu, PyObject *__pyx_v_reg_qi, PyObject *__pyx_v_reg_bu, PyObject *__pyx_v_reg_bi, PyObject *__pyx_v_lr_bu, PyObject *__pyx_v_lr_bi, PyObject *__pyx_v_init_low, PyObject *__pyx_v_init_high, PyObject *__pyx_v_random_state, PyObject *__pyx_v_verbose) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__init__", 0);
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.NMF.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__23 = PyTuple_Pack(14, __pyx_n_s_self, __pyx_n_s_n_factors, __pyx_n_s_n_epochs, __pyx_n_s_biased, __pyx_n_s_reg_pu, __pyx_n_s_reg_qi, __pyx_n_s_reg_bu, __pyx_n_s_reg_bi, __pyx_n_s_lr_bu, __pyx_n_s_lr_bi, __pyx_n_s_init_low, __pyx_n_s_init_high, __pyx_n_s_random_state, __pyx_n_s_verbose); if (unlikely(!__pyx_tuple__23)) __PYX_ERR(0, 628, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__23);
  __Pyx_GIVEREF(__pyx_tuple__23);
  __pyx_codeobj__24 = (PyObject*)__Pyx_PyCode_New(14, 0, 14, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__23, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_init, 628, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__24)) __PYX_ERR(0, 628, __pyx_L1_error)
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_1__init__, 0, __pyx_n_s_NMF___init, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__24)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 628, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_4, __pyx_tuple__25);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_init, __pyx_t_4) < 0) __PYX_ERR(0, 628, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_tuple__25 = PyTuple_Pack(13, ((PyObject *)__pyx_int_15), ((PyObject *)__pyx_int_50), ((PyObject *)Py_False), ((PyObject*)__pyx_float__06), ((PyObject*)__pyx_float__06), ((PyObject*)__pyx_float__02), ((PyObject*)__pyx_float__02), ((PyObject*)__pyx_float__005), ((PyObject*)__pyx_float__005), ((PyObject *)__pyx_int_0), ((PyObject *)__pyx_int_1), ((PyObject *)Py_None), ((PyObject *)Py_False)); if (unlikely(!__pyx_tuple__25)) __PYX_ERR(0, 628, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__25);
  __Pyx_GIVEREF(__pyx_tuple__25);
 629:                  reg_qi=.06, reg_bu=.02, reg_bi=.02, lr_bu=.005, lr_bi=.005,
+630:                  init_low=0, init_high=1, random_state=None, verbose=False):
    values[12] = ((PyObject *)((PyObject *)Py_None));
    values[13] = ((PyObject *)((PyObject *)Py_False));
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case 14: values[13] = PyTuple_GET_ITEM(__pyx_args, 13);
        CYTHON_FALLTHROUGH;
        case 13: values[12] = PyTuple_GET_ITEM(__pyx_args, 12);
        CYTHON_FALLTHROUGH;
        case 12: values[11] = PyTuple_GET_ITEM(__pyx_args, 11);
        CYTHON_FALLTHROUGH;
        case 11: values[10] = PyTuple_GET_ITEM(__pyx_args, 10);
        CYTHON_FALLTHROUGH;
        case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9);
        CYTHON_FALLTHROUGH;
        case  9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8);
        CYTHON_FALLTHROUGH;
        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_n_factors);
          if (value) { values[1] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_n_epochs);
          if (value) { values[2] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_biased);
          if (value) { values[3] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  4:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_pu);
          if (value) { values[4] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  5:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_qi);
          if (value) { values[5] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  6:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_bu);
          if (value) { values[6] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  7:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reg_bi);
          if (value) { values[7] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  8:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_bu);
          if (value) { values[8] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  9:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lr_bi);
          if (value) { values[9] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 10:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_init_low);
          if (value) { values[10] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 11:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_init_high);
          if (value) { values[11] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 12:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_random_state);
          if (value) { values[12] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case 13:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_verbose);
          if (value) { values[13] = value; kw_args--; }
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 628, __pyx_L3_error)
      }
    } else {
      switch (PyTuple_GET_SIZE(__pyx_args)) {
        case 14: values[13] = PyTuple_GET_ITEM(__pyx_args, 13);
        CYTHON_FALLTHROUGH;
        case 13: values[12] = PyTuple_GET_ITEM(__pyx_args, 12);
        CYTHON_FALLTHROUGH;
        case 12: values[11] = PyTuple_GET_ITEM(__pyx_args, 11);
        CYTHON_FALLTHROUGH;
        case 11: values[10] = PyTuple_GET_ITEM(__pyx_args, 10);
        CYTHON_FALLTHROUGH;
        case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9);
        CYTHON_FALLTHROUGH;
        case  9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8);
        CYTHON_FALLTHROUGH;
        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        break;
        default: goto __pyx_L5_argtuple_error;
      }
    }
    __pyx_v_self = values[0];
    __pyx_v_n_factors = values[1];
    __pyx_v_n_epochs = values[2];
    __pyx_v_biased = values[3];
    __pyx_v_reg_pu = values[4];
    __pyx_v_reg_qi = values[5];
    __pyx_v_reg_bu = values[6];
    __pyx_v_reg_bi = values[7];
    __pyx_v_lr_bu = values[8];
    __pyx_v_lr_bi = values[9];
    __pyx_v_init_low = values[10];
    __pyx_v_init_high = values[11];
    __pyx_v_random_state = values[12];
    __pyx_v_verbose = values[13];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("__init__", 0, 1, 14, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 628, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.NMF.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3NMF___init__(__pyx_self, __pyx_v_self, __pyx_v_n_factors, __pyx_v_n_epochs, __pyx_v_biased, __pyx_v_reg_pu, __pyx_v_reg_qi, __pyx_v_reg_bu, __pyx_v_reg_bi, __pyx_v_lr_bu, __pyx_v_lr_bi, __pyx_v_init_low, __pyx_v_init_high, __pyx_v_random_state, __pyx_v_verbose);
 631: 
+632:         self.n_factors = n_factors
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_n_factors, __pyx_v_n_factors) < 0) __PYX_ERR(0, 632, __pyx_L1_error)
+633:         self.n_epochs = n_epochs
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_n_epochs, __pyx_v_n_epochs) < 0) __PYX_ERR(0, 633, __pyx_L1_error)
+634:         self.biased = biased
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_biased, __pyx_v_biased) < 0) __PYX_ERR(0, 634, __pyx_L1_error)
+635:         self.reg_pu = reg_pu
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_pu, __pyx_v_reg_pu) < 0) __PYX_ERR(0, 635, __pyx_L1_error)
+636:         self.reg_qi = reg_qi
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_qi, __pyx_v_reg_qi) < 0) __PYX_ERR(0, 636, __pyx_L1_error)
+637:         self.lr_bu = lr_bu
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_bu, __pyx_v_lr_bu) < 0) __PYX_ERR(0, 637, __pyx_L1_error)
+638:         self.lr_bi = lr_bi
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_lr_bi, __pyx_v_lr_bi) < 0) __PYX_ERR(0, 638, __pyx_L1_error)
+639:         self.reg_bu = reg_bu
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_bu, __pyx_v_reg_bu) < 0) __PYX_ERR(0, 639, __pyx_L1_error)
+640:         self.reg_bi = reg_bi
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_reg_bi, __pyx_v_reg_bi) < 0) __PYX_ERR(0, 640, __pyx_L1_error)
+641:         self.init_low = init_low
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_init_low, __pyx_v_init_low) < 0) __PYX_ERR(0, 641, __pyx_L1_error)
+642:         self.init_high = init_high
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_init_high, __pyx_v_init_high) < 0) __PYX_ERR(0, 642, __pyx_L1_error)
+643:         self.random_state = random_state
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_random_state, __pyx_v_random_state) < 0) __PYX_ERR(0, 643, __pyx_L1_error)
+644:         self.verbose = verbose
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_verbose, __pyx_v_verbose) < 0) __PYX_ERR(0, 644, __pyx_L1_error)
 645: 
+646:         if self.init_low < 0:
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_low); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 646, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_int_0, Py_LT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 646, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 646, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(__pyx_t_3)) {
/* … */
  }
+647:             raise ValueError('init_low should be greater than zero')
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 647, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __PYX_ERR(0, 647, __pyx_L1_error)
/* … */
  __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_u_init_low_should_be_greater_than); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 647, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple_);
  __Pyx_GIVEREF(__pyx_tuple_);
 648: 
+649:         AlgoBase.__init__(self)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_AlgoBase); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 649, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_init); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 649, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_1)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  __pyx_t_2 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_1, __pyx_v_self) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_self);
  __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 649, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 650: 
+651:     def fit(self, trainset):
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_3fit(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_3fit = {"fit", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_3fit, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_3fit(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_trainset = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("fit (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_trainset,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_trainset)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("fit", 1, 2, 2, 1); __PYX_ERR(0, 651, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "fit") < 0)) __PYX_ERR(0, 651, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_self = values[0];
    __pyx_v_trainset = values[1];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("fit", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 651, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.NMF.fit", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_2fit(__pyx_self, __pyx_v_self, __pyx_v_trainset);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_2fit(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_trainset) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("fit", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.NMF.fit", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__26 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_trainset); if (unlikely(!__pyx_tuple__26)) __PYX_ERR(0, 651, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__26);
  __Pyx_GIVEREF(__pyx_tuple__26);
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_3fit, 0, __pyx_n_s_NMF_fit, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__27)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 651, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_fit, __pyx_t_4) < 0) __PYX_ERR(0, 651, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_codeobj__27 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__26, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_fit, 651, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__27)) __PYX_ERR(0, 651, __pyx_L1_error)
 652: 
+653:         AlgoBase.fit(self, trainset)
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_AlgoBase); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 653, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_fit); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 653, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = NULL;
  __pyx_t_4 = 0;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_2)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
      __pyx_t_4 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_3)) {
    PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_v_self, __pyx_v_trainset};
    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_4, 2+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 653, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_GOTREF(__pyx_t_1);
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
    PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_v_self, __pyx_v_trainset};
    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_4, 2+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 653, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_GOTREF(__pyx_t_1);
  } else
  #endif
  {
    __pyx_t_5 = PyTuple_New(2+__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 653, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    if (__pyx_t_2) {
      __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2); __pyx_t_2 = NULL;
    }
    __Pyx_INCREF(__pyx_v_self);
    __Pyx_GIVEREF(__pyx_v_self);
    PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_4, __pyx_v_self);
    __Pyx_INCREF(__pyx_v_trainset);
    __Pyx_GIVEREF(__pyx_v_trainset);
    PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_4, __pyx_v_trainset);
    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 653, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+654:         self.sgd(trainset)
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_sgd); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 654, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_v_trainset) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_trainset);
  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 654, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 655: 
+656:         return self
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_self);
  __pyx_r = __pyx_v_self;
  goto __pyx_L0;
 657: 
+658:     def sgd(self, trainset):
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_5sgd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_5sgd = {"sgd", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_5sgd, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_5sgd(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_trainset = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("sgd (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_trainset,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_trainset)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("sgd", 1, 2, 2, 1); __PYX_ERR(0, 658, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "sgd") < 0)) __PYX_ERR(0, 658, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_self = values[0];
    __pyx_v_trainset = values[1];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("sgd", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 658, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.NMF.sgd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_4sgd(__pyx_self, __pyx_v_self, __pyx_v_trainset);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_4sgd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_trainset) {
  PyArrayObject *__pyx_v_pu = 0;
  PyArrayObject *__pyx_v_qi = 0;
  PyArrayObject *__pyx_v_bu = 0;
  PyArrayObject *__pyx_v_bi = 0;
  PyArrayObject *__pyx_v_user_num = 0;
  PyArrayObject *__pyx_v_user_denom = 0;
  PyArrayObject *__pyx_v_item_num = 0;
  PyArrayObject *__pyx_v_item_denom = 0;
  int __pyx_v_u;
  int __pyx_v_i;
  int __pyx_v_f;
  double __pyx_v_r;
  double __pyx_v_est;
  double __pyx_v_dot;
  double __pyx_v_err;
  double __pyx_v_reg_pu;
  double __pyx_v_reg_qi;
  double __pyx_v_reg_bu;
  double __pyx_v_reg_bi;
  double __pyx_v_lr_bu;
  double __pyx_v_lr_bi;
  double __pyx_v_global_mean;
  PyObject *__pyx_v_rng = NULL;
  PyObject *__pyx_v_current_epoch = NULL;
  PyObject *__pyx_v_n_ratings = NULL;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_bi;
  __Pyx_Buffer __pyx_pybuffer_bi;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_bu;
  __Pyx_Buffer __pyx_pybuffer_bu;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_item_denom;
  __Pyx_Buffer __pyx_pybuffer_item_denom;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_item_num;
  __Pyx_Buffer __pyx_pybuffer_item_num;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_pu;
  __Pyx_Buffer __pyx_pybuffer_pu;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_qi;
  __Pyx_Buffer __pyx_pybuffer_qi;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_user_denom;
  __Pyx_Buffer __pyx_pybuffer_user_denom;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_user_num;
  __Pyx_Buffer __pyx_pybuffer_user_num;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("sgd", 0);
  __pyx_pybuffer_pu.pybuffer.buf = NULL;
  __pyx_pybuffer_pu.refcount = 0;
  __pyx_pybuffernd_pu.data = NULL;
  __pyx_pybuffernd_pu.rcbuffer = &__pyx_pybuffer_pu;
  __pyx_pybuffer_qi.pybuffer.buf = NULL;
  __pyx_pybuffer_qi.refcount = 0;
  __pyx_pybuffernd_qi.data = NULL;
  __pyx_pybuffernd_qi.rcbuffer = &__pyx_pybuffer_qi;
  __pyx_pybuffer_bu.pybuffer.buf = NULL;
  __pyx_pybuffer_bu.refcount = 0;
  __pyx_pybuffernd_bu.data = NULL;
  __pyx_pybuffernd_bu.rcbuffer = &__pyx_pybuffer_bu;
  __pyx_pybuffer_bi.pybuffer.buf = NULL;
  __pyx_pybuffer_bi.refcount = 0;
  __pyx_pybuffernd_bi.data = NULL;
  __pyx_pybuffernd_bi.rcbuffer = &__pyx_pybuffer_bi;
  __pyx_pybuffer_user_num.pybuffer.buf = NULL;
  __pyx_pybuffer_user_num.refcount = 0;
  __pyx_pybuffernd_user_num.data = NULL;
  __pyx_pybuffernd_user_num.rcbuffer = &__pyx_pybuffer_user_num;
  __pyx_pybuffer_user_denom.pybuffer.buf = NULL;
  __pyx_pybuffer_user_denom.refcount = 0;
  __pyx_pybuffernd_user_denom.data = NULL;
  __pyx_pybuffernd_user_denom.rcbuffer = &__pyx_pybuffer_user_denom;
  __pyx_pybuffer_item_num.pybuffer.buf = NULL;
  __pyx_pybuffer_item_num.refcount = 0;
  __pyx_pybuffernd_item_num.data = NULL;
  __pyx_pybuffernd_item_num.rcbuffer = &__pyx_pybuffer_item_num;
  __pyx_pybuffer_item_denom.pybuffer.buf = NULL;
  __pyx_pybuffer_item_denom.refcount = 0;
  __pyx_pybuffernd_item_denom.data = NULL;
  __pyx_pybuffernd_item_denom.rcbuffer = &__pyx_pybuffer_item_denom;
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_26);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bi.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bu.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_item_denom.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_item_num.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_pu.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_qi.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_user_denom.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_user_num.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.NMF.sgd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bi.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bu.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_item_denom.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_item_num.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_pu.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_qi.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_user_denom.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_user_num.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_pu);
  __Pyx_XDECREF((PyObject *)__pyx_v_qi);
  __Pyx_XDECREF((PyObject *)__pyx_v_bu);
  __Pyx_XDECREF((PyObject *)__pyx_v_bi);
  __Pyx_XDECREF((PyObject *)__pyx_v_user_num);
  __Pyx_XDECREF((PyObject *)__pyx_v_user_denom);
  __Pyx_XDECREF((PyObject *)__pyx_v_item_num);
  __Pyx_XDECREF((PyObject *)__pyx_v_item_denom);
  __Pyx_XDECREF(__pyx_v_rng);
  __Pyx_XDECREF(__pyx_v_current_epoch);
  __Pyx_XDECREF(__pyx_v_n_ratings);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__28 = PyTuple_Pack(28, __pyx_n_s_self, __pyx_n_s_trainset, __pyx_n_s_pu, __pyx_n_s_qi, __pyx_n_s_bu, __pyx_n_s_bi, __pyx_n_s_user_num, __pyx_n_s_user_denom, __pyx_n_s_item_num, __pyx_n_s_item_denom, __pyx_n_s_u, __pyx_n_s_i, __pyx_n_s_f, __pyx_n_s_r, __pyx_n_s_est, __pyx_n_s_l, __pyx_n_s_dot, __pyx_n_s_err, __pyx_n_s_reg_pu, __pyx_n_s_reg_qi, __pyx_n_s_reg_bu, __pyx_n_s_reg_bi, __pyx_n_s_lr_bu, __pyx_n_s_lr_bi, __pyx_n_s_global_mean, __pyx_n_s_rng, __pyx_n_s_current_epoch, __pyx_n_s_n_ratings); if (unlikely(!__pyx_tuple__28)) __PYX_ERR(0, 658, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__28);
  __Pyx_GIVEREF(__pyx_tuple__28);
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_5sgd, 0, __pyx_n_s_NMF_sgd, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__29)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 658, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_sgd, __pyx_t_4) < 0) __PYX_ERR(0, 658, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_codeobj__29 = (PyObject*)__Pyx_PyCode_New(2, 0, 28, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__28, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_surprise_prediction_algorithms_m_2, __pyx_n_s_sgd, 658, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__29)) __PYX_ERR(0, 658, __pyx_L1_error)
 659: 
 660:         # user and item factors
 661:         cdef np.ndarray[np.double_t, ndim=2] pu
 662:         cdef np.ndarray[np.double_t, ndim=2] qi
 663: 
 664:         # user and item biases
 665:         cdef np.ndarray[np.double_t] bu
 666:         cdef np.ndarray[np.double_t] bi
 667: 
 668:         # auxiliary matrices used in optimization process
 669:         cdef np.ndarray[np.double_t, ndim=2] user_num
 670:         cdef np.ndarray[np.double_t, ndim=2] user_denom
 671:         cdef np.ndarray[np.double_t, ndim=2] item_num
 672:         cdef np.ndarray[np.double_t, ndim=2] item_denom
 673: 
 674:         cdef int u, i, f
 675:         cdef double r, est, l, dot, err
+676:         cdef double reg_pu = self.reg_pu
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_pu); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 676, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_2 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 676, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_reg_pu = __pyx_t_2;
+677:         cdef double reg_qi = self.reg_qi
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_qi); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 677, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_2 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 677, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_reg_qi = __pyx_t_2;
+678:         cdef double reg_bu = self.reg_bu
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_bu); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 678, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_2 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 678, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_reg_bu = __pyx_t_2;
+679:         cdef double reg_bi = self.reg_bi
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_reg_bi); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 679, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_2 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 679, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_reg_bi = __pyx_t_2;
+680:         cdef double lr_bu = self.lr_bu
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_bu); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 680, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_2 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 680, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_lr_bu = __pyx_t_2;
+681:         cdef double lr_bi = self.lr_bi
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_lr_bi); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 681, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_2 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 681, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_lr_bi = __pyx_t_2;
+682:         cdef double global_mean = self.trainset.global_mean
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 682, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_global_mean); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 682, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_2 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_2 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 682, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_global_mean = __pyx_t_2;
 683: 
 684:         # Randomly initialize user and item factors
+685:         rng = get_rng(self.random_state)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_get_rng); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 685, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_random_state); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 685, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_5 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_1, function);
    }
  }
  __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 685, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_rng = __pyx_t_3;
  __pyx_t_3 = 0;
+686:         pu = rng.uniform(self.init_low, self.init_high,
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_rng, __pyx_n_s_uniform); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 686, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_low); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 686, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_high); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 686, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 686, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_4);
  PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4);
  __pyx_t_1 = 0;
  __pyx_t_4 = 0;
/* … */
  __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 686, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 686, __pyx_L1_error)
  __pyx_t_8 = ((PyArrayObject *)__pyx_t_7);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_pu.rcbuffer->pybuffer);
    __pyx_t_9 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_pu.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
    if (unlikely(__pyx_t_9 < 0)) {
      PyErr_Fetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_pu.rcbuffer->pybuffer, (PyObject*)__pyx_v_pu, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_12);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
      }
      __pyx_t_10 = __pyx_t_11 = __pyx_t_12 = 0;
    }
    __pyx_pybuffernd_pu.diminfo[0].strides = __pyx_pybuffernd_pu.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_pu.diminfo[0].shape = __pyx_pybuffernd_pu.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_pu.diminfo[1].strides = __pyx_pybuffernd_pu.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_pu.diminfo[1].shape = __pyx_pybuffernd_pu.rcbuffer->pybuffer.shape[1];
    if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 686, __pyx_L1_error)
  }
  __pyx_t_8 = 0;
  __pyx_v_pu = ((PyArrayObject *)__pyx_t_7);
  __pyx_t_7 = 0;
+687:                          size=(trainset.n_users, self.n_factors))
  __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 687, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_users); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 687, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 687, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 687, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_6);
  PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_6);
  __pyx_t_1 = 0;
  __pyx_t_6 = 0;
  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_size, __pyx_t_7) < 0) __PYX_ERR(0, 687, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+688:         qi = rng.uniform(self.init_low, self.init_high,
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_rng, __pyx_n_s_uniform); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 688, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_low); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 688, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_init_high); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 688, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 688, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_4);
  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_5);
  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_5);
  __pyx_t_4 = 0;
  __pyx_t_5 = 0;
/* … */
  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_3, __pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 688, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 688, __pyx_L1_error)
  __pyx_t_13 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_qi.rcbuffer->pybuffer);
    __pyx_t_9 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_qi.rcbuffer->pybuffer, (PyObject*)__pyx_t_13, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
    if (unlikely(__pyx_t_9 < 0)) {
      PyErr_Fetch(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_qi.rcbuffer->pybuffer, (PyObject*)__pyx_v_qi, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_10);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_12, __pyx_t_11, __pyx_t_10);
      }
      __pyx_t_12 = __pyx_t_11 = __pyx_t_10 = 0;
    }
    __pyx_pybuffernd_qi.diminfo[0].strides = __pyx_pybuffernd_qi.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_qi.diminfo[0].shape = __pyx_pybuffernd_qi.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_qi.diminfo[1].strides = __pyx_pybuffernd_qi.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_qi.diminfo[1].shape = __pyx_pybuffernd_qi.rcbuffer->pybuffer.shape[1];
    if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 688, __pyx_L1_error)
  }
  __pyx_t_13 = 0;
  __pyx_v_qi = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+689:                          size=(trainset.n_items, self.n_factors))
  __pyx_t_5 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 689, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_items); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 689, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 689, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 689, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_4);
  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_6);
  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_6);
  __pyx_t_4 = 0;
  __pyx_t_6 = 0;
  if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_size, __pyx_t_1) < 0) __PYX_ERR(0, 689, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 690: 
+691:         bu = np.zeros(trainset.n_users, np.double)
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 691, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_zeros); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 691, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_users); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 691, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_np); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 691, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_double); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 691, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_7 = NULL;
  __pyx_t_9 = 0;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_7)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_7);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
      __pyx_t_9 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_3)) {
    PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_t_5, __pyx_t_6};
    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_9, 2+__pyx_t_9); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 691, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
    PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_t_5, __pyx_t_6};
    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_9, 2+__pyx_t_9); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 691, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else
  #endif
  {
    __pyx_t_4 = PyTuple_New(2+__pyx_t_9); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 691, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    if (__pyx_t_7) {
      __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_7); __pyx_t_7 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_5);
    PyTuple_SET_ITEM(__pyx_t_4, 0+__pyx_t_9, __pyx_t_5);
    __Pyx_GIVEREF(__pyx_t_6);
    PyTuple_SET_ITEM(__pyx_t_4, 1+__pyx_t_9, __pyx_t_6);
    __pyx_t_5 = 0;
    __pyx_t_6 = 0;
    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_4, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 691, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 691, __pyx_L1_error)
  __pyx_t_14 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bu.rcbuffer->pybuffer);
    __pyx_t_9 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bu.rcbuffer->pybuffer, (PyObject*)__pyx_t_14, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_9 < 0)) {
      PyErr_Fetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bu.rcbuffer->pybuffer, (PyObject*)__pyx_v_bu, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_12);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
      }
      __pyx_t_10 = __pyx_t_11 = __pyx_t_12 = 0;
    }
    __pyx_pybuffernd_bu.diminfo[0].strides = __pyx_pybuffernd_bu.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_bu.diminfo[0].shape = __pyx_pybuffernd_bu.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 691, __pyx_L1_error)
  }
  __pyx_t_14 = 0;
  __pyx_v_bu = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+692:         bi = np.zeros(trainset.n_items, np.double)
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 692, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_zeros); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 692, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_items); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 692, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_np); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 692, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_double); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 692, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_6 = NULL;
  __pyx_t_9 = 0;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_6)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
      __pyx_t_9 = 1;
    }
  }
  #if CYTHON_FAST_PYCALL
  if (PyFunction_Check(__pyx_t_4)) {
    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_5};
    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_9, 2+__pyx_t_9); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 692, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  } else
  #endif
  #if CYTHON_FAST_PYCCALL
  if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_5};
    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_9, 2+__pyx_t_9); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 692, __pyx_L1_error)
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  } else
  #endif
  {
    __pyx_t_7 = PyTuple_New(2+__pyx_t_9); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 692, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    if (__pyx_t_6) {
      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_6); __pyx_t_6 = NULL;
    }
    __Pyx_GIVEREF(__pyx_t_3);
    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_9, __pyx_t_3);
    __Pyx_GIVEREF(__pyx_t_5);
    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_9, __pyx_t_5);
    __pyx_t_3 = 0;
    __pyx_t_5 = 0;
    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 692, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 692, __pyx_L1_error)
  __pyx_t_15 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_bi.rcbuffer->pybuffer);
    __pyx_t_9 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bi.rcbuffer->pybuffer, (PyObject*)__pyx_t_15, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_9 < 0)) {
      PyErr_Fetch(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_bi.rcbuffer->pybuffer, (PyObject*)__pyx_v_bi, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_10);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_12, __pyx_t_11, __pyx_t_10);
      }
      __pyx_t_12 = __pyx_t_11 = __pyx_t_10 = 0;
    }
    __pyx_pybuffernd_bi.diminfo[0].strides = __pyx_pybuffernd_bi.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_bi.diminfo[0].shape = __pyx_pybuffernd_bi.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 692, __pyx_L1_error)
  }
  __pyx_t_15 = 0;
  __pyx_v_bi = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
 693: 
+694:         if not self.biased:
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_biased); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 694, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_16 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_16 < 0)) __PYX_ERR(0, 694, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_17 = ((!__pyx_t_16) != 0);
  if (__pyx_t_17) {
/* … */
  }
+695:             global_mean = 0
    __pyx_v_global_mean = 0.0;
 696: 
+697:         for current_epoch in range(self.n_epochs):
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_range); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 697, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_epochs); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 697, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_5 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_7);
  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 697, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
    __pyx_t_4 = __pyx_t_1; __Pyx_INCREF(__pyx_t_4); __pyx_t_18 = 0;
    __pyx_t_19 = NULL;
  } else {
    __pyx_t_18 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 697, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_19 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 697, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    if (likely(!__pyx_t_19)) {
      if (likely(PyList_CheckExact(__pyx_t_4))) {
        if (__pyx_t_18 >= PyList_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_18); __Pyx_INCREF(__pyx_t_1); __pyx_t_18++; if (unlikely(0 < 0)) __PYX_ERR(0, 697, __pyx_L1_error)
        #else
        __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_18); __pyx_t_18++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 697, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
      } else {
        if (__pyx_t_18 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_18); __Pyx_INCREF(__pyx_t_1); __pyx_t_18++; if (unlikely(0 < 0)) __PYX_ERR(0, 697, __pyx_L1_error)
        #else
        __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_18); __pyx_t_18++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 697, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
      }
    } else {
      __pyx_t_1 = __pyx_t_19(__pyx_t_4);
      if (unlikely(!__pyx_t_1)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 697, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_XDECREF_SET(__pyx_v_current_epoch, __pyx_t_1);
    __pyx_t_1 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 698: 
+699:             if self.verbose:
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_verbose); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 699, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_17 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_17 < 0)) __PYX_ERR(0, 699, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (__pyx_t_17) {
/* … */
    }
+700:                 print("Processing epoch {}".format(current_epoch))
      __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Processing_epoch, __pyx_n_s_format); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 700, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __pyx_t_5 = NULL;
      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_7);
        if (likely(__pyx_t_5)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
          __Pyx_INCREF(__pyx_t_5);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_7, function);
        }
      }
      __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_5, __pyx_v_current_epoch) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_current_epoch);
      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 700, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_t_7 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_t_1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 700, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 701: 
 702:             # (re)initialize nums and denoms to zero
+703:             user_num = np.zeros((trainset.n_users, self.n_factors))
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 703, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 703, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_users); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 703, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 703, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 703, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_3);
    PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_3);
    __pyx_t_1 = 0;
    __pyx_t_3 = 0;
    __pyx_t_3 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_5);
      if (likely(__pyx_t_3)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_5, function);
      }
    }
    __pyx_t_7 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_3, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 703, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 703, __pyx_L1_error)
    __pyx_t_20 = ((PyArrayObject *)__pyx_t_7);
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_user_num.rcbuffer->pybuffer);
      __pyx_t_9 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_user_num.rcbuffer->pybuffer, (PyObject*)__pyx_t_20, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_9 < 0)) {
        PyErr_Fetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_user_num.rcbuffer->pybuffer, (PyObject*)__pyx_v_user_num, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_12);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
        }
        __pyx_t_10 = __pyx_t_11 = __pyx_t_12 = 0;
      }
      __pyx_pybuffernd_user_num.diminfo[0].strides = __pyx_pybuffernd_user_num.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_user_num.diminfo[0].shape = __pyx_pybuffernd_user_num.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_user_num.diminfo[1].strides = __pyx_pybuffernd_user_num.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_user_num.diminfo[1].shape = __pyx_pybuffernd_user_num.rcbuffer->pybuffer.shape[1];
      if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 703, __pyx_L1_error)
    }
    __pyx_t_20 = 0;
    __Pyx_XDECREF_SET(__pyx_v_user_num, ((PyArrayObject *)__pyx_t_7));
    __pyx_t_7 = 0;
+704:             user_denom = np.zeros((trainset.n_users, self.n_factors))
    __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 704, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_zeros); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 704, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_users); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 704, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 704, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 704, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_5);
    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5);
    __Pyx_GIVEREF(__pyx_t_3);
    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3);
    __pyx_t_5 = 0;
    __pyx_t_3 = 0;
    __pyx_t_3 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_6);
      if (likely(__pyx_t_3)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_6, function);
      }
    }
    __pyx_t_7 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_3, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_1);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 704, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 704, __pyx_L1_error)
    __pyx_t_21 = ((PyArrayObject *)__pyx_t_7);
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_user_denom.rcbuffer->pybuffer);
      __pyx_t_9 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_user_denom.rcbuffer->pybuffer, (PyObject*)__pyx_t_21, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_9 < 0)) {
        PyErr_Fetch(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_user_denom.rcbuffer->pybuffer, (PyObject*)__pyx_v_user_denom, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_10);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_12, __pyx_t_11, __pyx_t_10);
        }
        __pyx_t_12 = __pyx_t_11 = __pyx_t_10 = 0;
      }
      __pyx_pybuffernd_user_denom.diminfo[0].strides = __pyx_pybuffernd_user_denom.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_user_denom.diminfo[0].shape = __pyx_pybuffernd_user_denom.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_user_denom.diminfo[1].strides = __pyx_pybuffernd_user_denom.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_user_denom.diminfo[1].shape = __pyx_pybuffernd_user_denom.rcbuffer->pybuffer.shape[1];
      if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 704, __pyx_L1_error)
    }
    __pyx_t_21 = 0;
    __Pyx_XDECREF_SET(__pyx_v_user_denom, ((PyArrayObject *)__pyx_t_7));
    __pyx_t_7 = 0;
+705:             item_num = np.zeros((trainset.n_items, self.n_factors))
    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_np); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 705, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_zeros); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 705, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_items); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 705, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 705, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 705, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_GIVEREF(__pyx_t_6);
    PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_6);
    __Pyx_GIVEREF(__pyx_t_3);
    PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_3);
    __pyx_t_6 = 0;
    __pyx_t_3 = 0;
    __pyx_t_3 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1);
      if (likely(__pyx_t_3)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_1, function);
      }
    }
    __pyx_t_7 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_3, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 705, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 705, __pyx_L1_error)
    __pyx_t_22 = ((PyArrayObject *)__pyx_t_7);
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_item_num.rcbuffer->pybuffer);
      __pyx_t_9 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_item_num.rcbuffer->pybuffer, (PyObject*)__pyx_t_22, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_9 < 0)) {
        PyErr_Fetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_item_num.rcbuffer->pybuffer, (PyObject*)__pyx_v_item_num, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_12);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
        }
        __pyx_t_10 = __pyx_t_11 = __pyx_t_12 = 0;
      }
      __pyx_pybuffernd_item_num.diminfo[0].strides = __pyx_pybuffernd_item_num.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_item_num.diminfo[0].shape = __pyx_pybuffernd_item_num.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_item_num.diminfo[1].strides = __pyx_pybuffernd_item_num.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_item_num.diminfo[1].shape = __pyx_pybuffernd_item_num.rcbuffer->pybuffer.shape[1];
      if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 705, __pyx_L1_error)
    }
    __pyx_t_22 = 0;
    __Pyx_XDECREF_SET(__pyx_v_item_num, ((PyArrayObject *)__pyx_t_7));
    __pyx_t_7 = 0;
+706:             item_denom = np.zeros((trainset.n_items, self.n_factors))
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 706, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 706, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_n_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 706, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 706, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 706, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_3);
    PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_3);
    __pyx_t_1 = 0;
    __pyx_t_3 = 0;
    __pyx_t_3 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_5);
      if (likely(__pyx_t_3)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_5, function);
      }
    }
    __pyx_t_7 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_3, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 706, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (!(likely(((__pyx_t_7) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_7, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 706, __pyx_L1_error)
    __pyx_t_23 = ((PyArrayObject *)__pyx_t_7);
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_item_denom.rcbuffer->pybuffer);
      __pyx_t_9 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_item_denom.rcbuffer->pybuffer, (PyObject*)__pyx_t_23, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_9 < 0)) {
        PyErr_Fetch(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_item_denom.rcbuffer->pybuffer, (PyObject*)__pyx_v_item_denom, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11); Py_XDECREF(__pyx_t_10);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_12, __pyx_t_11, __pyx_t_10);
        }
        __pyx_t_12 = __pyx_t_11 = __pyx_t_10 = 0;
      }
      __pyx_pybuffernd_item_denom.diminfo[0].strides = __pyx_pybuffernd_item_denom.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_item_denom.diminfo[0].shape = __pyx_pybuffernd_item_denom.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_item_denom.diminfo[1].strides = __pyx_pybuffernd_item_denom.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_item_denom.diminfo[1].shape = __pyx_pybuffernd_item_denom.rcbuffer->pybuffer.shape[1];
      if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 706, __pyx_L1_error)
    }
    __pyx_t_23 = 0;
    __Pyx_XDECREF_SET(__pyx_v_item_denom, ((PyArrayObject *)__pyx_t_7));
    __pyx_t_7 = 0;
 707: 
 708:             # Compute numerators and denominators for users and items factors
+709:             for u, i, r in trainset.all_ratings():
    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_all_ratings); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 709, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_6 = NULL;
    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
      if (likely(__pyx_t_6)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
        __Pyx_INCREF(__pyx_t_6);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_5, function);
      }
    }
    __pyx_t_7 = (__pyx_t_6) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6) : __Pyx_PyObject_CallNoArg(__pyx_t_5);
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 709, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (likely(PyList_CheckExact(__pyx_t_7)) || PyTuple_CheckExact(__pyx_t_7)) {
      __pyx_t_5 = __pyx_t_7; __Pyx_INCREF(__pyx_t_5); __pyx_t_24 = 0;
      __pyx_t_25 = NULL;
    } else {
      __pyx_t_24 = -1; __pyx_t_5 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 709, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __pyx_t_25 = Py_TYPE(__pyx_t_5)->tp_iternext; if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 709, __pyx_L1_error)
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    for (;;) {
      if (likely(!__pyx_t_25)) {
        if (likely(PyList_CheckExact(__pyx_t_5))) {
          if (__pyx_t_24 >= PyList_GET_SIZE(__pyx_t_5)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_7 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_24); __Pyx_INCREF(__pyx_t_7); __pyx_t_24++; if (unlikely(0 < 0)) __PYX_ERR(0, 709, __pyx_L1_error)
          #else
          __pyx_t_7 = PySequence_ITEM(__pyx_t_5, __pyx_t_24); __pyx_t_24++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 709, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_7);
          #endif
        } else {
          if (__pyx_t_24 >= PyTuple_GET_SIZE(__pyx_t_5)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_7 = PyTuple_GET_ITEM(__pyx_t_5, __pyx_t_24); __Pyx_INCREF(__pyx_t_7); __pyx_t_24++; if (unlikely(0 < 0)) __PYX_ERR(0, 709, __pyx_L1_error)
          #else
          __pyx_t_7 = PySequence_ITEM(__pyx_t_5, __pyx_t_24); __pyx_t_24++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 709, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_7);
          #endif
        }
      } else {
        __pyx_t_7 = __pyx_t_25(__pyx_t_5);
        if (unlikely(!__pyx_t_7)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 709, __pyx_L1_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_7);
      }
      if ((likely(PyTuple_CheckExact(__pyx_t_7))) || (PyList_CheckExact(__pyx_t_7))) {
        PyObject* sequence = __pyx_t_7;
        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
        if (unlikely(size != 3)) {
          if (size > 3) __Pyx_RaiseTooManyValuesError(3);
          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
          __PYX_ERR(0, 709, __pyx_L1_error)
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        if (likely(PyTuple_CheckExact(sequence))) {
          __pyx_t_6 = PyTuple_GET_ITEM(sequence, 0); 
          __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
          __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2); 
        } else {
          __pyx_t_6 = PyList_GET_ITEM(sequence, 0); 
          __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
          __pyx_t_1 = PyList_GET_ITEM(sequence, 2); 
        }
        __Pyx_INCREF(__pyx_t_6);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(__pyx_t_1);
        #else
        __pyx_t_6 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 709, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 709, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __pyx_t_1 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 709, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      } else {
        Py_ssize_t index = -1;
        __pyx_t_26 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_26)) __PYX_ERR(0, 709, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_26);
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __pyx_t_27 = Py_TYPE(__pyx_t_26)->tp_iternext;
        index = 0; __pyx_t_6 = __pyx_t_27(__pyx_t_26); if (unlikely(!__pyx_t_6)) goto __pyx_L9_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_6);
        index = 1; __pyx_t_3 = __pyx_t_27(__pyx_t_26); if (unlikely(!__pyx_t_3)) goto __pyx_L9_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_3);
        index = 2; __pyx_t_1 = __pyx_t_27(__pyx_t_26); if (unlikely(!__pyx_t_1)) goto __pyx_L9_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_1);
        if (__Pyx_IternextUnpackEndCheck(__pyx_t_27(__pyx_t_26), 3) < 0) __PYX_ERR(0, 709, __pyx_L1_error)
        __pyx_t_27 = NULL;
        __Pyx_DECREF(__pyx_t_26); __pyx_t_26 = 0;
        goto __pyx_L10_unpacking_done;
        __pyx_L9_unpacking_failed:;
        __Pyx_DECREF(__pyx_t_26); __pyx_t_26 = 0;
        __pyx_t_27 = NULL;
        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
        __PYX_ERR(0, 709, __pyx_L1_error)
        __pyx_L10_unpacking_done:;
      }
      __pyx_t_9 = __Pyx_PyInt_As_int(__pyx_t_6); if (unlikely((__pyx_t_9 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 709, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __pyx_t_28 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_28 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 709, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_2 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_2 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 709, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_v_u = __pyx_t_9;
      __pyx_v_i = __pyx_t_28;
      __pyx_v_r = __pyx_t_2;
/* … */
    }
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
 710: 
 711:                 # compute current estimation and error
+712:                 dot = 0  # <q_i, p_u>
      __pyx_v_dot = 0.0;
+713:                 for f in range(self.n_factors):
      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_range); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 713, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 713, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_6 = NULL;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1);
        if (likely(__pyx_t_6)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
          __Pyx_INCREF(__pyx_t_6);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_1, function);
        }
      }
      __pyx_t_7 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_3);
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 713, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (likely(PyList_CheckExact(__pyx_t_7)) || PyTuple_CheckExact(__pyx_t_7)) {
        __pyx_t_1 = __pyx_t_7; __Pyx_INCREF(__pyx_t_1); __pyx_t_29 = 0;
        __pyx_t_30 = NULL;
      } else {
        __pyx_t_29 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 713, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __pyx_t_30 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_30)) __PYX_ERR(0, 713, __pyx_L1_error)
      }
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      for (;;) {
        if (likely(!__pyx_t_30)) {
          if (likely(PyList_CheckExact(__pyx_t_1))) {
            if (__pyx_t_29 >= PyList_GET_SIZE(__pyx_t_1)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_7 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_29); __Pyx_INCREF(__pyx_t_7); __pyx_t_29++; if (unlikely(0 < 0)) __PYX_ERR(0, 713, __pyx_L1_error)
            #else
            __pyx_t_7 = PySequence_ITEM(__pyx_t_1, __pyx_t_29); __pyx_t_29++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 713, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_7);
            #endif
          } else {
            if (__pyx_t_29 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_7 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_29); __Pyx_INCREF(__pyx_t_7); __pyx_t_29++; if (unlikely(0 < 0)) __PYX_ERR(0, 713, __pyx_L1_error)
            #else
            __pyx_t_7 = PySequence_ITEM(__pyx_t_1, __pyx_t_29); __pyx_t_29++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 713, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_7);
            #endif
          }
        } else {
          __pyx_t_7 = __pyx_t_30(__pyx_t_1);
          if (unlikely(!__pyx_t_7)) {
            PyObject* exc_type = PyErr_Occurred();
            if (exc_type) {
              if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
              else __PYX_ERR(0, 713, __pyx_L1_error)
            }
            break;
          }
          __Pyx_GOTREF(__pyx_t_7);
        }
        __pyx_t_28 = __Pyx_PyInt_As_int(__pyx_t_7); if (unlikely((__pyx_t_28 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 713, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __pyx_v_f = __pyx_t_28;
/* … */
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+714:                     dot += qi[i, f] * pu[u, f]
        __pyx_t_31 = __pyx_v_i;
        __pyx_t_32 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_32 < 0) {
          __pyx_t_32 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_32 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_32 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 714, __pyx_L1_error)
        }
        __pyx_t_33 = __pyx_v_u;
        __pyx_t_34 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 714, __pyx_L1_error)
        }
        __pyx_v_dot = (__pyx_v_dot + ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_32, __pyx_pybuffernd_qi.diminfo[1].strides)) * (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_pu.diminfo[1].strides))));
+715:                 est = global_mean + bu[u] + bi[i] + dot
      __pyx_t_34 = __pyx_v_u;
      __pyx_t_28 = -1;
      if (__pyx_t_34 < 0) {
        __pyx_t_34 += __pyx_pybuffernd_bu.diminfo[0].shape;
        if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 0;
      } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_bu.diminfo[0].shape)) __pyx_t_28 = 0;
      if (unlikely(__pyx_t_28 != -1)) {
        __Pyx_RaiseBufferIndexError(__pyx_t_28);
        __PYX_ERR(0, 715, __pyx_L1_error)
      }
      __pyx_t_33 = __pyx_v_i;
      __pyx_t_28 = -1;
      if (__pyx_t_33 < 0) {
        __pyx_t_33 += __pyx_pybuffernd_bi.diminfo[0].shape;
        if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
      } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_bi.diminfo[0].shape)) __pyx_t_28 = 0;
      if (unlikely(__pyx_t_28 != -1)) {
        __Pyx_RaiseBufferIndexError(__pyx_t_28);
        __PYX_ERR(0, 715, __pyx_L1_error)
      }
      __pyx_v_est = (((__pyx_v_global_mean + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bu.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_bu.diminfo[0].strides))) + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bi.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_bi.diminfo[0].strides))) + __pyx_v_dot);
+716:                 err = r - est
      __pyx_v_err = (__pyx_v_r - __pyx_v_est);
 717: 
 718:                 # update biases
+719:                 if self.biased:
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_biased); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 719, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_17 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_17 < 0)) __PYX_ERR(0, 719, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (__pyx_t_17) {
/* … */
      }
+720:                     bu[u] += lr_bu * (err - reg_bu * bu[u])
        __pyx_t_33 = __pyx_v_u;
        __pyx_t_28 = -1;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_bu.diminfo[0].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_bu.diminfo[0].shape)) __pyx_t_28 = 0;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 720, __pyx_L1_error)
        }
        __pyx_t_34 = __pyx_v_u;
        __pyx_t_28 = -1;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_bu.diminfo[0].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_bu.diminfo[0].shape)) __pyx_t_28 = 0;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 720, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bu.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_bu.diminfo[0].strides) += (__pyx_v_lr_bu * (__pyx_v_err - (__pyx_v_reg_bu * (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bu.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_bu.diminfo[0].strides)))));
+721:                     bi[i] += lr_bi * (err - reg_bi * bi[i])
        __pyx_t_33 = __pyx_v_i;
        __pyx_t_28 = -1;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_bi.diminfo[0].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_bi.diminfo[0].shape)) __pyx_t_28 = 0;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 721, __pyx_L1_error)
        }
        __pyx_t_34 = __pyx_v_i;
        __pyx_t_28 = -1;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_bi.diminfo[0].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_bi.diminfo[0].shape)) __pyx_t_28 = 0;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 721, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bi.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_bi.diminfo[0].strides) += (__pyx_v_lr_bi * (__pyx_v_err - (__pyx_v_reg_bi * (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_bi.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_bi.diminfo[0].strides)))));
 722: 
 723:                 # compute numerators and denominators
+724:                 for f in range(self.n_factors):
      __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_range); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 724, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 724, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_6 = NULL;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) {
        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_7);
        if (likely(__pyx_t_6)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
          __Pyx_INCREF(__pyx_t_6);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_7, function);
        }
      }
      __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_6, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_3);
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 724, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
        __pyx_t_7 = __pyx_t_1; __Pyx_INCREF(__pyx_t_7); __pyx_t_29 = 0;
        __pyx_t_30 = NULL;
      } else {
        __pyx_t_29 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 724, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        __pyx_t_30 = Py_TYPE(__pyx_t_7)->tp_iternext; if (unlikely(!__pyx_t_30)) __PYX_ERR(0, 724, __pyx_L1_error)
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      for (;;) {
        if (likely(!__pyx_t_30)) {
          if (likely(PyList_CheckExact(__pyx_t_7))) {
            if (__pyx_t_29 >= PyList_GET_SIZE(__pyx_t_7)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_1 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_29); __Pyx_INCREF(__pyx_t_1); __pyx_t_29++; if (unlikely(0 < 0)) __PYX_ERR(0, 724, __pyx_L1_error)
            #else
            __pyx_t_1 = PySequence_ITEM(__pyx_t_7, __pyx_t_29); __pyx_t_29++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 724, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_1);
            #endif
          } else {
            if (__pyx_t_29 >= PyTuple_GET_SIZE(__pyx_t_7)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_29); __Pyx_INCREF(__pyx_t_1); __pyx_t_29++; if (unlikely(0 < 0)) __PYX_ERR(0, 724, __pyx_L1_error)
            #else
            __pyx_t_1 = PySequence_ITEM(__pyx_t_7, __pyx_t_29); __pyx_t_29++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 724, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_1);
            #endif
          }
        } else {
          __pyx_t_1 = __pyx_t_30(__pyx_t_7);
          if (unlikely(!__pyx_t_1)) {
            PyObject* exc_type = PyErr_Occurred();
            if (exc_type) {
              if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
              else __PYX_ERR(0, 724, __pyx_L1_error)
            }
            break;
          }
          __Pyx_GOTREF(__pyx_t_1);
        }
        __pyx_t_28 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_28 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 724, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_v_f = __pyx_t_28;
/* … */
      }
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+725:                     user_num[u, f] += qi[i, f] * r
        __pyx_t_33 = __pyx_v_i;
        __pyx_t_34 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 725, __pyx_L1_error)
        }
        __pyx_t_32 = __pyx_v_u;
        __pyx_t_31 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_32 < 0) {
          __pyx_t_32 += __pyx_pybuffernd_user_num.diminfo[0].shape;
          if (unlikely(__pyx_t_32 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_32 >= __pyx_pybuffernd_user_num.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_user_num.diminfo[1].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_user_num.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 725, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_user_num.rcbuffer->pybuffer.buf, __pyx_t_32, __pyx_pybuffernd_user_num.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_user_num.diminfo[1].strides) += ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_qi.diminfo[1].strides)) * __pyx_v_r);
+726:                     user_denom[u, f] += qi[i, f] * est
        __pyx_t_34 = __pyx_v_i;
        __pyx_t_33 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 726, __pyx_L1_error)
        }
        __pyx_t_31 = __pyx_v_u;
        __pyx_t_32 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_user_denom.diminfo[0].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_user_denom.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_32 < 0) {
          __pyx_t_32 += __pyx_pybuffernd_user_denom.diminfo[1].shape;
          if (unlikely(__pyx_t_32 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_32 >= __pyx_pybuffernd_user_denom.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 726, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_user_denom.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_user_denom.diminfo[0].strides, __pyx_t_32, __pyx_pybuffernd_user_denom.diminfo[1].strides) += ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_qi.diminfo[1].strides)) * __pyx_v_est);
+727:                     item_num[i, f] += pu[u, f] * r
        __pyx_t_33 = __pyx_v_u;
        __pyx_t_34 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 727, __pyx_L1_error)
        }
        __pyx_t_32 = __pyx_v_i;
        __pyx_t_31 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_32 < 0) {
          __pyx_t_32 += __pyx_pybuffernd_item_num.diminfo[0].shape;
          if (unlikely(__pyx_t_32 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_32 >= __pyx_pybuffernd_item_num.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_item_num.diminfo[1].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_item_num.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 727, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_item_num.rcbuffer->pybuffer.buf, __pyx_t_32, __pyx_pybuffernd_item_num.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_item_num.diminfo[1].strides) += ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_pu.diminfo[1].strides)) * __pyx_v_r);
+728:                     item_denom[i, f] += pu[u, f] * est
        __pyx_t_34 = __pyx_v_u;
        __pyx_t_33 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 728, __pyx_L1_error)
        }
        __pyx_t_31 = __pyx_v_i;
        __pyx_t_32 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_item_denom.diminfo[0].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_item_denom.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_32 < 0) {
          __pyx_t_32 += __pyx_pybuffernd_item_denom.diminfo[1].shape;
          if (unlikely(__pyx_t_32 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_32 >= __pyx_pybuffernd_item_denom.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 728, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_item_denom.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_item_denom.diminfo[0].strides, __pyx_t_32, __pyx_pybuffernd_item_denom.diminfo[1].strides) += ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_pu.diminfo[1].strides)) * __pyx_v_est);
 729: 
 730:             # Update user factors
+731:             for u in trainset.all_users():
    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_all_users); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 731, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_1 = NULL;
    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_7);
      if (likely(__pyx_t_1)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
        __Pyx_INCREF(__pyx_t_1);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_7, function);
      }
    }
    __pyx_t_5 = (__pyx_t_1) ? __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_1) : __Pyx_PyObject_CallNoArg(__pyx_t_7);
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 731, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (likely(PyList_CheckExact(__pyx_t_5)) || PyTuple_CheckExact(__pyx_t_5)) {
      __pyx_t_7 = __pyx_t_5; __Pyx_INCREF(__pyx_t_7); __pyx_t_24 = 0;
      __pyx_t_25 = NULL;
    } else {
      __pyx_t_24 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 731, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __pyx_t_25 = Py_TYPE(__pyx_t_7)->tp_iternext; if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 731, __pyx_L1_error)
    }
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    for (;;) {
      if (likely(!__pyx_t_25)) {
        if (likely(PyList_CheckExact(__pyx_t_7))) {
          if (__pyx_t_24 >= PyList_GET_SIZE(__pyx_t_7)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_5 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_24); __Pyx_INCREF(__pyx_t_5); __pyx_t_24++; if (unlikely(0 < 0)) __PYX_ERR(0, 731, __pyx_L1_error)
          #else
          __pyx_t_5 = PySequence_ITEM(__pyx_t_7, __pyx_t_24); __pyx_t_24++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 731, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_5);
          #endif
        } else {
          if (__pyx_t_24 >= PyTuple_GET_SIZE(__pyx_t_7)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_24); __Pyx_INCREF(__pyx_t_5); __pyx_t_24++; if (unlikely(0 < 0)) __PYX_ERR(0, 731, __pyx_L1_error)
          #else
          __pyx_t_5 = PySequence_ITEM(__pyx_t_7, __pyx_t_24); __pyx_t_24++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 731, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_5);
          #endif
        }
      } else {
        __pyx_t_5 = __pyx_t_25(__pyx_t_7);
        if (unlikely(!__pyx_t_5)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 731, __pyx_L1_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_5);
      }
      __pyx_t_28 = __Pyx_PyInt_As_int(__pyx_t_5); if (unlikely((__pyx_t_28 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 731, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
      __pyx_v_u = __pyx_t_28;
/* … */
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+732:                 n_ratings = len(trainset.ur[u])
      __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_ur); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 732, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_5, __pyx_v_u, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 732, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
      __pyx_t_29 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_29 == ((Py_ssize_t)-1))) __PYX_ERR(0, 732, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_29); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 732, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_XDECREF_SET(__pyx_v_n_ratings, __pyx_t_1);
      __pyx_t_1 = 0;
+733:                 for f in range(self.n_factors):
      __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_range); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 733, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 733, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_6 = NULL;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
        if (likely(__pyx_t_6)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
          __Pyx_INCREF(__pyx_t_6);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_5, function);
        }
      }
      __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_6, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_3);
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 733, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
      if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
        __pyx_t_5 = __pyx_t_1; __Pyx_INCREF(__pyx_t_5); __pyx_t_29 = 0;
        __pyx_t_30 = NULL;
      } else {
        __pyx_t_29 = -1; __pyx_t_5 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 733, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_5);
        __pyx_t_30 = Py_TYPE(__pyx_t_5)->tp_iternext; if (unlikely(!__pyx_t_30)) __PYX_ERR(0, 733, __pyx_L1_error)
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      for (;;) {
        if (likely(!__pyx_t_30)) {
          if (likely(PyList_CheckExact(__pyx_t_5))) {
            if (__pyx_t_29 >= PyList_GET_SIZE(__pyx_t_5)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_1 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_29); __Pyx_INCREF(__pyx_t_1); __pyx_t_29++; if (unlikely(0 < 0)) __PYX_ERR(0, 733, __pyx_L1_error)
            #else
            __pyx_t_1 = PySequence_ITEM(__pyx_t_5, __pyx_t_29); __pyx_t_29++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 733, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_1);
            #endif
          } else {
            if (__pyx_t_29 >= PyTuple_GET_SIZE(__pyx_t_5)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_5, __pyx_t_29); __Pyx_INCREF(__pyx_t_1); __pyx_t_29++; if (unlikely(0 < 0)) __PYX_ERR(0, 733, __pyx_L1_error)
            #else
            __pyx_t_1 = PySequence_ITEM(__pyx_t_5, __pyx_t_29); __pyx_t_29++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 733, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_1);
            #endif
          }
        } else {
          __pyx_t_1 = __pyx_t_30(__pyx_t_5);
          if (unlikely(!__pyx_t_1)) {
            PyObject* exc_type = PyErr_Occurred();
            if (exc_type) {
              if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
              else __PYX_ERR(0, 733, __pyx_L1_error)
            }
            break;
          }
          __Pyx_GOTREF(__pyx_t_1);
        }
        __pyx_t_28 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_28 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 733, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_v_f = __pyx_t_28;
/* … */
      }
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+734:                     user_denom[u, f] += n_ratings * reg_pu * pu[u, f]
        __pyx_t_1 = PyFloat_FromDouble(__pyx_v_reg_pu); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 734, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __pyx_t_3 = PyNumber_Multiply(__pyx_v_n_ratings, __pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 734, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_t_33 = __pyx_v_u;
        __pyx_t_34 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 734, __pyx_L1_error)
        }
        __pyx_t_1 = PyFloat_FromDouble((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_pu.diminfo[1].strides))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 734, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __pyx_t_6 = PyNumber_Multiply(__pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 734, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_t_35 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_35 == ((npy_double)-1)) && PyErr_Occurred())) __PYX_ERR(0, 734, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        __pyx_t_34 = __pyx_v_u;
        __pyx_t_33 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_user_denom.diminfo[0].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_user_denom.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_user_denom.diminfo[1].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_user_denom.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 734, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_user_denom.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_user_denom.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_user_denom.diminfo[1].strides) += __pyx_t_35;
+735:                     pu[u, f] *= user_num[u, f] / user_denom[u, f]
        __pyx_t_33 = __pyx_v_u;
        __pyx_t_34 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_user_num.diminfo[0].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_user_num.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_user_num.diminfo[1].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_user_num.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 735, __pyx_L1_error)
        }
        __pyx_t_35 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_user_num.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_user_num.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_user_num.diminfo[1].strides));
        __pyx_t_34 = __pyx_v_u;
        __pyx_t_33 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_user_denom.diminfo[0].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_user_denom.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_user_denom.diminfo[1].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_user_denom.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 735, __pyx_L1_error)
        }
        __pyx_t_36 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_user_denom.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_user_denom.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_user_denom.diminfo[1].strides));
        if (unlikely(__pyx_t_36 == 0)) {
          PyErr_SetString(PyExc_ZeroDivisionError, "float division");
          __PYX_ERR(0, 735, __pyx_L1_error)
        }
        __pyx_t_33 = __pyx_v_u;
        __pyx_t_34 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_pu.diminfo[0].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_pu.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_pu.diminfo[1].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_pu.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 735, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_pu.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_pu.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_pu.diminfo[1].strides) *= (__pyx_t_35 / __pyx_t_36);
 736: 
 737:             # Update item factors
+738:             for i in trainset.all_items():
    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_all_items); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 738, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_6 = NULL;
    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
      if (likely(__pyx_t_6)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
        __Pyx_INCREF(__pyx_t_6);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_5, function);
      }
    }
    __pyx_t_7 = (__pyx_t_6) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6) : __Pyx_PyObject_CallNoArg(__pyx_t_5);
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 738, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (likely(PyList_CheckExact(__pyx_t_7)) || PyTuple_CheckExact(__pyx_t_7)) {
      __pyx_t_5 = __pyx_t_7; __Pyx_INCREF(__pyx_t_5); __pyx_t_24 = 0;
      __pyx_t_25 = NULL;
    } else {
      __pyx_t_24 = -1; __pyx_t_5 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 738, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __pyx_t_25 = Py_TYPE(__pyx_t_5)->tp_iternext; if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 738, __pyx_L1_error)
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    for (;;) {
      if (likely(!__pyx_t_25)) {
        if (likely(PyList_CheckExact(__pyx_t_5))) {
          if (__pyx_t_24 >= PyList_GET_SIZE(__pyx_t_5)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_7 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_24); __Pyx_INCREF(__pyx_t_7); __pyx_t_24++; if (unlikely(0 < 0)) __PYX_ERR(0, 738, __pyx_L1_error)
          #else
          __pyx_t_7 = PySequence_ITEM(__pyx_t_5, __pyx_t_24); __pyx_t_24++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 738, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_7);
          #endif
        } else {
          if (__pyx_t_24 >= PyTuple_GET_SIZE(__pyx_t_5)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_7 = PyTuple_GET_ITEM(__pyx_t_5, __pyx_t_24); __Pyx_INCREF(__pyx_t_7); __pyx_t_24++; if (unlikely(0 < 0)) __PYX_ERR(0, 738, __pyx_L1_error)
          #else
          __pyx_t_7 = PySequence_ITEM(__pyx_t_5, __pyx_t_24); __pyx_t_24++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 738, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_7);
          #endif
        }
      } else {
        __pyx_t_7 = __pyx_t_25(__pyx_t_5);
        if (unlikely(!__pyx_t_7)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 738, __pyx_L1_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_7);
      }
      __pyx_t_28 = __Pyx_PyInt_As_int(__pyx_t_7); if (unlikely((__pyx_t_28 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 738, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_v_i = __pyx_t_28;
/* … */
    }
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+739:                 n_ratings = len(trainset.ir[i])
      __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_trainset, __pyx_n_s_ir); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 739, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_7, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 739, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_t_29 = PyObject_Length(__pyx_t_6); if (unlikely(__pyx_t_29 == ((Py_ssize_t)-1))) __PYX_ERR(0, 739, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __pyx_t_6 = PyInt_FromSsize_t(__pyx_t_29); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 739, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_XDECREF_SET(__pyx_v_n_ratings, __pyx_t_6);
      __pyx_t_6 = 0;
+740:                 for f in range(self.n_factors):
      __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_range); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 740, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_n_factors); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 740, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_3 = NULL;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) {
        __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_7);
        if (likely(__pyx_t_3)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
          __Pyx_INCREF(__pyx_t_3);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_7, function);
        }
      }
      __pyx_t_6 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_3, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_1);
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 740, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (likely(PyList_CheckExact(__pyx_t_6)) || PyTuple_CheckExact(__pyx_t_6)) {
        __pyx_t_7 = __pyx_t_6; __Pyx_INCREF(__pyx_t_7); __pyx_t_29 = 0;
        __pyx_t_30 = NULL;
      } else {
        __pyx_t_29 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 740, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        __pyx_t_30 = Py_TYPE(__pyx_t_7)->tp_iternext; if (unlikely(!__pyx_t_30)) __PYX_ERR(0, 740, __pyx_L1_error)
      }
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      for (;;) {
        if (likely(!__pyx_t_30)) {
          if (likely(PyList_CheckExact(__pyx_t_7))) {
            if (__pyx_t_29 >= PyList_GET_SIZE(__pyx_t_7)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_6 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_29); __Pyx_INCREF(__pyx_t_6); __pyx_t_29++; if (unlikely(0 < 0)) __PYX_ERR(0, 740, __pyx_L1_error)
            #else
            __pyx_t_6 = PySequence_ITEM(__pyx_t_7, __pyx_t_29); __pyx_t_29++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 740, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
            #endif
          } else {
            if (__pyx_t_29 >= PyTuple_GET_SIZE(__pyx_t_7)) break;
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_29); __Pyx_INCREF(__pyx_t_6); __pyx_t_29++; if (unlikely(0 < 0)) __PYX_ERR(0, 740, __pyx_L1_error)
            #else
            __pyx_t_6 = PySequence_ITEM(__pyx_t_7, __pyx_t_29); __pyx_t_29++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 740, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
            #endif
          }
        } else {
          __pyx_t_6 = __pyx_t_30(__pyx_t_7);
          if (unlikely(!__pyx_t_6)) {
            PyObject* exc_type = PyErr_Occurred();
            if (exc_type) {
              if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
              else __PYX_ERR(0, 740, __pyx_L1_error)
            }
            break;
          }
          __Pyx_GOTREF(__pyx_t_6);
        }
        __pyx_t_28 = __Pyx_PyInt_As_int(__pyx_t_6); if (unlikely((__pyx_t_28 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 740, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        __pyx_v_f = __pyx_t_28;
/* … */
      }
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+741:                     item_denom[i, f] += n_ratings * reg_qi * qi[i, f]
        __pyx_t_6 = PyFloat_FromDouble(__pyx_v_reg_qi); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 741, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __pyx_t_1 = PyNumber_Multiply(__pyx_v_n_ratings, __pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 741, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        __pyx_t_34 = __pyx_v_i;
        __pyx_t_33 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 741, __pyx_L1_error)
        }
        __pyx_t_6 = PyFloat_FromDouble((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_qi.diminfo[1].strides))); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 741, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __pyx_t_3 = PyNumber_Multiply(__pyx_t_1, __pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 741, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        __pyx_t_36 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_36 == ((npy_double)-1)) && PyErr_Occurred())) __PYX_ERR(0, 741, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __pyx_t_33 = __pyx_v_i;
        __pyx_t_34 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_item_denom.diminfo[0].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_item_denom.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_item_denom.diminfo[1].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_item_denom.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 741, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_item_denom.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_item_denom.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_item_denom.diminfo[1].strides) += __pyx_t_36;
+742:                     qi[i, f] *= item_num[i, f] / item_denom[i, f]
        __pyx_t_34 = __pyx_v_i;
        __pyx_t_33 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_item_num.diminfo[0].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_item_num.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_item_num.diminfo[1].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_item_num.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 742, __pyx_L1_error)
        }
        __pyx_t_36 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_item_num.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_item_num.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_item_num.diminfo[1].strides));
        __pyx_t_33 = __pyx_v_i;
        __pyx_t_34 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_item_denom.diminfo[0].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_item_denom.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_item_denom.diminfo[1].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_item_denom.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 742, __pyx_L1_error)
        }
        __pyx_t_35 = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_item_denom.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_item_denom.diminfo[0].strides, __pyx_t_34, __pyx_pybuffernd_item_denom.diminfo[1].strides));
        if (unlikely(__pyx_t_35 == 0)) {
          PyErr_SetString(PyExc_ZeroDivisionError, "float division");
          __PYX_ERR(0, 742, __pyx_L1_error)
        }
        __pyx_t_34 = __pyx_v_i;
        __pyx_t_33 = __pyx_v_f;
        __pyx_t_28 = -1;
        if (__pyx_t_34 < 0) {
          __pyx_t_34 += __pyx_pybuffernd_qi.diminfo[0].shape;
          if (unlikely(__pyx_t_34 < 0)) __pyx_t_28 = 0;
        } else if (unlikely(__pyx_t_34 >= __pyx_pybuffernd_qi.diminfo[0].shape)) __pyx_t_28 = 0;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_qi.diminfo[1].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_28 = 1;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_qi.diminfo[1].shape)) __pyx_t_28 = 1;
        if (unlikely(__pyx_t_28 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_28);
          __PYX_ERR(0, 742, __pyx_L1_error)
        }
        *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_qi.rcbuffer->pybuffer.buf, __pyx_t_34, __pyx_pybuffernd_qi.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_qi.diminfo[1].strides) *= (__pyx_t_36 / __pyx_t_35);
 743: 
+744:         self.bu = bu
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_bu, ((PyObject *)__pyx_v_bu)) < 0) __PYX_ERR(0, 744, __pyx_L1_error)
+745:         self.bi = bi
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_bi, ((PyObject *)__pyx_v_bi)) < 0) __PYX_ERR(0, 745, __pyx_L1_error)
+746:         self.pu = pu
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_pu, ((PyObject *)__pyx_v_pu)) < 0) __PYX_ERR(0, 746, __pyx_L1_error)
+747:         self.qi = qi
  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_qi, ((PyObject *)__pyx_v_qi)) < 0) __PYX_ERR(0, 747, __pyx_L1_error)
 748: 
+749:     def estimate(self, u, i):
/* Python wrapper */
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_7estimate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_7estimate = {"estimate", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_7estimate, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_7estimate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_self = 0;
  PyObject *__pyx_v_u = 0;
  PyObject *__pyx_v_i = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("estimate (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_u,&__pyx_n_s_i,0};
    PyObject* values[3] = {0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_u)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("estimate", 1, 3, 3, 1); __PYX_ERR(0, 749, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_i)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("estimate", 1, 3, 3, 2); __PYX_ERR(0, 749, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "estimate") < 0)) __PYX_ERR(0, 749, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
    }
    __pyx_v_self = values[0];
    __pyx_v_u = values[1];
    __pyx_v_i = values[2];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("estimate", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 749, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.NMF.estimate", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_6estimate(__pyx_self, __pyx_v_self, __pyx_v_u, __pyx_v_i);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_6estimate(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_u, PyObject *__pyx_v_i) {
  PyObject *__pyx_v_known_user = NULL;
  PyObject *__pyx_v_known_item = NULL;
  PyObject *__pyx_v_est = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("estimate", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_AddTraceback("surprise.prediction_algorithms.matrix_factorization.NMF.estimate", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_known_user);
  __Pyx_XDECREF(__pyx_v_known_item);
  __Pyx_XDECREF(__pyx_v_est);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__30 = PyTuple_Pack(6, __pyx_n_s_self, __pyx_n_s_u, __pyx_n_s_i, __pyx_n_s_known_user, __pyx_n_s_known_item, __pyx_n_s_est); if (unlikely(!__pyx_tuple__30)) __PYX_ERR(0, 749, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__30);
  __Pyx_GIVEREF(__pyx_tuple__30);
/* … */
  __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_8surprise_21prediction_algorithms_20matrix_factorization_3NMF_7estimate, 0, __pyx_n_s_NMF_estimate, NULL, __pyx_n_s_surprise_prediction_algorithms_m, __pyx_d, ((PyObject *)__pyx_codeobj__31)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 749, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (__Pyx_SetNameInClass(__pyx_t_3, __pyx_n_s_estimate, __pyx_t_4) < 0) __PYX_ERR(0, 749, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 750:         # Should we cythonize this as well?
 751: 
+752:         known_user = self.trainset.knows_user(u)
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 752, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_knows_user); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 752, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_2)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_v_u) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_u);
  __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 752, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_known_user = __pyx_t_1;
  __pyx_t_1 = 0;
+753:         known_item = self.trainset.knows_item(i)
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 753, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_knows_item); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 753, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_2, function);
    }
  }
  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_i) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_i);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 753, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_known_item = __pyx_t_1;
  __pyx_t_1 = 0;
 754: 
+755:         if self.biased:
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_biased); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 755, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 755, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (__pyx_t_4) {
/* … */
    goto __pyx_L3;
  }
+756:             est = self.trainset.global_mean
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_trainset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 756, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_global_mean); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 756, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_est = __pyx_t_2;
    __pyx_t_2 = 0;
 757: 
+758:             if known_user:
    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_known_user); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 758, __pyx_L1_error)
    if (__pyx_t_4) {
/* … */
    }
+759:                 est += self.bu[u]
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_bu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 759, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_v_u); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 759, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_est, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 759, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF_SET(__pyx_v_est, __pyx_t_2);
      __pyx_t_2 = 0;
 760: 
+761:             if known_item:
    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_known_item); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 761, __pyx_L1_error)
    if (__pyx_t_4) {
/* … */
    }
+762:                 est += self.bi[i]
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_bi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 762, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_v_i); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 762, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_est, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 762, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF_SET(__pyx_v_est, __pyx_t_2);
      __pyx_t_2 = 0;
 763: 
+764:             if known_user and known_item:
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_known_user); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 764, __pyx_L1_error)
    if (__pyx_t_5) {
    } else {
      __pyx_t_4 = __pyx_t_5;
      goto __pyx_L7_bool_binop_done;
    }
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_known_item); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 764, __pyx_L1_error)
    __pyx_t_4 = __pyx_t_5;
    __pyx_L7_bool_binop_done:;
    if (__pyx_t_4) {
/* … */
    }
+765:                 est += np.dot(self.qi[i], self.pu[u])
      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 765, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_dot); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 765, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_qi); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 765, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_v_i); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 765, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_pu); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 765, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_7 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_v_u); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 765, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = NULL;
      __pyx_t_8 = 0;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3);
        if (likely(__pyx_t_1)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
          __Pyx_INCREF(__pyx_t_1);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_3, function);
          __pyx_t_8 = 1;
        }
      }
      #if CYTHON_FAST_PYCALL
      if (PyFunction_Check(__pyx_t_3)) {
        PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_t_6, __pyx_t_7};
        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 765, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      } else
      #endif
      #if CYTHON_FAST_PYCCALL
      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
        PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_t_6, __pyx_t_7};
        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 765, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      } else
      #endif
      {
        __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 765, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_9);
        if (__pyx_t_1) {
          __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_1); __pyx_t_1 = NULL;
        }
        __Pyx_GIVEREF(__pyx_t_6);
        PyTuple_SET_ITEM(__pyx_t_9, 0+__pyx_t_8, __pyx_t_6);
        __Pyx_GIVEREF(__pyx_t_7);
        PyTuple_SET_ITEM(__pyx_t_9, 1+__pyx_t_8, __pyx_t_7);
        __pyx_t_6 = 0;
        __pyx_t_7 = 0;
        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_9, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 765, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_3 = PyNumber_InPlaceAdd(__pyx_v_est, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 765, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF_SET(__pyx_v_est, __pyx_t_3);
      __pyx_t_3 = 0;
 766: 
 767:         else:
+768:             if known_user and known_item:
  /*else*/ {
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_known_user); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 768, __pyx_L1_error)
    if (__pyx_t_5) {
    } else {
      __pyx_t_4 = __pyx_t_5;
      goto __pyx_L10_bool_binop_done;
    }
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_known_item); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 768, __pyx_L1_error)
    __pyx_t_4 = __pyx_t_5;
    __pyx_L10_bool_binop_done:;
    if (likely(__pyx_t_4)) {
/* … */
      goto __pyx_L9;
    }
+769:                 est = np.dot(self.qi[i], self.pu[u])
      __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 769, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_dot); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 769, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_qi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 769, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_7 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_v_i); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 769, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_pu); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 769, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_t_2, __pyx_v_u); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 769, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = NULL;
      __pyx_t_8 = 0;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) {
        __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_9);
        if (likely(__pyx_t_2)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9);
          __Pyx_INCREF(__pyx_t_2);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_9, function);
          __pyx_t_8 = 1;
        }
      }
      #if CYTHON_FAST_PYCALL
      if (PyFunction_Check(__pyx_t_9)) {
        PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_t_7, __pyx_t_6};
        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 769, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      } else
      #endif
      #if CYTHON_FAST_PYCCALL
      if (__Pyx_PyFastCFunction_Check(__pyx_t_9)) {
        PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_t_7, __pyx_t_6};
        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_9, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 769, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      } else
      #endif
      {
        __pyx_t_1 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 769, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        if (__pyx_t_2) {
          __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2); __pyx_t_2 = NULL;
        }
        __Pyx_GIVEREF(__pyx_t_7);
        PyTuple_SET_ITEM(__pyx_t_1, 0+__pyx_t_8, __pyx_t_7);
        __Pyx_GIVEREF(__pyx_t_6);
        PyTuple_SET_ITEM(__pyx_t_1, 1+__pyx_t_8, __pyx_t_6);
        __pyx_t_7 = 0;
        __pyx_t_6 = 0;
        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 769, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      }
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __pyx_v_est = __pyx_t_3;
      __pyx_t_3 = 0;
 770:             else:
+771:                 raise PredictionImpossible('User and item are unknown.')
    /*else*/ {
      __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_PredictionImpossible); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 771, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __pyx_t_1 = NULL;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) {
        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_9);
        if (likely(__pyx_t_1)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9);
          __Pyx_INCREF(__pyx_t_1);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_9, function);
        }
      }
      __pyx_t_3 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_9, __pyx_t_1, __pyx_kp_u_User_and_item_are_unknown) : __Pyx_PyObject_CallOneArg(__pyx_t_9, __pyx_kp_u_User_and_item_are_unknown);
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 771, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_Raise(__pyx_t_3, 0, 0, 0);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __PYX_ERR(0, 771, __pyx_L1_error)
    }
    __pyx_L9:;
  }
  __pyx_L3:;
 772: 
+773:         return est
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_est);
  __pyx_r = __pyx_v_est;
  goto __pyx_L0;