De façon optimale pour calculer les paires d'information mutuelle utilisation de numpy
Pour un m x n de la matrice, ce qui est optimal (le plus rapide) manière de calculer l'information mutuelle pour toutes les paires de colonnes (n x n)?
Par l'information mutuelle, je veux dire:
I(X, Y) = H(X) + H(Y) - H(X,Y)
où H(X) se réfère à l'entropie de Shannon de X.
Actuellement, je suis en utilisant np.histogram2d
et np.histogram
pour calculer la commune (X,Y) et personne (X ou Y) compte. Pour une matrice donnée A
(par exemple, un 250000 X 1000 matrice de chars), je suis en train de faire un imbriquée for
boucle,
n = A.shape[1]
for ix = arange(n)
for jx = arange(ix+1,n):
matMI[ix,jx]= calc_MI(A[:,ix],A[:,jx])
Il doit sûrement y avoir mieux/plus vite façons de le faire?
En aparté, j'ai aussi regardé pour les fonctions de mappage de colonnes (colonne ou de la ligne sage opérations) sur les tableaux, mais je n'ai pas trouvé une bonne réponse pour l'instant.
Voici ma pleine mise en œuvre, suivant les conventions en la page du 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)
Bien que ma version de travail avec imbriqué for
boucles t-il à vitesse raisonnable, je voudrais savoir si il y a une manière plus optimale à appliquer calc_MI
sur toutes les colonnes de A
(pour calculer leurs paires d'information mutuelle)?
Je voudrais aussi savoir:
-
S'il existe des moyens efficaces pour carte pour fonctionner sur les colonnes (ou lignes) de
np.arrays
(peut-être commenp.vectorize
, qui ressemble plus à un décorateur)? -
Si il y a d'autres optimal des implémentations pour ce calcul spécifique (information mutuelle)?
- Pourriez-vous développer votre exemple de code pour inclure
calc_MI
et exemple d'entrée pourA
? Faire en sorte que nous pouvons copier, coller et de les exécuter. Va grandement aider quelqu'un essayer de répondre à votre question. - Veuillez lire ce sscce.org et de mettre à jour votre exemple de code pour inclure
calc_MI
et exemple d'entrée pourA
. - Mon commentaire précédent a été par inadvertance alors que je voulais répondre à la suggestion. Merci pour le pointeur sscce.org.
- est-ce un précis autonome exemple de votre méthode actuelle? pastebin.com/kbzyvA6K.
- Si votre matrice est de taille
(n, m)
, il n'est pas facile de vectoriser le calcul de la seulement len * (n - 1) / 2
valeurs uniques, vous êtes après, mais il est souvent plus rapide de faire un vectorisé calcul de lan * n
valeurs dans un produit cartésien complet, même avec les doubles. Le problème avec cette solution est qu'elle nécessite la création de tous les intermédiaires de calcul des objets à la fois. Avec votre approche ci-dessus, vous devez trouver un moyen de la création d'un 4Dhistogramdd
... je ne vois pas de travail avec votre énorme jeu de données. Je veux le regarder dans Cython ou une extension de do... - Dans
shan_entropy
, il ressemble àH = -sum(...)
devrait êtreH = -np.sum(...)
. - Oui, M. E. Merci pour le sscce. J'ai juste inclus des modifications mineures & mises à jour ici: pastebin.com/2bJM6uSi
- Est-ce censé donner un matMI rempli avec des zéros?
- c_normalized = c[np.différent de zéro(c_normalized)] devrait-il en être c_normalized = c_normalized[np.différent de zéro(c_normalized)] ?
- Oui @M4rtini, corrigé. Merci pour le spotting c'. Pas totalement rempli avec des zéros, mais avec des zéros partout où il n'y a pas de MI entre les colonnes.
Vous devez vous connecter pour publier un commentaire.
Je ne peut pas proposer un calcul plus rapide de la boucle externe sur le n*(n-1)/2
les vecteurs, mais votre mise en œuvre de
calc_MI(x, y, bins)
peut être simplifiéesi vous pouvez utiliser scipy version 0.13 ou scikit-learn.
Dans scipy 0,13, de la
lambda_
argument a été ajouté àscipy.les stats.chi2_contingency
Cet argument contrôle de la statistique qui est calculée par la fonction. Si
vous utilisez
lambda_="log-likelihood"
(oulambda_=0
), le logarithme du rapport de vraisemblanceest retourné. C'est aussi souvent appelé le G ou G2 statistique. Autres que
un facteur de 2*n (où n est le nombre total d'échantillons dans l'éventualité
tableau), ce est l'information mutuelle. Donc, vous pourriez mettre en œuvre
calc_MI
comme:
La seule différence entre le présent et de votre mise en œuvre, c'est que ce
la mise en œuvre utilise le logarithme naturel au lieu de le logarithme en base 2
(donc, il est l'expression de l'information dans les "nats" au lieu de "bits"). Si
vous préférerez bits, juste diviser
mi
log(2).Si vous avez (ou peut installer)
sklearn
(c'est à dire scikit-learn), vous pouvez utilisersklearn.métriques.mutual_info_score
, et de mettre en œuvrecalc_MI
comme:chi2_contingency(correction = False)
supprime cette incohérence.