2016-05-20 4 views
2

Я строю текстовый классификатор Naive Bayes с нуля на Python, и я знаю, что, столкнувшись с продуктом очень малых вероятностей, использование логарифма над вероятностями является хорошим выбор.Усложнение с использованием логарифмических вероятностей - классификатор текста Naive Bayes

Проблема в том, что математическая функция, которую я использую, имеет суммирование по продукту этих чрезвычайно малых вероятностей.

Чтобы быть конкретным, я пытаюсь вычислить полные вероятности слов, учитывая компонент смеси (класс) по всем классам.

Непосредственно добавление журналов этих полных вероятностей неверно, поскольку журнал суммы не равен сумме журналов.

Чтобы привести пример, скажем, что у меня есть 3 класса, 2000 слов и 50 документов. Тогда у меня есть матрица вероятности слов, называемая wordprob с 2000 строк и 3 столбца.

Алгоритм для полной вероятности слов в этом примере будет выглядеть следующим образом:

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 

Что в конечном итоге происходит, что prob_product становится равной 0 на многих итерации из-за многие малые вероятности умножая друг с другом.

Поскольку я не могу легко решить это с помощью журналов (из-за суммирования спереди), я совершенно не знаю.

Любая помощь будет очень признательна.

+1

Для этой цели NumPy имеет функцию '' logaddexp' '(http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.logaddexp.html). –

+0

(И 'scipy.misc.logsumexp' также может представлять интерес.) –

ответ

1

Я думаю, что вы можете быть лучше, чтобы держать все в журналах. Первая часть этого, чтобы вычислить журнал продукта, просто складывает лог терминов. Второй бит, вычисляющий журнал сумм экспонентов журналов, немного сложнее.

Один из способов будет хранить каждый из журналов продуктов в массиве, а затем вам нужна функция, которая, учитывая массив L с п элементов, будет вычислять

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

Один из способов сделать это найти максимум, M сказать, L; немного алгебра показывает

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

каждое из слагаемых L [I] -M неположителен так переполнения не может произойти. Underflow не проблема, так как для них exp будет возвращать 0. По крайней мере один из них (тот, где L [i] равен M) будет равен нулю, поэтому он будет exp, и мы получим что-то, что мы можем передать журнал.Другими словами, оценка формулы будет без проблем.

Если у вас есть функция log1p (log1p (x) = log (1 + x)), вы можете получить некоторую точность, опуская (только один!) I, где L [i] == M из суммы, и передавая сумму log1p вместо log.

+0

Это решает. Благодаря! –

1

Ваш вопрос кажется на математической стороне вещей, а не на его кодировании. Я не совсем понял, какова ваша проблема, но сумма журналов равна журналу продуктов. Не знаю, поможет ли это. Кроме того, вы вычисляете один prob_product для каждого j, но вы используете только последний (и вы повторно инициализируете его). вы хотели сделать одну из двух вещей: либо инициализировать ее перед j-циклом, либо использовать ее до того, как вы увеличите j. Наконец, я не считаю, что вам нужно инициализировать сумму, если это не является частью еще одного цикла, который вы здесь не показываете.

Это все, что у меня есть пока. Извините за длинный пост и никакого кода.

+0

Спасибо за отзыв. Как только я добавлю этот prob_product в свою сумму, мне нужно его повторно инициализировать, чтобы начать новый продукт нового столбца j. –

+0

@ C.Steyn Точно. Более подробно о косметической стороне вещей и просто упомянуть об этом, диапазон (0,3) точно такой же, как диапазон (3), и увеличивающиеся переменные могут быть выполнены следующим образом: prob_product * = wordprob [i, j] sum + = prob_product –

+0

Это очень удобный совет, спасибо. –