Получение вероятности класса с использованием наивного Байеса

Я пытаюсь классифицировать ввод с помощью двух классов, вот код. dino и crypto — это два класса:

for w, cnt in list(counts.items()): #count is dict with word and it's count value
    p_word = vocab[w] / sum(vocab.values()) 
    p_w_given_dino = (word_counts["dino"].get(w, 0.0) + 1) / (sum(word_counts["dino"].values()) + v) 
    p_w_given_crypto = (word_counts["crypto"].get(w, 0.0) + 1) / (sum(word_counts["crypto"].values()) + v)

    log_prob_dino += math.log(cnt * p_w_given_dino / p_word)
    log_prob_crypto += math.log(cnt * p_w_given_crypto / p_word)

print("Score(dino)  :", math.exp(log_prob_dino + math.log(prior_dino)))
print("Score(crypto):", math.exp(log_prob_crypto + math.log(prior_crypto)))

Другой подход:

prior_dino = (priors["dino"] / sum(priors.values()))
prior_crypto = (priors["crypto"] / sum(priors.values()))
for w, cnt in list(counts.items()):
    p_word = vocab[w] / sum(vocab.values())
    p_w_given_dino = (word_counts["dino"].get(w, 0.0) + 1) / (sum(word_counts["dino"].values()) + v) 
    p_w_given_crypto = (word_counts["crypto"].get(w, 0.0) + 1) / (sum(word_counts["crypto"].values()) + v)
    prob_dino *= p_w_given_dino
    prob_crypto *= p_w_given_crypto
t_prior_dino = prob_dino * prior_dino
t_prior_crypto = prob_crypto * prior_crypto

При втором подходе я получил очень маленькие значения.

Какой из них правильный, или они оба верны?


comment
Второй подход умножает вероятности, которые могут быть чуть выше нуля, давая общий результат после умножения, близкий к нулю. Использование log() позволяет избежать этой проблемы.   -  person aleju    schedule 30.07.2015
comment
@ user3760780: результат обоих значителен, верно? просто способ представления меняется   -  person nlper    schedule 30.07.2015
comment
После использования log() вы все равно должны получить наивысший балл для наиболее вероятного класса. Кроме того, я думаю, что вы не используете p_word во втором подходе. Вы также используете cnt только в первом подходе.   -  person aleju    schedule 30.07.2015


Ответы (1)


Это полностью равнозначные подходы. Однако первый вариант предпочтительнее, так как работа с логарифмами вероятностей делает весь процесс более численно устойчивым. Результаты должны быть идентичными (вплоть до числовых ошибок).

Однако кажется, что у вас есть ошибки во втором подходе

prob_dino *= p_w_given_dino

не использует тот факт, что у вас есть cnt вхождений; это должно быть что-то вроде

prob_dino *= pow(p_w_given_dino, cnt) 
person lejlot    schedule 30.07.2015
comment
о, спасибо, приятель, на самом деле я думал, что это будет умножаться при повторении цикла for, я не заметил, что я уже получаю значение счетчика, и каждое слово повторяется только один раз - person nlper; 31.07.2015