2012-04-13 14 views
22

Mam następujący kod, który próbuje znormalizować wartości tablicy m x n (Będzie on używany jako wejście do sieci neuronowej, gdzie m jest liczbą przykładów treningu, a n jest liczbą funkcji).Numpy modyfikować macierz w miejscu?

Jednak, gdy sprawdzam tablicę w interpretera po uruchomieniu skryptu, widzę, że wartości nie są znormalizowane; to znaczy, że nadal mają oryginalne wartości. Sądzę, że dzieje się tak dlatego, że przypisanie zmiennej array do funkcji jest widoczne tylko w funkcji.

Jak mogę wprowadzić tę normalizację? Czy muszę zwrócić nową tablicę z funkcji normalizacji?

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() 

Odpowiedz

19

Jeśli chcesz zastosować operacje matematyczne do numpy tablicy w miejscu, można po prostu użyć standard w miejscu operatorzy +=, -=, /= itp więc na przykład:

>>> 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]) 

in-place wersja tych operacji jest odrobinę szybszy rozruch, zwłaszcza dla większych tablic:

>>> 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 
+0

co to jest "% timeit"? To wygląda interesująco, czy jest wbudowane? – User

+0

Używana tutaj wersja jest wbudowana tylko w [ipython] (http://ipython.org/). Ale jest oparty na funkcji 'timeit' w module [' timeit'] (http://docs.python.org/library/timeit.html#module-timeit). – senderle

+0

Ah w końcu spojrzał na ipython. Zabawne, zawsze kojarzyłem go z ironpythonem, omyłkowo teraz widzę. – User

3
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] 
+0

Jeśli chodzi o wydajność, czy jest jakaś kwestia w ten sposób? Jak to się ma do tworzenia nowej tablicy? – User

+0

Chodzi mi o to, że musiałbyś porównywać. To zależy od wielkości tablicy. W przypadku małych problemów z pewnością po prostu utworzę nową tablicę. – ely

1

Istnieje dobry sposób na normalizację w miejscu podczas korzystania z numpy. np.vectorize jest bardzo przydatny w połączeniu z funkcją lambda po zastosowaniu do macierzy. Zobacz przykład poniżej:

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 

Można porównać wydajność z wyrażeniem generatora, jednak prawdopodobnie istnieje wiele innych sposobów, aby to zrobić.

%%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 

Więc vectorize pewno nie jest najszybszy, ale można conveient w przypadkach, gdy wydajność nie jest tak ważne.

+0

Wykonuje zadanie, ale jest bardzo powolne, ponieważ jest zaimplementowane jak pętla for, zgodnie z dokumentacją. – Michael

+0

Czy są jakieś punkty odniesienia dla tego rodzaju rzeczy? Miejmy nadzieję, że wektoryzacja może pomóc szybciej. – user48956

0

Jest to trik, który jest nieco bardziej ogólne niż innych przydatnych odpowiedzi tutaj:

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) 

Tutaj jesteśmy przypisanie wartości do widoku array[...] zamiast przypisanie tych wartości do jakiejś nowej zmiennej lokalnej w zakresie funkcji.

x = np.arange(5, dtype='float') 
print x 
normalize(x) 
print x 

>>> [0. 1. 2. 3. 4.] 
>>> [-1. -0.5 0. 0.5 1. ] 
Powiązane problemy