2016-12-10 16 views
1

Я пытаюсь использовать numpy.multiply.outer на многомерных массивах, и мне действительно нужно это предположить, что любой 0 * infinity, который он видит, оценивает до нуля. Как я могу сделать это эффективно?Как multiply.outer() в NumPy при допущении 0 * бесконечность = 0?

>>> import numpy 
>>> numpy.multiply.outer([0.], [float('inf')]) 
Warning (from warnings module): 
    File "__main__", line 2 
RuntimeWarning: invalid value encountered in multiply 
array([[ nan]]) 
+0

В основном есть 2 варианта - изменить 'np.inf' так что-то рациональное перед использованием, или изменить предупреждения «игнорировать» и фиксировать значения после факта (если необходимо). – hpaulj

+0

@hpaulj: Я не могу изменить infs на что-то рациональное заранее, потому что у меня нет гарантии, что они умножаются на ноль. Я не могу изменить их после факта, потому что я действительно не знаю, откуда пришли NaN. – Mehrdad

+0

Вы должны предоставить тестовый пример, который включает в себя все нюансы, которые вас волнуют. Один с 'inf' или' nan', который вы хотите сохранить, а также тот, который вы хотите изменить. – hpaulj

ответ

2

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

import numpy as np 
A = np.array([0., 0., 0.4, 2]) 
B = np.array([float('inf'), 1., 3.4, np.inf]) 

# Conditions of interest 
c1 = (A == 0) 
c2 = (B == np.inf) 
condition1 = np.multiply.outer(c1, c2) 
c3 = (A == np.inf) 
c4 = (B == 0) 
condition2 = np.multiply.outer(c3, c4) 
condition = condition1 | condition2 

AA = np.multiply.outer(A, np.ones(B.shape)) 
BB = np.multiply.outer(np.ones(A.shape), B) 

AA[condition] = 0. 
BB[condition] = 0. 

AA*BB 

Это может не передать запрос эффективности на плакате.

+0

Эх ... +1, так как он все же лучше, чем цикл, но да, не то, на что я надеялся. – Mehrdad

+0

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

2

Нужно ли беспокоиться о других источниках nan значений? Если нет, то вы всегда можете просто зафиксировать в отдельном шаге:

import numpy as np 

r = np.multiply.outer([0.], [float('inf')]) 
np.where(np.isnan(r), 0, r) 

до вас, если вы хотите, чтобы подавить предупреждения.

+0

Да, я все еще хочу получить нормальное поведение для других случаев. Но +1, поскольку это обходной путь для некоторых людей (хотя и очевидный). – Mehrdad

1

Вот как подавить предупреждения:

mean, nanmean and warning: Mean of empty slice

In [528]: import warnings 

In [530]: x = np.array([0,1,2],float) 
In [531]: y = np.array([np.inf,3,2],float) 
In [532]: np.outer(x,y) 
/usr/local/lib/python3.5/dist-packages/numpy/core/numeric.py:1093: RuntimeWarning: invalid value encountered in multiply 
    return multiply(a.ravel()[:, newaxis], b.ravel()[newaxis,:], out) 
Out[532]: 
array([[ nan, 0., 0.], 
     [ inf, 3., 2.], 
     [ inf, 6., 4.]]) 

In [535]: with warnings.catch_warnings(): 
    ...:  warnings.simplefilter('ignore',category=RuntimeWarning) 
    ...:  z = np.outer(x,y) 
    ...:  
In [536]: z 
Out[536]: 
array([[ nan, 0., 0.], 
     [ inf, 3., 2.], 
     [ inf, 6., 4.]]) 

заменить nan с 1:

In [542]: z[np.isnan(z)]=1 
In [543]: z 
Out[543]: 
array([[ 1., 0., 0.], 
     [ inf, 3., 2.], 
     [ inf, 6., 4.]]) 

In [547]: z[np.isinf(z)]=9999 
In [548]: z 
Out[548]: 
array([[ 1.00000000e+00, 0.00000000e+00, 0.00000000e+00], 
     [ 9.99900000e+03, 3.00000000e+00, 2.00000000e+00], 
     [ 9.99900000e+03, 6.00000000e+00, 4.00000000e+00]]) 

============== ===

Мы могли бы создать mask с помощью своего рода тестирования, что @P-robot демонстрирующую:

In [570]: np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y)) 
Out[570]: 
array([[ True, False, False], 
     [False, False, False], 
     [False, False, False]], dtype=bool) 
In [571]: mask=np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y)) 
In [572]: with warnings.catch_warnings(): 
    ...:  warnings.simplefilter('ignore',category=RuntimeWarning) 
    ...:  z = np.outer(x,y) 
    ...:  
In [573]: z[mask]=1 
In [574]: z 
Out[574]: 
array([[ 1., 0., 0.], 
     [ inf, 3., 2.], 
     [ inf, 6., 4.]]) 

Или с Messier входы:

In [587]: x = np.array([0,1,2,np.inf],float) 
In [588]: y = np.array([np.inf,3,np.nan,0],float) 
In [589]: mask=np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y)) 
... 
In [591]: with warnings.catch_warnings(): 
    ...:  warnings.simplefilter('ignore',category=RuntimeWarning) 
    ...:  z = np.outer(x,y) 
    ...:  
In [592]: z[mask]=1 
In [593]: z 
Out[593]: 
array([[ 1., 0., nan, 0.], 
     [ inf, 3., nan, 0.], 
     [ inf, 6., nan, 0.], 
     [ inf, inf, nan, 1.]]) 
+0

Это предполагает, что нет никаких NaN уже в любом массиве ввода, правильно? В противном случае вы можете замаскировать что-то. – Mehrdad

+0

Я добавил маскировочный тест в соответствии с ответом '@ P-robot'. – hpaulj