Есть ли эффективный способ умножить каждую строку (или столбец) dask.array на векторный элемент? - PullRequest
1 голос
/ 08 февраля 2020

У меня есть (огромный) 2D массив в dask, который не помещается в памяти, и мне нужно умножить каждый столбец на соответствующее число вектора. Т.е. я хочу отобразить M (i, j) → x (i) * M (i, j).

Я не думаю, что есть какой-либо способ изменить элементы непосредственно в dask. Это невероятно легко сделать в numpy, но похоже, что умножение dask не позволяет сделать это таким же образом.

Мой текущий план состоял в том, чтобы создать массив dask из вектора и map нулевая матрица (того же размера, что и исходная матрица) для повторения векторного фрагмента и передачи его обратно.

M = da.from_array( the_matix  , chunks = chunks )
x = da.from_array( the_vector , chunks = chunks ) 

def fn(x, block_id=None): 
   ret = x.blocks[ block_id[0] ].compute()
   ret = np.repeat( ret[:,np.newaxis] , M.shape[1] , axis = 1 )
   return ret

temp = da.zeros( chunks=M.chunks , shape=M.shape )
temp = temp.map_blocks( fn , dtype=float )
M = da.multiply( [ M , temp ] ) 

Это кажется крайне неэффективным и включает в себя ужасающее количество использования ОЗУ для такого простое задание Есть ли более простой способ сделать это?

1 Ответ

1 голос
/ 09 февраля 2020

Как в примере ниже не работает?

from dask.array import from_array, multiply
from numpy import array
M = from_array(array([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]]))
vector = from_array(array([1,2,3]))
multiply(M.T, vector).T.compute()

Вывод:

array([[ 0,  1,  2,  3,  4],
       [10, 12, 14, 16, 18],
       [30, 33, 36, 39, 42]])

Я проверял, что он также работает с:

import dask.array as da
M = da.random.random((10000, 10000), chunks=(1000, 1000))
vector = da.random.random((10000, 1), chunks=(1000, 1000))
result = multiply(M.T, vector).T
...