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)

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:

  1. S'il existe des moyens efficaces pour carte pour fonctionner sur les colonnes (ou lignes) de np.arrays (peut-être comme np.vectorize, qui ressemble plus à un décorateur)?

  2. 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 pour A? 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 pour A.
  • 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 le n * (n - 1) / 2 valeurs uniques, vous êtes après, mais il est souvent plus rapide de faire un vectorisé calcul de la n * 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 4D histogramdd... 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 être H = -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.

InformationsquelleAutor nahsivar | 2013-12-10