Эффективный по памяти метод для вычисления sqrt большой матрицы с отрицательными значениями - PullRequest
1 голос
/ 04 мая 2019

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

neg=numpy.argwhere(temp<0)
temp=numpy.abs(temp)
temp=numpy.sqrt(temp)
temp[neg]=-temp[neg]

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

Есть ли альтернативная память и вычислительно эффективный метод для решения той же задачи. Размер матрицы порядка O(10^5)

Ответы [ 2 ]

3 голосов
/ 04 мая 2019

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

(2*(temp>=0)-1)*np.sqrt(np.abs(temp))

Портировать это на numexpr довольно просто -

import numexpr as ne

ne.evaluate('(2*(temp>=0)-1)*sqrt(abs(temp))')

Сравнительный анализ

Исходная функция-

def orgfunc(temp):
    neg=temp<0
    temp=numpy.abs(temp)
    temp=numpy.sqrt(temp)
    temp[neg]=-temp[neg]
    return temp

Синхронизация больших массивов -

In [55]: np.random.seed(0)
    ...: m,n = 1000,1000
    ...: temp = np.random.randn(m,n)

In [56]: %timeit orgfunc(temp)
100 loops, best of 3: 16 ms per loop

In [57]: %timeit ne.evaluate('(2*(temp>=0)-1)*sqrt(abs(temp))')
100 loops, best of 3: 2.47 ms per loop

In [58]: np.random.seed(0)
    ...: m,n = 10000,10000
    ...: temp = np.random.randn(m,n)

In [59]: %timeit orgfunc(temp)
1 loop, best of 3: 2.09 s per loop

In [60]: %timeit ne.evaluate('(2*(temp>=0)-1)*sqrt(abs(temp))')
1 loop, best of 3: 248 ms per loop
0 голосов
/ 04 мая 2019

Numpy "где" является подходящей альтернативой для вашей проблемы, попробуйте этот код:

result = numpy.where(a>=0, numpy.sqrt(a), -numpy.sqrt(-a))

Эта строка кода возвращает sqrt чисел в вашей матрице, если она положительна или равна нулю, в противном случае возвращает отрицательное значение отрицательного sqrt.

...