Scipy - Как дополнительно оптимизировать редкий матричный код для стохастического градиента спуска
-
21-12-2019 - |
Вопрос
Я работаю над реализации алгоритма спуска стохастического градиента для систем рекомендации, используя редкие матрицы с помощью Scipy.
Вот как выглядит первая базовая реализация:
N = self.model.shape[0] #no of users
M = self.model.shape[1] #no of items
self.p = np.random.rand(N, K)
self.q = np.random.rand(M, K)
rows,cols = self.model.nonzero()
for step in xrange(steps):
for u, i in zip(rows,cols):
e=self.model-np.dot(self.p,self.q.T) #calculate error for gradient
p_temp = learning_rate * ( e[u,i] * self.q[i,:] - regularization * self.p[u,:])
self.q[i,:]+= learning_rate * ( e[u,i] * self.p[u,:] - regularization * self.q[i,:])
self.p[u,:] += p_temp
.
К сожалению, мой код все еще довольно медленно, даже для небольших рейтингов 4x5 Ratings Matrix.Я думал, что это, вероятно, связано с редкой матрицей для петли.Я попытался выразить изменения q и p, используя причудливую индексацию, но поскольку я все еще довольно новичок в Scipy и Numpy, я не мог понять лучший способ сделать это.
Есть ли у вас какие-либо указатели на то, как я могу избежать итерации по рядам и столбцам редкой матрицы?
Решение
Я почти забыл все о рекомендации системы, поэтому я могу быть ошибочно переведен в ваш код, но вы переоцениваете self.model-np.dot(self.p,self.q.T)
внутри каждого цикла, в то время как я почти убежден, его следует оценивать один раз на шаг.
Тогда кажется, что вы делаете матричное умножение вручную, что, вероятно, может быть ускорена с помощью прямого матрицы Mulithlication (Numpy или Scipy сделает это быстрее, чем вы вручную), что-то подобное:
for step in xrange(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))
self.p *= (1-regularization)
self.p += p_temp
. Другие советы
Вы уверены, что вы реализуете SGD?Потому что на каждом этапе вы должны рассчитать ошибку одного рейтинга одного пользователя, а не ошибку всей матрицы рейтинга или, возможно, не могу понять эту строку вашего кода:
e=self.model-np.dot(self.p,self.q.T) #calculate error for gradient
.
А для Scipy Library, я уверен, что у вас будет медленное узкое место, если вы хотите получить доступ к элементам редкой матрицы напрямую.Вместо того, чтобы получить доступ к элементам матрицы рейтинга из Scipy-Bearse-Matrix, вы можете принести определенную строку и столбец в ОЗУ на каждый шаг, а затем выполнять расчет.