Numpy modificar la matriz en su lugar?

Tengo el siguiente código que intenta normalizar los valores de una matriz mxn (se usará como entrada a una neural network, donde m es el número de ejemplos de entrenamiento y n es el número de funciones).

Sin embargo, cuando inspecciono la matriz en el intérprete después de ejecutar el script, veo que los valores no están normalizados; es decir, todavía tienen los valores originales. Supongo que esto se debe a que la asignación a la variable de array dentro de la función solo se ve dentro de la función.

¿Cómo puedo hacer esta normalización en su lugar? ¿O tengo que devolver una nueva matriz de la función normalizar?

 import numpy def normalize(array, imin = -1, imax = 1): """I = Imin + (Imax-Imin)*(D-Dmin)/(Dmax-Dmin)""" dmin = array.min() dmax = array.max() array = imin + (imax - imin)*(array - dmin)/(dmax - dmin) print array[0] def main(): array = numpy.loadtxt('test.csv', delimiter=',', skiprows=1) for column in array.T: normalize(column) return array if __name__ == "__main__": a = main() 

Si desea aplicar operaciones matemáticas a una matriz numpy en el lugar, simplemente puede usar los operadores en el lugar estándar += , -= , /= , etc. Por ejemplo:

 >>> def foo(a): ... a += 10 ... >>> a = numpy.arange(10) >>> a array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> foo(a) >>> a array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]) 

La versión in situ de estas operaciones es un poco más rápida de iniciar, especialmente para matrices más grandes:

 >>> def normalize_inplace(array, imin=-1, imax=1): ... dmin = array.min() ... dmax = array.max() ... array -= dmin ... array *= imax - imin ... array /= dmax - dmin ... array += imin ... >>> def normalize_copy(array, imin=-1, imax=1): ... dmin = array.min() ... dmax = array.max() ... return imin + (imax - imin) * (array - dmin) / (dmax - dmin) ... >>> a = numpy.arange(10000, dtype='f') >>> %timeit normalize_inplace(a) 10000 loops, best of 3: 144 us per loop >>> %timeit normalize_copy(a) 10000 loops, best of 3: 146 us per loop >>> a = numpy.arange(1000000, dtype='f') >>> %timeit normalize_inplace(a) 100 loops, best of 3: 12.8 ms per loop >>> %timeit normalize_copy(a) 100 loops, best of 3: 16.4 ms per loop 
 def normalize(array, imin = -1, imax = 1): """I = Imin + (Imax-Imin)*(D-Dmin)/(Dmax-Dmin)""" dmin = array.min() dmax = array.max() array -= dmin; array *= (imax - imin) array /= (dmax-dmin) array += imin print array[0] 

Este es un truco que es un poco más general que las otras respuestas útiles aquí:

 def normalize(array, imin = -1, imax = 1): """I = Imin + (Imax-Imin)*(D-Dmin)/(Dmax-Dmin)""" dmin = array.min() dmax = array.max() array[...] = imin + (imax - imin)*(array - dmin)/(dmax - dmin) 

Aquí estamos asignando valores a la array[...] vista array[...] lugar de asignar estos valores a alguna nueva variable local dentro del scope de la función.

 x = np.arange(5, dtype='float') print x normalize(x) print x >>> [0. 1. 2. 3. 4.] >>> [-1. -0.5 0. 0.5 1. ] 

EDITAR:

Es mas lento asigna una nueva matriz. Pero puede ser valioso si está haciendo algo más complicado donde las operaciones in situ integradas son engorrosas o no son suficientes.

 def normalize2(array, imin=-1, imax=1): dmin = array.min() dmax = array.max() array -= dmin; array *= (imax - imin) array /= (dmax-dmin) array += imin A = np.random.randn(200**3).reshape([200] * 3) %timeit -n5 -r5 normalize(A) %timeit -n5 -r5 normalize2(A) >> 47.6 ms ± 678 µs per loop (mean ± std. dev. of 5 runs, 5 loops each) >> 26.1 ms ± 866 µs per loop (mean ± std. dev. of 5 runs, 5 loops each) 

Hay una buena manera de hacer una normalización en el lugar cuando se usa numpy. np.vectorize es muy útil cuando se combina con una función lambda cuando se aplica a una matriz. Vea el ejemplo a continuación:

 import numpy as np def normalizeMe(value,vmin,vmax): vnorm = float(value-vmin)/float(vmax-vmin) return vnorm imin = 0 imax = 10 feature = np.random.randint(10, size=10) # Vectorize your function (only need to do it once) temp = np.vectorize(lambda val: normalizeMe(val,imin,imax)) normfeature = temp(np.asarray(feature)) print feature print normfeature 

Uno puede comparar el rendimiento con una expresión generadora, sin embargo, es probable que haya muchas otras formas de hacerlo.

 %%timeit temp = np.vectorize(lambda val: normalizeMe(val,imin,imax)) normfeature1 = temp(np.asarray(feature)) 10000 loops, best of 3: 25.1 µs per loop %%timeit normfeature2 = [i for i in (normalizeMe(val,imin,imax) for val in feature)] 100000 loops, best of 3: 9.69 µs per loop %%timeit normalize(np.asarray(feature)) 100000 loops, best of 3: 12.7 µs per loop 

Por lo tanto, vectorizar definitivamente no es el más rápido, pero puede ser conveniente en casos donde el rendimiento no es tan importante.