for step in range(steps):
    e = self.model - np.dot(self.p, self.q.T)
p_temp = learning_rate * np.dot(e, self.q)
self.q *= 1 - regularization
self.q += learning_rate * np.dot(e.T, self.p)
Scipy - как дополнительно оптимизировать код разреженной матрицы для стохастического градиентного спуска