Próbuję przeanalizować przestrzeń parametrów funkcji 6-parametrowej, aby zbadać jej zachowanie numeryczne, zanim spróbuję zrobić z nią coś złożonego, więc szukam skutecznego sposobu, aby to zrobić.
Moja funkcja przyjmuje wartości zmiennoprzecinkowe, które jako dane wejściowe przyjmują 6-dim tablicę numpy. Na początku próbowałem zrobić tak:
Najpierw stworzyłem funkcję, która pobiera 2 tablice i generuje tablicę ze wszystkimi kombinacjami wartości z dwóch tablic
from numpy import *
def comb(a,b):
c = []
for i in a:
for j in b:
c.append(r_[i,j])
return c
Następnie reduce()
stosowałem to do m kopii tej samej tablicy:
def combs(a,m):
return reduce(comb,[a]*m)
A potem oceniam moją funkcję w ten sposób:
values = combs(np.arange(0,1,0.1),6)
for val in values:
print F(val)
To działa, ale jest zbyt wolne. Wiem, że przestrzeń parametrów jest ogromna, ale nie powinno to być takie wolne. W tym przykładzie pobrałem tylko 10 6 (milion) punktów, a samo utworzenie tablicy zajęło więcej niż 15 sekund values
.
Czy znasz lepszy sposób na zrobienie tego z numpy?
Mogę zmodyfikować sposób, w jaki funkcja F
przyjmuje argumenty, jeśli jest to konieczne.
źródło
Odpowiedzi:
W nowszej wersji
numpy
(> 1.8.x)numpy.meshgrid()
zapewnia znacznie szybszą implementację:Rozwiązanie @ pv
numpy.meshgrid()
Kiedyś był tylko 2D, teraz jest zdolny do ND. W tym przypadku 3D:Zwróć uwagę, że kolejność wyniku końcowego jest nieco inna.
źródło
np.stack(np.meshgrid([1, 2, 3], [4, 5], [6, 7]), -1).reshape(-1, 3)
wyda właściwą kolejnośćOto prosta implementacja. To około 5 razy szybciej niż przy użyciu itertools.
źródło
from sklearn.utils.extmath import cartesian
TypeError: slice indices must be integers or None or have an __index__ method
wyrzucony przezcartesian(arrays[1:], out=out[0:m,1:])
itertools.combinations to generalnie najszybszy sposób na uzyskanie kombinacji z kontenera Pythona (jeśli faktycznie potrzebujesz kombinacji, tj. układów BEZ powtórzeń i niezależnych od kolejności; wydaje się, że nie to robi twój kod, ale nie mogę powiedz, czy dzieje się tak dlatego, że twój kod zawiera błędy, czy też dlatego, że używasz złej terminologii).
Jeśli chcesz czegoś innego niż kombinacje, być może inne iteratory w itertools
product
lubpermutations
mogą ci służyć lepiej. Na przykład wygląda na to, że Twój kod jest mniej więcej taki sam, jak:Wszystkie te iteratory dają krotki, a nie listy lub tablice numpy, więc jeśli twój F jest wybredny, jeśli chodzi o uzyskanie konkretnej tablicy numpy, będziesz musiał zaakceptować dodatkowe obciążenie związane z konstruowaniem lub czyszczeniem i ponownym wypełnianiem jednej na każdym kroku.
źródło
Możesz zrobić coś takiego
co daje
źródło
Następująca implementacja numpy powinna wynosić ok. 2x szybkość udzielonej odpowiedzi:
źródło
np.indices((n,...,n)).reshape(k,-1).T
wystarczą.Wygląda na to, że potrzebujesz siatki do oceny funkcji, w takim przypadku możesz użyć
numpy.ogrid
(otwórz) lubnumpy.mgrid
(uzupełnij):źródło
możesz użyć
np.array(itertools.product(a, b))
źródło
Oto jeszcze jeden sposób, używając czystego NumPy, bez rekursji, bez rozumienia list i bez jawnych pętli for. Jest około 20% wolniejsze niż oryginalna odpowiedź i opiera się na np.meshgrid.
Na przykład,
daje
źródło
Aby uzyskać czystą numpy implementację iloczynu kartezjańskiego tablic 1D (lub płaskich list Pythona), po prostu użyj
meshgrid()
, obróć osietranspose()
i zmień kształt na pożądany wynik:Zauważ, że ma to konwencję najszybszej zmiany ostatniej osi („styl C” lub „wiersz główny”).
Jeśli chcesz zmienić pierwszą oś najszybciej („styl FORTRAN” lub „kolumna główna”), po prostu zmień
order
parametr wreshape()
ten sposób:reshape((-1, N), order='F')
źródło
Pandy
merge
oferują naiwne, szybkie rozwiązanie problemu:źródło