2013-09-23 9 views
6

Mam następujący kod wykonując dokładnie to, co chcę (jest to część metody kriging). Ale problem polega na tym, że działa zbyt wolno i chciałbym się dowiedzieć, czy istnieje jakaś opcja przesunięcia pętli for do numpy? Jeśli wyrzucę numpy.sum i użyję tam argumentu osi, to przyspieszy trochę, ale najwyraźniej nie jest to wąskie gardło. Wszelkie pomysły, w jaki sposób mogę popchnąć forloop do NumPy ją przyspieszyć, lub inne sposoby, aby ją przyspieszyć?)Jak przesunąć pętlę for do numpy

# n = 2116 
print GRZVV.shape # (16309, 2116) 
print GinvVV.shape # (2117, 2117) 
VVg = numpy.empty((GRZVV.shape[0])) 

for k in xrange(GRZVV.shape[0]): 
    GRVV = numpy.empty((n+1, 1)) 
    GRVV[n, 0] = 1 
    GRVV[:n, 0] = GRZVV[k, :] 
    EVV = numpy.array(GinvVV * GRVV) # GinvVV is numpy.matrix 
    VVg[k] = numpy.sum(EVV[:n, 0] * VV) 

Zamieściłem wymiarów ndarrays n macierzy, aby wyczyścić pewne rzeczy z

edit: kształt VV wynosi 2116

+1

Jaki kształt jest ' VV'? –

+0

Jeśli 'VV.shape == (16309,)', w jaki sposób można go zmnożyć przez 'EVV [: n, 0]', który ma kształt '(n,)'? – askewchan

+0

Być może ostatnia linia twojej pętli powinna mieć 'EVV [: n, 0] * VV [k]', co wydaje się być odpowiedzią @ Jaime'a. – askewchan

Odpowiedz

5

Można wykonać następujące czynności w miejscu swojej pętli nad k (wykonawczego ~ 3s):

tmp = np.concatenate((GRZVV, np.ones((16309,1),dtype=np.double)), axis=1) 
EVV1 = np.dot(GinvVV, tmp.T) 
#Changed line below based on *askewchan's* recommendation 
VVg1 = np.sum(np.multiply(EVV1[:n,:],VV[:,np.newaxis]), axis=0) 
+1

Daje to taki sam wynik, jak kod @ usethedeathstar i działa 15 razy szybciej na moim komputerze. – askewchan

+1

Nie ma potrzeby wywoływania kafelków, jak transmisje 'np.multiply'. Zmień go na: 'VVg1 = np.sum (np.multiply (EVV1 [: n,:], VV [:, np.newaxis]), axis = 0)' dla małego przyspieszenia. – askewchan

+0

+1 Dobra rozmowa ... Edytowałem linię powyżej ... dzięki –

3

Jesteś w zasadzie przy każdym rzędzie GRZVV, dołączając 1 na końcu, mnożąc ją GinvVV, a następnie sumując wszystkie elementy w wektorze. Jeśli nie robi nic „append 1”, można zrobić to wszystko bez pętli jak:

VVg = np.sum(np.dot(GinvVV[:, :-1], GRZVV.T), axis=-1) * VV 

lub nawet:

VVg = np.einsum('ij,kj->k', GinvVV[:, :-1], GRZVV) * VV 

jaki sposób obsłużyć ten dodatkowy 1? Cóż, wynikowy wektor pochodzący z mnożenia macierzy zostanie zwiększony o odpowiednią wartość w GinvVV[:, -1], a po dodaniu wszystkich, wartość zostanie zwiększona o np.sum(GinvVV[:, -1]). Więc może po prostu obliczyć ten jeden raz i dodać go do wszystkich elementów w wektorze powrotnej:

VVg = (np.einsum('ij,kj->k', GinvVV[:-1, :-1], GRZVV) + np.sum(GinvVV[:-1, -1])) * VV 

Powyższy kod działa, jeśli VV jest skalarne. Jeśli to jest tablicą kształcie (n,), następnie dodaje zadziała:

GinvVV = np.asarray(GinvVV) 
VVgbis = (np.einsum('ij,kj->k', GinvVV[:-1, :-1]*VV[:, None], GRZVV) + 
      np.dot(GinvVV[:-1, -1], VV)) 
+1

Z edycji @ usethedeathstar, 'VV.shape' jest teraz 2116, więc nie nadaje w twoim rozwiązaniu (ponieważ' Wg.shape' jest 16309) – askewchan

+0

Wyliczyłem, że był to skalar. Z pełną tablicą, nie zwijającą tablicy do końca, jak w odpowiedzi Joela, jest znacznie szybsza niż powyższe dla dużych tablic. – Jaime

Powiązane problemy