Ótima maneira de calcular informações mútuas emparelhadas usando numpy

Para ummx n matriz, qual é a maneira ideal (mais rápida) de calcular a informação mútua para todos os pares de colunas (n x n)

Porinformação mútua, Quero dizer:

I (X, Y) = H (X) + H (Y) - H (X, Y)

OndeH (X) refere-se à entropia de Shannon deX.

Atualmente estou usandonp.histogram2d enp.histogram calcular a articulação(X, Y) e individual(X ou Y) conta. Para uma determinada matrizA (por exemplo, uma matriz de 250000 X 1000 de flutuadores), eu estou fazendo um aninhadofor laço

    n = A.shape[1]
    for ix = arange(n)  
        for jx = arange(ix+1,n):
           matMI[ix,jx]= calc_MI(A[:,ix],A[:,jx])

Certamente deve haver maneiras melhores / mais rápidas de fazer isso?

Como um aparte, eu também procurei funções de mapeamento em colunas (operações de coluna ou linha) em matrizes, mas ainda não encontrei uma boa resposta geral.

Aqui está a minha implementação completa, seguindo as convenções ema página do Wiki:

import numpy as np

def calc_MI(X,Y,bins):

   c_XY = np.histogram2d(X,Y,bins)[0]
   c_X = np.histogram(X,bins)[0]
   c_Y = np.histogram(Y,bins)[0]

   H_X = shan_entropy(c_X)
   H_Y = shan_entropy(c_Y)
   H_XY = shan_entropy(c_XY)

   MI = H_X + H_Y - H_XY
   return MI

def shan_entropy(c):
    c_normalized = c / float(np.sum(c))
    c_normalized = c_normalized[np.nonzero(c_normalized)]
    H = -sum(c_normalized* np.log2(c_normalized))  
    return H

A = np.array([[ 2.0,  140.0,  128.23, -150.5, -5.4  ],
              [ 2.4,  153.11, 130.34, -130.1, -9.5  ],
              [ 1.2,  156.9,  120.11, -110.45,-1.12 ]])

bins = 5 # ?
n = A.shape[1]
matMI = np.zeros((n, n))

for ix in np.arange(n):
    for jx in np.arange(ix+1,n):
        matMI[ix,jx] = calc_MI(A[:,ix], A[:,jx], bins)

Embora minha versão de trabalho com aninhadofor loops faz isso a uma velocidade razoável, eu gostaria de saber se existe uma maneira mais ideal de aplicarcalc_MI em todas as colunas deA (para calcular sua informação mútua em pares)?

Eu também gostaria de saber:

Se existem maneiras eficientes de mapear funções para operar em colunas (ou linhas) denp.arrays (talvez comonp.vectorize, que mais parece um decorador?

Se existem outras implementações ideais para este cálculo específico (informação mútua)?

questionAnswers(1)

yourAnswerToTheQuestion