Estou tentando percorrer o espaço de parâmetros de uma função de 6 parâmetros para estudar seu comportamento numérico antes de tentar fazer algo complexo com ela, então estou procurando uma maneira eficiente de fazer isso.
Minha função usa valores de flutuação dados uma matriz numpy de 6 dim como entrada. O que eu tentei fazer inicialmente foi o seguinte:
Primeiro, criei uma função que pega 2 matrizes e gera uma matriz com todas as combinações de valores das duas matrizes
from numpy import *
def comb(a,b):
c = []
for i in a:
for j in b:
c.append(r_[i,j])
return c
Então eu costumava reduce()
aplicar isso a m cópias da mesma matriz:
def combs(a,m):
return reduce(comb,[a]*m)
E então eu avalio minha função assim:
values = combs(np.arange(0,1,0.1),6)
for val in values:
print F(val)
Isso funciona, mas é muito lento. Eu sei que o espaço dos parâmetros é enorme, mas isso não deve ser tão lento. Eu apenas amostramos 10 6 (um milhão) de pontos neste exemplo e levou mais de 15 segundos apenas para criar a matriz values
.
Você conhece alguma maneira mais eficiente de fazer isso com numpy?
Posso modificar a maneira como a função F
leva seus argumentos, se for necessário.
fonte
Respostas:
Na versão mais recente do
numpy
(> 1.8.x),numpy.meshgrid()
fornece uma implementação muito mais rápida:solução de @ pv
numpy.meshgrid()
use apenas para 2D, agora é capaz de ND. Nesse caso, 3D:Observe que a ordem do resultante final é um pouco diferente.
fonte
np.stack(np.meshgrid([1, 2, 3], [4, 5], [6, 7]), -1).reshape(-1, 3)
vai dar a ordem certaAqui está uma implementação numpy pura. É cerca de 5 vezes mais rápido que o uso de ferramentas.
fonte
from sklearn.utils.extmath import cartesian
TypeError: slice indices must be integers or None or have an __index__ method
jogado porcartesian(arrays[1:], out=out[0:m,1:])
Em geral, itertools.combinations é a maneira mais rápida de obter combinações de um contêiner Python (se você realmente deseja combinações, isto é, arranjos SEM repetições e independentes da ordem; não é isso que seu código parece estar fazendo, mas não posso diga se é porque seu código está com defeito ou porque você está usando a terminologia errada).
Se você quiser algo diferente de combinações, talvez outros iteradores em iterols,
product
oupermutations
, possam atendê-lo melhor. Por exemplo, parece que seu código é aproximadamente o mesmo que:Todos esses iteradores produzem tuplas, não listas ou matrizes numpy, portanto, se seu F for exigente em obter especificamente uma matriz numpy, você terá que aceitar a sobrecarga extra de construir ou limpar e preencher novamente uma a cada etapa.
fonte
Você pode fazer algo assim
que dá
fonte
A seguinte implementação numpy deve ser de aprox. 2x a velocidade da resposta dada:
fonte
np.indices((n,...,n)).reshape(k,-1).T
fará.Parece que você deseja uma grade para avaliar sua função; nesse caso, você pode usar
numpy.ogrid
(aberto) ounumpy.mgrid
(detalhado):fonte
você pode usar
np.array(itertools.product(a, b))
fonte
Aqui está outra maneira, usando o NumPy puro, sem recursão, sem compreensão de lista e sem explicações para loops. É cerca de 20% mais lento que a resposta original e é baseado em np.meshgrid.
Por exemplo,
dá
fonte
Para uma implementação numpy pura do produto cartesiano de matrizes 1D (ou listas planas de python), basta usar
meshgrid()
, rolar os eixos comtranspose()
e remodelar para a saída desejada:Observe que a convenção do último eixo muda mais rapidamente ("estilo C" ou "linha principal").
Se você deseja alterar o primeiro eixo mais rapidamente ("estilo FORTRAN" ou "coluna principal"), basta alterar o
order
parâmetro dareshape()
seguinte maneira:reshape((-1, N), order='F')
fonte
O Pandas
merge
oferece uma solução rápida e ingênua para o problema:fonte