2016-07-02 2 views
2

Я столкнулся с проблемой памяти и скорости, используя NumPy, но моя проблема довольно проста.Как эффективно умножать список видов NumPy с соответствующими весами?

  • A - большой массив NumPy из H * W целых чисел.
  • V - это список, содержащий N виды большого массива A, каждый вид, как то же (Hv, Wv) форму.
  • K - еще один список, содержащий N плавающие грузы, соответствующие представлениям.

Hv являются Wv почти равны H и W, но меньше. Поскольку NumPy views не являются копиями, это хорошо для управления памятью, даже если N большой.

Теперь я хочу, чтобы вычислить новый массив, используя для вещания скорости: B = V * K + ... + V N * K N

Этот приведет к созданию нового взвешенного массива Hv * Wv.

Проблема в том, что я не знаю, как выполнить такую ​​операцию, не создавая промежуточные массивы в памяти (что и происходит, когда представление умножается на соответствующий вес) и при этом выигрывает от широковещательных операций.

import numpy as np 

H = W = 1000 
Hv = Wv = 900 
N = 100 

A = np.arange(H * W).reshape(H, W) 

V = [A[i:Hv + i, i:Wv + i] for i in range(N)] 

K = np.random.rand(N) 

# It neither uses speed broadcast nor low memory! 
B = sum(v*k for v, k in zip(V, K)) 

Может ли кто-нибудь помочь мне разумно использовать NumPy, пожалуйста?

+0

Кажется, что 'A' удерживает вес? Таким образом, было бы разумнее использовать образец с случайными числами в нем, а не просто «одни», правильно? – Divakar

+0

Разве вы не упростились с помощью: 'V = [A [: Hv:: Wv] для _ в диапазоне (N)]' как V [0], V [1] и т. Д. То же самое? – Divakar

+0

@ Divakar Я думал, что этого достаточно, чтобы понять проблему, но это правда, что она не выглядит как настоящие данные.Я обновил свой вопрос массивом скользящих диагональных представлений, я надеюсь, что это лучше (но это работает, потому что 'N = H - Hv' и в противном случае приведет к ошибке). – Delgan

ответ

1

Я принимаю, что V указан как список, и у нас нет доступа к оптимизации его создания или просто не нужно. Итак, A находится вне уравнения, и мы остаемся с V и K, чтобы получить окончательный вывод B и, таким образом, оставим с оптимизацией последний шаг.

Чтобы решить эту проблему, мы можем просто использовать np.tensordot, чтобы заменить последний шаг суммирования, поскольку это в основном сокращение суммы умножения матрицы. В нашем случае мы уменьшаем первую ось от K и по длине списка ввода V. Внутренне NumPy преобразует список в массив тензоров NumPy, и эта длина станет первой осью его версии массива. Таким образом, мы бы уменьшение первой оси от обоих входов и, следовательно, реализация будет -

B = np.tensordot(K,V,axes=[0,0]) # `axes` indicates the axes to be sum-reduced 

Пожалуйста, обратите внимание, что внутреннее преобразование списка в NumPy массив не может быть недорогой и, как таковой, он будет иметь больше смысла для создания V с использованием инициализации в виде массива NumPy, а не в понимании цикла, которое приведет к списку.

+0

О, это выглядит сложным, я бы никогда не понял этого, спасибо. Извините, но поскольку я отредактировал свой вопрос, чтобы упростить его, переменные 'coords' больше не имеют смысла. – Delgan

+0

Вау, большое спасибо за ваше время, решение и объяснения очень ценятся! Тем не менее, я все еще запутался в использовании памяти NumPy. Хотя решение, использующее 'np.tensordot', кажется более быстрым и [светлее] (http://pastebin.com/raw/a1emehwQ) (не так сильно, как я думал, так оно и будет, поэтому мое предположение о том, что умножение представления с помощью float дает огромные использование памяти было неправильным), инициализация 'V' в качестве массива NumPy приводит к [неожиданному увеличению использования памяти] (http://pastebin.com/raw/ct0kSTG2). Я что-то делаю с профилированием, или я должен что-то знать? – Delgan

+0

@ Delgan Ах не так, что бы создать список, а затем преобразовать в массив! Я имел в виду, что V = np.zeros ((N, Hv, Wv)) и использовать правильную петлю вместо понимания цикла для хранения на каждой итерации в V [0] = .., V [1] = ... и так на. Если по какой-то причине использование правильного цикла невозможно, придерживайтесь того, что у вас было в списке. – Divakar

Смежные вопросы