2016-05-20 5 views
2

Ich konstruiere einen Naive Bayes Textklassifizierer von Grund auf neu in Python und mir ist bewusst, dass ein Logarithmus über die Wahrscheinlichkeiten ein gutes ist, wenn man ein Produkt von sehr kleinen Wahrscheinlichkeiten trifft Wahl.Komplikation mit Log-Wahrscheinlichkeiten - Naive Bayes Textklassifizierer

Das Problem jetzt ist, dass die mathematische Funktion, die ich verwende, eine Summierung über ein Produkt dieser extrem kleinen Wahrscheinlichkeiten hat.

Um genau zu sein, ich versuche, die gesamten Wortwahrscheinlichkeiten für eine Mischung Komponente (Klasse) über alle Klassen zu berechnen.

Die Protokolle dieser Gesamtwahrscheinlichkeiten einfach zu addieren ist falsch, da das Protokoll einer Summe nicht der Summe der Protokolle entspricht.

Um ein Beispiel zu geben, lassen Sie uns sagen, dass ich 3 Klassen, 2000 Wörter und 50 Dokumente habe. Dann habe ich ein Wort Wahrscheinlichkeitsmatrix namens Wordprob mit 2000 Zeilen und 3 Spalten.

Der Algorithmus für die gesamte Wortwahrscheinlichkeit in diesem Beispiel würde wie folgt aussehen:

sum = 0 
for j in range(0,3): 
    prob_product = 1 
    for i in words: #just the index of words from my vocabulary in this document 
     prob_product = prob_product*wordprob[i,j] 
    sum = sum + prob_product 

Was am Ende passiert ist, dass prob_product 0 auf vielen Iterationen wird durch viele kleine Wahrscheinlichkeiten miteinander multiplizieren.

Da ich das mit logs nicht so einfach lösen kann (wegen der summierung vorne) bin ich total ratlos.

Jede Hilfe wird sehr geschätzt.

+1

NumPy hat eine ['logaddexp'-Funktion] (http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.logaddexp.html) für genau diesen Zweck. –

+0

(Und 'scipy.misc.logsumexp' könnte auch von Interesse sein.) –

Antwort

1

Ich glaube, Sie können am besten alles in Protokollen zu halten. Der erste Teil davon, um das Protokoll des Produkts zu berechnen, ist nur das Protokoll der Begriffe. Das zweite Bit, das den Logarithmus der Summe der Exponentiale der Logs berechnet, ist etwas kniffliger.

Eine Möglichkeit wäre, jedem der Protokolle der Produkte in einem Array zu speichern, und dann müssen Sie eine Funktion, die bei einem gegebenen Array L mit n Elementen wird

S = log(sum { i=1..n | exp(L[i])}) 

Ein Weg berechnen zu tun Dies ist, um das Maximum, sagen wir, des L's zu finden; ein wenig Algebra zeigt

S = M + log(sum { i=1..n | exp(L[i]-M)}) 

Jeder der Begriffe L [i] -M ist kraft- so Überlauf nicht auftreten kann. Unterlauf ist kein Problem, denn für sie wird exp 0 zurückgeben. Mindestens einer von ihnen (der, wo L [i] M ist) wird Null sein, also ist exp ein Eins und wir werden mit etwas enden, an das wir gehen können Log.Mit anderen Worten, die Bewertung der Formel wird problemlos sein.

Wenn Sie die Funktion log1p (log1p (x) = log (1 + x)) haben, können Sie etwas Genauigkeit erreichen, indem Sie (nur ein!) I weglassen, wobei L [i] == M aus der Summe ist. und übergibt die Summe an log1p statt an log.

+0

Das löst es. Vielen Dank! –

1

Ihre Frage scheint eher auf der mathematischen Seite der Dinge als auf der Codierung davon. Ich habe nicht ganz herausgefunden, was Ihr Problem ist, aber die Summe der Protokolle entspricht dem Protokoll der Produkte. Weiß nicht, ob das hilft. Sie berechnen auch ein prob_product für jedes j, aber Sie verwenden nur das letzte (und Sie initialisieren es erneut). Sie wollten eines von zwei Dingen tun: entweder initialisieren Sie es vor der J-Schleife oder verwenden Sie es, bevor Sie j erhöhen. Schließlich sehe ich nicht, dass Sie die Summe initialisieren müssen, es sei denn, dies ist Teil einer weiteren Schleife, die Sie hier nicht anzeigen.

Das ist alles, was ich für jetzt habe. Sorry für den langen Post und keinen Code.

+0

Danke für die Rückmeldung. Sobald ich dieses prob_product zu meiner Summe hinzugefügt habe, muss ich es neu initialisieren, um ein neues Produkt der neuen Spalte j zu starten. –

+0

@ C.Steyn Genau. Mehr auf der kosmetischen Seite der Dinge jetzt und nur um es zu erwähnen, Bereich (0,3) ist genau das gleiche wie Bereich (3) und inkrementierende Variablen können wie getan werden: prob_product * = wordprob [i, j] Summe + = prob_product –

+0

Das ist sehr praktisch, danke. –

Verwandte Themen