Для оптимизации цикла в Python

#python #numpy

#python #numpy

Вопрос:

Я выполнил следующий код для матриц размером 100 миллионов строк и 100 столбцов.

Я хочу оптимизировать следующий код. Любая помощь была бы действительно оценена.

 def matrix_factorization(R, P, Q, K, steps=5000, alpha=0.0002, beta=0.02):

    Q = Q.T

    for step in range(steps):
        e = 0
        for i in range(len(R)):
            for j in range(len(R[i])):
                if R[i][j] > 0:
                    temp_dot = numpy.dot(P[i,:],Q[:,j])
                    eij = R[i][j] - temp_dot
                    e = e   eij*eij
                    for k in range(K):
                        P[i][k] = P[i][k]   alpha * (2 * eij * Q[k][j] - beta * P[i][k])
                        Q[k][j] = Q[k][j]   alpha * (2 * eij * P[i][k] - beta * Q[k][j])
                        e = e   (beta/2) * ((P[i][k]*P[i][k])   (Q[k][j]*Q[k][j]))
        if e < 0.001:
            break

    return P, Q.T
  

Комментарии:

1. насколько велика эта машина и сколько времени это занимает?

2. Обязательно ли запускать все это сразу или вы можете разбить это на фрагменты или вставить в поток? Я недостаточно знаком с вашими операциями, чтобы знать, не можете ли вы разделить это так, чтобы его части анализировались параллельно.

3. я использую corei5 с 8 ГБ оперативной памяти … я протестировал образец матрицы из 5000 строк и 5 columns..it заняло около 1 часа при значении K = 5

4. Какого рода матричную факторизацию должна вычислять эта функция?

Ответ №1:

Ваш внутренний цикл:

 for k in range(K):
    P[i][k] = P[i][k]   alpha * (2 * eij * Q[k][j] - beta * P[i][k])
    Q[k][j] = Q[k][j]   alpha * (2 * eij * P[i][k] - beta * Q[k][j])
    e = e   (beta/2) * ((P[i][k]*P[i][k])   (Q[k][j]*Q[k][j]))
  

Может быть векторизован как:

 P[i,:]  = alpha    * np.sum(2 * eij * Q[:,j] - beta * P[i,:], axis=-1)
Q[:,j]  = alpha    * np.sum(2 * eij * P[i,:] - beta * Q[:,j], axis=-1)
e       = (beta/2) * np.sum(P[i,:]*P[i,:]   Q[:,j]*Q[:,j])
  

Комментарии:

1. Отличная идея! Еще одним улучшением могло бы стать использование на последнем шаге (a b)**2 свойства там. Итак, мы можем использовать einsum и dot там : a_b = a b; e = np.einsum('i,i',a_b,a_b) - 2*a.dot(b) , где a и b являются P[i,:] и Q[:,j] . Обожаю эти функции! 🙂

2. @Divakar: Мне кажется нелогичным, что это было бы быстрее