простой способ сделать внешний продукт списка

Я пытаюсь сделать нормализованную сумму внешнего произведения матрицы 60000x100. Я хотел бы сделать это с помощью numpy, так как мое решение ограничено циклом python for в понимании списка:

def covariance_over_time(X):
    B = np.sum(np.array([np.outer(x, x) for x in X]),axis=0)              
    B = np.true_divide(B, len(X))
    return B 

Имейте в виду, что даже это решение работает, оно однопоточное и поэтому очень медленное, когда X имеет 60000 строк и 100 столбцов.

Я пробовал другие подходы, подобные описанным здесь в stackoverflow. Ответ, размещенный в ссылке, работает для небольших матриц, дает мне память после ошибки в несколько секунд. Ты знаешь почему? (Примечание: у меня 6 терабайт оперативной памяти, поэтому маловероятно, что у меня проблема с памятью, поскольку я вообще не вижу роста использования памяти!)


person asdf    schedule 22.05.2017    source источник


Ответы (1)


Вы можете просто использовать matrix-multiplication, используя np.dot -

B = X.T.dot(X)

Затем нормализуйте с помощью np.true_divide(B, len(X)).


Решения, оптимизированные для памяти

Если вы все еще сталкиваетесь с ошибками памяти, у нас есть еще два варианта/метода.

И. Полное зацикленное решение

Мы могли бы перебрать вторую ось (столбцы) X и выполнить матричное умножение между каждым столбцом против каждого столбца, используя два цикла. Теперь X имеет только 100 столбцов, и, таким образом, полное зацикленное решение будет повторяться только 100X100 = 10000 раз и на каждой итерации выполнять 60000 (количество строк в X) сумма-редукции.

n = X.shape[1]
out = np.empty((n,n),dtype=X.dtype)
for i in range(n):
    for j in range(n):
        out[i,j] = X[:,i].dot(X[:,j])

II. Гибридное решение

Соединение между полным циклическим решением и полностью векторизованным решением, указанным в начале, будет использовать один цикл, который будет выполнять матричное умножение между каждым столбцом по всему массиву. Это будет делать 60000X100=6000000 уменьшения суммы на каждой итерации.

n = X.shape[1]
out = np.empty((n,n),dtype=X.dtype)
for i in range(n):
    out[i] = X[:,i].dot(X)
person Divakar    schedule 22.05.2017
comment
Вау, очень впечатляет. Спасибо! - person asdf; 23.05.2017