Эффективный с точки зрения памяти метод вычисления sqrt большой матрицы с отрицательными значениями

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

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

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

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


person shaifali Gupta    schedule 04.05.2019    source источник


Ответы (2)


При работе с большими данными мы также можем использовать 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
person Divakar    schedule 04.05.2019
comment
Я удивлен, что у numexpr нет функции sign. - person Warren Weckesser; 04.05.2019
comment
@WarrenWeckesser Ага! Может быть хорошим дополнением к их списку. - person Divakar; 04.05.2019

Numpy "where" - подходящая альтернатива для вашей проблемы. Попробуйте этот код:

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

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

person Arashsyh    schedule 04.05.2019