2014-07-10 15 views
8

Sto avendo alcuni problemi di attuazione della funzione di informazione reciproca che le librerie di apprendimento automatico di Python forniscono, in particolare: sklearn.metrics.mutual_info_score (labels_true, labels_pred, contingenza = None)di Python di mutuo scambio di informazioni

(http://scikit-learn.org/stable/modules/generated/sklearn.metrics.mutual_info_score.html)

sto cercando di implementare l'esempio che trovo nel sito di tutorial Stanford NLP:

example

Il sito si trova qui: http://nlp.stanford.edu/IR-book/html/htmledition/mutual-information-1.html#mifeatsel2

Il problema è che continuo a ottenere risultati diversi, senza capire ancora il motivo.

Ricevo il concetto di Informazioni mutue e selezione delle funzionalità, ma non capisco come sia implementato in Python. Quello che faccio è che fornisco il metodo mutual_info_score con due array basati sull'esempio del sito NLP, ma produce risultati diversi. L'altro fatto interessante è che, comunque, si gioca e si cambia il numero su quegli array che è più probabile che si ottenga lo stesso risultato. Dovrei usare un'altra struttura dati specifica per Python o qual è il problema alla base di questo? Se qualcuno ha usato questa funzione con successo in passato sarebbe di grande aiuto per me, grazie per il tuo tempo.

+1

si dovrebbe fornirci esempio di ciò che è esattamente "sbagliato" di lavoro. – lejlot

risposta

8

Ho riscontrato lo stesso problema oggi. Dopo alcune prove, ho trovato la vera ragione: prendi log2 se segui rigorosamente il tutorial sulla PNL, ma sklearn.metrics.mutual_info_score usa logaritmo naturale (base e, il numero di Eulero). Non ho trovato questo dettaglio nella documentazione sklearn ...

ho verificato questo:

import numpy as np 
def computeMI(x, y): 
    sum_mi = 0.0 
    x_value_list = np.unique(x) 
    y_value_list = np.unique(y) 
    Px = np.array([ len(x[x==xval])/float(len(x)) for xval in x_value_list ]) #P(x) 
    Py = np.array([ len(y[y==yval])/float(len(y)) for yval in y_value_list ]) #P(y) 
    for i in xrange(len(x_value_list)): 
     if Px[i] ==0.: 
      continue 
     sy = y[x == x_value_list[i]] 
     if len(sy)== 0: 
      continue 
     pxy = np.array([len(sy[sy==yval])/float(len(y)) for yval in y_value_list]) #p(x,y) 
     t = pxy[Py>0.]/Py[Py>0.] /Px[i] # log(P(x,y)/(P(x)*P(y)) 
     sum_mi += sum(pxy[t>0]*np.log2(t[t>0])) # sum (P(x,y)* log(P(x,y)/(P(x)*P(y))) 
    return sum_mi 

Se si modifica questa np.log2-np.log, penso che darebbe la stessa risposta sklearn. L'unica differenza è che quando questo metodo restituisce 0, sklearn restituirà un numero molto vicino a 0. (E ovviamente, usa sklearn se non ti interessa la base di log, il mio pezzo di codice è solo per demo, dà scarso performance ...)

FYI, 1) sklearn.metrics.mutual_info_score accetta liste e np.array; 2) il sklearn.metrics.cluster.entropy utilizza anche il log, non log2

Modifica: per quanto riguarda lo "stesso risultato", non sono sicuro di cosa intendi realmente. In generale, i valori nei vettori non contano davvero, è la "distribuzione" dei valori che conta. Ti preoccupi di P (X = x), P (Y = y) e P (X = x, Y = y), non il valore x, y.

+1

potresti mostrare un esempio in esecuzione? Ho ottenuto valori diversi su [1,2,2], [1,2,2] come argomenti per questa routine e mutual_info_score – user1603472

-2

Il codice qui sotto dovrebbe fornito un risultato :0.00011053558610110256

c=np.concatenate([np.ones(49), np.zeros(27652), np.ones(141), np.zeros(774106) ]) 
t=np.concatenate([np.ones(49), np.ones(27652), np.zeros(141), np.zeros(774106)]) 

computeMI(c,t)