Evita errori numerici nel metodo Naive Bayes

1

Sto implementando il metodo Naive Bayes con distribuzione gaussiana.

Il problema che ho è che la varianza usata sulla curva gaussiana (calcolata da un set di allenamento) è VERAMENTE piccola. Sono nell'ordine di e-07. Ciò significa l'intera equazione,

(1/:math.sqrt(2*:math.pi*:math.sqrt(variance))) *
:math.exp(-0.5*(:math.pow(elem - mean, 2) / variance))

produce valori molto alti (come 500 o anche più). Questo diventa un problema in seguito, quando moltiplicherò ogni probabilità p (x | C) insieme (è un vettore di 256 caratteristiche).

Ho sentito che è possibile usare i logaritmi per evitare questo tipo di numeri. Ho cercato su google ma non ho trovato nulla relativo all'argomento. Qualcuno lo sa?

    
posta lhahn 24.05.2015 - 03:00
fonte

3 risposte

5

Lavorare con le probabilità di log aiuta a risolvere il problema dei valori intermedi che traboccano (e che scorrono). Invece di calcolare L = P(x1|C)P(x2|C)... , calcoli log L = log P(x1|C) + log P(x2|C) + ... . Puoi fare due cose con log L :

  1. Se stai cercando di massimizzare la verosimiglianza, puoi massimizzare direttamente la probabilità di log invece che log è monotona e in aumento.

  2. Se vuoi una probabilità normalizzata L/Z in [0,1] , puoi calcolarla come exp(log L - log Z) , che è possibile anche se L e Z sono troppo grandi per adattarsi al tuo punto mobile tipo.

Nella mia esperienza questo trucco è spesso necessario quando si implementano modelli grafici probabilistici.

    
risposta data 23.06.2015 - 08:28
fonte
2

Il tuo problema è probabilmente un refuso: calcoli 1 / sqrt(2 * pi * sqrt(variance)) , mentre la formula ha previsto 1 / sqrt(2 * pi * variance**2) . (La radice quadrata dalla varianza presa due volte è altamente improbabile in un fattore di normalizzazione.)

Mentre ci siamo, non credo che gli errori di arrotondamento abbiano nulla a che fare con il problema della tua formula.

Con l'intervallo utilizzabile di un numero a virgola mobile a 64 bit compreso tra 1e + 308, I ' d non chiamare 1e-7 "veramente piccolo". Anche se utilizzi float a 32 bit (con intervallo intorno a 1e + 38), le cose non sono poi così male.

Le fonti comuni di errori di arrotondamento sono operazioni con grandezze molto diverse: 1e+15 + 0.2 ti dà un numero che improvvisamente è 1000000000000000.25 . Inoltre, sqrt , exp e pow sono calcoli complessi che rimuovono parte della precisione. Scommetto che pow(x, 2) differisce leggermente da x * x per molti valori di x .

Ovviamente, log(a * b) = log(a) + log(b) e exp(a + b) = exp(a) * exp(b) . Tuttavia, non vedo come questo possa aiutare il tuo caso: il calcolo di exp due volte introduce più errori del calcolo di una volta.

    
risposta data 24.05.2015 - 04:59
fonte
0

Il tuo problema è formato in virgola mobile. Sono fondamentalmente memorizzati come Sign * Man * 2 ^ Exp. Per i tipi a virgola mobile a 32 bit, sono disponibili solo 9 bit di esponente e anche FP a 64 bit utilizza solo 11 bit.

Ma una volta preso il registro di quel valore, si è effettivamente utente il campo di grande ampiezza per memorizzare il tuo esponente originale.

C'è anche un'altra alternativa. Crea il tuo formato FP personalizzato, nel formato 2 ^ (- Esp / 4294967296). operator+ è abbastanza impreciso per questo tipo, ma operator* è solo una questione di aggiunta di esponenti (integrali) e pow è una moltiplicazione di esponenti.

    
risposta data 23.06.2015 - 15:51
fonte

Leggi altre domande sui tag