2012-03-14 13 views
8

¿Es posible construir una matriz numpy a partir de una función? En este caso, específicamente, la función es la diferencia absoluta de dos vectores: S[i,j] = abs(A[i] - B[j]). Un ejemplo de trabajo mínima que utiliza Python normal:Rellene la matriz numpy de la diferencia de dos vectores

import numpy as np 

A = np.array([1,3,6]) 
B = np.array([2,4,6]) 
S = np.zeros((3,3)) 

for i,x in enumerate(A): 
    for j,y in enumerate(B): 
     S[i,j] = abs(x-y) 

El dar:

[[ 1. 3. 5.] 
[ 1. 1. 3.] 
[ 4. 2. 0.]] 

Sería bueno tener una construcción que se ve algo como:

def build_matrix(shape, input_function, *args) 

donde puede pasar una la función de entrada con sus argumentos y conserva la ventaja de velocidad de numpy.

+0

Esto es posible. ¿Qué has intentado? – Marcin

+0

@Marcin - como se indica en la pregunta, estoy usando un enfoque simple de python para completar la matriz en este momento. Al revisar los documentos de numpy, sugiero que la función 'vectorize' podría ser útil, pero aún no vi cómo construir la matriz a partir de la función en primer lugar. Si pudieras señalarme en la dirección correcta (en cuanto a documentación), ¡te lo agradecería! – Hooked

+0

Esto debería ser posible en python simple. ¿Qué has intentado crear tu función build_matrix? Seguramente tienes algo, y estás atrapado en algún lugar, en lugar de esperar que alguien lo escriba todo por ti. – Marcin

Respuesta

10

Yo recomiendo echar un vistazo en las capacidades de transmisión de numpy:

In [6]: np.abs(A[:,np.newaxis] - B) 
Out[6]: 
array([[1, 3, 5], 
     [1, 1, 3], 
     [4, 2, 0]]) 

http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html

entonces se podría simplemente escribir su función como:

In [7]: def build_matrix(func,args): 
    ...:  return func(*args) 
    ...: 

In [8]: def f1(A,B): 
    ...:  return np.abs(A[:,np.newaxis] - B) 
    ...: 

In [9]: build_matrix(f1,(A,B)) 
Out[9]: 
array([[1, 3, 5], 
     [1, 1, 3], 
     [4, 2, 0]]) 

Esto también debe ser considerablemente más rápido que su solución para matrices más grandes.

+0

Esto es perfecto y tiene una _considerable_ ganancia para N. grande Veré más en la radiodifusión, gracias. – Hooked

+2

Para evitar la creación de una matriz intermedia que contenga la diferencia ['numpexpr'] (https://code.google.com/p/numexpr/) podría utilizarse:' c = a [:, None]; result = numexpr.evaluate ("abs (c - b)") ' – jfs

+0

@ J.F.Sebastian - Para lo que sea, también puede evitarlo tomando el valor absoluto in situ si no tiene instalado' numexpr'. Sin embargo, es un poco más detallado: 'c = a [:, None]; resultado = c - b; np.abs (resultado, resultado) ' –

13

Además de lo que ha sugerido @JoshAdel, también puede usar el outer method de cualquier numpy ufunc para hacer la transmisión en el caso de dos arreglos.

En este caso, solo quiere np.subtract.outer(A, B) (O, más bien, el valor absoluto de la misma).

Si bien uno es bastante legible para este ejemplo, en algunos casos, la difusión es más útil, mientras que en otros, el uso de métodos ufunc es más limpio.

De cualquier manera, es útil conocer ambos trucos.

E.g.

import numpy as np 

A = np.array([1,3,6]) 
B = np.array([2,4,6]) 

diff = np.subtract.outer(A, B) 
result = np.abs(diff) 

Básicamente, se puede utilizar outer, accumulate, reduce y reduceat con cualquier numpy ufunc como subtract, multiply, divide, o incluso cosas como logical_and, etc.

Por ejemplo, es equivalente np.cumsum a np.add.accumulate. Esto significa que podría implementar algo como cumdiv por np.divide.accumulate si lo necesitara.

+0

Gracias @JoeKington, ¿sabes de primera mano si hay alguna diferencia interna entre el método de difusión y el método externo? Por razones prácticas, no noto ninguna diferencia de velocidad para pequeñas pruebas en mi máquina, así que supongo que puedo usar cualquiera de ellas. – Hooked

+0

@JoeKington +1 Definitivamente otro gran conjunto de trucos numpy para mantener la manga. De alguna manera, realmente me gusta este enfoque porque considero que la sintaxis es más descriptiva. – JoshAdel

+1

@talonmies En mi máquina para matrices con 10,100,1000 y 10000 elementos, la difusión y los métodos externos tienen más o menos los mismos tiempos, con el método de transmisión ganando por una pequeña cantidad. – JoshAdel

Cuestiones relacionadas