docs: def partial_fit(self, counts_df, batch_type='users', step_size=None,
  					nusers=None, nitems=None, users_in_batch=None, items_in_batch=None,
  					new_users=False, new_items=False, random_seed=None):
  		"""
  		Updates the model with batches of data from a subset of users or items
  
  		Note
  		----
  		You must pass either the **full set of user-item interactions** that are non-zero for some
  		subset of users, or the **full set of item-user intersactions** that are non-zero for some
  		subset of items.
  		Otherwise, if passing a random sample of triplets, the model will not converge to reasonable results.
  
  		Note
  		----
  		All user and items IDs must be integers starting at one, without gaps in the numeration.
  
  		Note
  		----
  		For better results, fit the model with full-batch iterations (using the 'fit' method).
  		Adding new users and/or items without refitting the model might result in worsened results
  		for existing users/items. For adding users without altering the parameters for items or for
  		other users, see the method 'add_user'.
  
  		Note
  		----
  		Fitting in mini-batches is more prone to numerical instability and compared to full-batch
  		variational inference, it is more likely that all your parameters will turn to NaNs (which
  		means the optimization procedure failed).
  
  		Parameters
  		----------
  		counts_df : data frame (n_samples, 3)
  			Data frame with the user-item interactions for some subset of users. Must have columns
  			'UserId', 'ItemId', 'Count'.
  		batch_type : str, one of 'users' or 'items'
  			Whether 'counts_df' contains a sample of users with all their item counts ('users'), or a
  			sample of items with all their user counts ('items').
  		step_size : None or float in (0, 1)
  			Step size with which to update the global variables in the model. Must be a number between
  			zero and one. If passing None, will determine it according to the step size function with which
  			the model was initialized and the number of iterations or calls to partial fit that have been
  			performed. If no valid function was passed at the initialization, it will use 1/sqrt(i+1).
  		nusers : int
  			Total number of users (not just in this batch!). Only required if calling partial_fit for the
  			first time on a model object that hasn't been fit.
  		nitems : int
  			Total number of items (not just in this batch!). Only required if calling partial_fit for the
  			first time on a model object that hasn't been fit.
  		users_in_batch : None or array (n_users_sample,)
  			Users that are present int counts_df. If passing None, will determine the unique elements in
  			counts_df.UserId, but passing them if you already have them will skip this step.
  		items_in_batch : None or array (n_items_sample,)
  			Items that are present int counts_df. If passing None, will determine the unique elements in
  			counts_df.ItemId, but passing them if you already have them will skip this step.
  		new_users : bool
  			Whether the data contains new users with numeration greater than the number of users with which
  			the model was initially fit. **For better results refit the model including all users/items instead
  			of adding them afterwards**.
  		new_items : bool
  			Whether the data contains new items with numeration greater than the number of items with which
  			the model was initially fit. **For better results refit the model including all users/items instead
  			of adding them afterwards**.
  		random_seed : int
  			Random seed to be used for the initialization of new user/item parameters. Ignored when
  			new_users=False and new_items=False.
  
  		Returns
  		-------
  		self : obj
  			Copy of this object.
  		"""
  
  		if self.reindex:
  			raise ValueError("'partial_fit' can only be called when using reindex=False.")
  		if not self.keep_all_objs:
  			raise ValueError("'partial_fit' can only be called when using keep_all_objs=True.")
  		if self.keep_data:
  			try:
  				self.seen
  				msg = "When using 'partial_fit', the list of items seen by each user is not updated "
  				msg += "with the data passed here."
  				warnings.warn(msg)
  			except:
  				msg = "When fitting the model through 'partial_fit' without calling 'fit' beforehand, "
  				msg += "'keep_data' will be forced to False."
  				warnings.warn(msg)
  				self.keep_data = False
  
  		assert batch_type in ['users', 'items']
  		if batch_type == 'users':
  			user_batch = True
  		else:
  			user_batch = False
  
  		if nusers is None:
  			try:
  				nusers = self.nusers
  			except:
  				raise ValueError("Must specify total number of users when calling 'partial_fit' for the first time.")
  		if nitems is None:
  			try:
  				nitems = self.nitems
  			except:
  				raise ValueError("Must specify total number of items when calling 'partial_fit' for the first time.")
  
  		try:
  			if self.nusers is None:
  				self.nusers = nusers
  		except:
  			self.nusers = nusers
  		try:
  			if self.nitems is None:
  				self.nitems = nitems
  		except:
  			self.nitems = nitems
  
  		if step_size is None:
  			try:
  				self.step_size(0)
  				try:
  					step_size = self.step_size(self.niter)
  				except:
  					self.niter = 0
  					step_size = 1.0
  			except:
  				try:
  					step_size = 1 / np.sqrt(self.niter + 2)
  				except:
  					self.niter = 0
  					step_size = 1.0
  		assert step_size >= 0
  		assert step_size <= 1
  
  		if random_seed is not None:
  			if isinstance(random_seed, float):
  				random_seed = int(random_seed)
  			assert isinstance(random_seed, int)
  
  		if counts_df.__class__.__name__ == "ndarray":
  			counts_df = pd.DataFrame(counts_df)
  			counts_df.columns[:3] = ['UserId', 'ItemId', 'Count']
  
  		assert counts_df.__class__.__name__ == "DataFrame"
  		assert 'UserId' in counts_df.columns.values
  		assert 'ItemId' in counts_df.columns.values
  		assert 'Count' in counts_df.columns.values
  		assert counts_df.shape[0] > 0
  
  		Y_batch = counts_df.Count.values.astype('float32')
  		ix_u_batch = counts_df.UserId.values.astype(cython_loops.obj_ind_type)
  		ix_i_batch = counts_df.ItemId.values.astype(cython_loops.obj_ind_type)
  
  		if users_in_batch is None:
  			users_in_batch = np.unique(ix_u_batch)
  		else:
  			users_in_batch = np.array(users_in_batch).astype(cython_loops.obj_ind_type)
  		if items_in_batch is None:
  			items_in_batch = np.unique(ix_i_batch)
  		else:
  			items_in_batch = np.array(items_in_batch).astype(cython_loops.obj_ind_type)
  
  		if (self.Theta is None) or (self.Beta is None):
  			self._cast_before_fit()
  			self.Gamma_shp, self.Gamma_rte, self.Lambda_shp, self.Lambda_rte, \
  			self.k_rte, self.t_rte = cython_loops.initialize_parameters(
  				self.Theta, self.Beta, self.random_seed, self.a, self.a_prime,
  				self.b_prime, self.c, self.c_prime, self.d_prime)
  			self.Theta = self.Gamma_shp / self.Gamma_rte
  			self.Beta = self.Lambda_shp / self.Lambda_rte
  
  		if new_users:
  			if not self.keep_all_objs:
  				raise ValueError("Can only add users without refitting when using keep_all_objs=True")
  			nusers_now = ix_u_batch.max() + 1
  			nusers_add = self.nusers - nusers_now
  			if nusers_add < 1:
  				raise ValueError("There are no new users in the data passed to 'partial_fit'.")
  			self._initialize_extra_users(nusers_add, random_seed)
  			self.nusers += nusers_add
  
  		if new_items:
  			if not self.keep_all_objs:
  				raise ValueError("Can only add items without refitting when using keep_all_objs=True")
  			nitems_now = ix_i_batch.max() + 1
  			nitems_add = self.nitems - nitems_now
  			if nitems_add < 1:
  				raise ValueError("There are no new items in the data passed to 'partial_fit'.")
  			self._initialize_extra_items(nitems_add, random_seed)
  			self.nitems += nitems_add
  
  		k_shp = cython_loops.cast_float(self.a_prime + self.k * self.a)
  		t_shp = cython_loops.cast_float(self.c_prime + self.k * self.c)
  		add_k_rte = cython_loops.cast_float(self.a_prime / self.b_prime)
  		add_t_rte = cython_loops.cast_float(self.c_prime / self.d_prime)
  		multiplier_batch = float(nusers) / users_in_batch.shape[0]
  
  		cython_loops.partial_fit(
  					Y_batch,
  					ix_u_batch, ix_i_batch,
  					self.Theta, self.Beta,
  					self.Gamma_shp, self.Gamma_rte,
  					self.Lambda_shp, self.Lambda_rte,
  					self.k_rte, self.t_rte,
  					add_k_rte, add_t_rte, self.a, self.c,
  					k_shp, t_shp, cython_loops.cast_ind_type(self.k),
  					users_in_batch, items_in_batch,
  					cython_loops.cast_int(self.allow_inconsistent_math),
  					cython_loops.cast_float(step_size), cython_loops.cast_float(multiplier_batch),
  					self.ncores, user_batch
  				)
  
  		self.niter += 1
  		self.is_fitted = True
  		return self