朴素贝叶斯
代码实现:
# naive Bayes algorithm + add-k smoothingimport math, collectionsADDK = 1# D: documents# C: classes# return log P(c) and log P(w|c)def train_naive_bayes(D, C, inlog=False):V = vocabulary(D) #vocabulary of Dprint("|V| =", len(V))prior = collections.defaultdict()likelihood = collections.defaultdict(dict)Ndoc = len(D) # number of documents in Dfor c in C:# calculate P(c)Dc = [d for d in D if d.inclass(c)]Nc = len(Dc)# number of documents from D in class cif inlog:prior[c] = math.log(Nc/Ndoc) # log P(c)else:prior[c] = Nc/Ndoc# bigdoc contains all the documents from D in class cbigdoc = " ".join(d.text for d in Dc)# calculate P(w|c)for w in V: # w == word# occurrences() calculate the occurrences of w in bigdoc[c]count_wc = occurrences(bigdoc, w)if inlog:likelihood[w][c] = math.log((count_wc + ADDK)/(sum(occurrences(bigdoc, wd) + ADDK for wd in V))) # log P(w|c)else:likelihood[w][c] = (count_wc + ADDK)/(sum(occurrences(bigdoc, wd) + ADDK for wd in V)) # P(w|c)return prior, likelihood, V# return best cdef test_naive_bayes(testdoc, logprior, loglikelihood, C, V, inlog=False):sum_ = {}for c in C:sum_[c] = logprior[c]words = [word.strip() for word in testdoc.split(" ")]for word in words:if word in V: # remove unknownif inlog:sum_[c] += loglikelihood[word][c]else:sum_[c] *= loglikelihood[word][c]#print(sum_)return argmaxc(sum_)## utilsdef vocabulary(D, sep=" "):return {ele.strip() for d in D for ele in d.text.split(" ") if ele.strip()}def occurrences(doc, w):return [ele.strip() for ele in doc.split(" ")].count(w)def argmaxc(ps):return max(ps, default=None, key=lambda c: ps[c])##### 测试class Document():def __init__(self, text, c):self.text = textself.c = cdef inclass(self, c):return self.c == c## 例子来源于 《speech and language processing》4.3def testcase1():Ds = [Document("just plain boring", "-"),Document("entirely predictable and lacks energy", "-"),Document("no surprises and very few laughs", "-"),Document("very powerful", "+"),Document("the most fun film of the summer", "+"),]Cs = ["+", "-"]prior, likelihood, V = train_naive_bayes(Ds, Cs)for c in Cs:print("P('%s') = %f" % (c, prior[c]))for w in likelihood:print("P('%s'|'%s') = %f" % (w, c, likelihood[w][c]))# test doctestdoc = "predictable with no fun"predict = test_naive_bayes(testdoc, prior, likelihood, Cs, V)print("predict class:", predict)if __name__ == "__main__":testcase1()
