朴素贝叶斯

代码实现:

  1. # naive Bayes algorithm + add-k smoothing
  2. import math, collections
  3. ADDK = 1
  4. # D: documents
  5. # C: classes
  6. # return log P(c) and log P(w|c)
  7. def train_naive_bayes(D, C, inlog=False):
  8. V = vocabulary(D) #vocabulary of D
  9. print("|V| =", len(V))
  10. prior = collections.defaultdict()
  11. likelihood = collections.defaultdict(dict)
  12. Ndoc = len(D) # number of documents in D
  13. for c in C:
  14. # calculate P(c)
  15. Dc = [d for d in D if d.inclass(c)]
  16. Nc = len(Dc)# number of documents from D in class c
  17. if inlog:
  18. prior[c] = math.log(Nc/Ndoc) # log P(c)
  19. else:
  20. prior[c] = Nc/Ndoc
  21. # bigdoc contains all the documents from D in class c
  22. bigdoc = " ".join(d.text for d in Dc)
  23. # calculate P(w|c)
  24. for w in V: # w == word
  25. # occurrences() calculate the occurrences of w in bigdoc[c]
  26. count_wc = occurrences(bigdoc, w)
  27. if inlog:
  28. likelihood[w][c] = math.log((count_wc + ADDK)/(sum(occurrences(bigdoc, wd) + ADDK for wd in V))) # log P(w|c)
  29. else:
  30. likelihood[w][c] = (count_wc + ADDK)/(sum(occurrences(bigdoc, wd) + ADDK for wd in V)) # P(w|c)
  31. return prior, likelihood, V
  32. # return best c
  33. def test_naive_bayes(testdoc, logprior, loglikelihood, C, V, inlog=False):
  34. sum_ = {}
  35. for c in C:
  36. sum_[c] = logprior[c]
  37. words = [word.strip() for word in testdoc.split(" ")]
  38. for word in words:
  39. if word in V: # remove unknown
  40. if inlog:
  41. sum_[c] += loglikelihood[word][c]
  42. else:
  43. sum_[c] *= loglikelihood[word][c]
  44. #print(sum_)
  45. return argmaxc(sum_)
  46. ## utils
  47. def vocabulary(D, sep=" "):
  48. return {ele.strip() for d in D for ele in d.text.split(" ") if ele.strip()}
  49. def occurrences(doc, w):
  50. return [ele.strip() for ele in doc.split(" ")].count(w)
  51. def argmaxc(ps):
  52. return max(ps, default=None, key=lambda c: ps[c])
  53. ##### 测试
  54. class Document():
  55. def __init__(self, text, c):
  56. self.text = text
  57. self.c = c
  58. def inclass(self, c):
  59. return self.c == c
  60. ## 例子来源于 《speech and language processing》4.3
  61. def testcase1():
  62. Ds = [
  63. Document("just plain boring", "-"),
  64. Document("entirely predictable and lacks energy", "-"),
  65. Document("no surprises and very few laughs", "-"),
  66. Document("very powerful", "+"),
  67. Document("the most fun film of the summer", "+"),
  68. ]
  69. Cs = ["+", "-"]
  70. prior, likelihood, V = train_naive_bayes(Ds, Cs)
  71. # print
  72. for c in Cs:
  73. print("P('%s') = %f" % (c, prior[c]))
  74. for w in likelihood:
  75. print("P('%s'|'%s') = %f" % (w, c, likelihood[w][c]))
  76. # test doc
  77. testdoc = "predictable with no fun"
  78. predict = test_naive_bayes(testdoc, prior, likelihood, Cs, V)
  79. print("predict class:", predict)
  80. if __name__ == "__main__":
  81. testcase1()