diff --git a/docs/4.朴素贝叶斯.md b/docs/4.朴素贝叶斯.md index 0c1f0f6e..23f985e4 100644 --- a/docs/4.朴素贝叶斯.md +++ b/docs/4.朴素贝叶斯.md @@ -1,50 +1,24 @@ # 4) 朴素贝叶斯 - - * 假设: 特征之间强(朴素)独立 * 概率模型 - * P(C|F1F2...Fn) = P(F1F2...Fn|C)P(C) / P(F1F2...Fn) - * 由于对于所有类别,P(F1F2...Fn)都是相同的,比较P(C|F1F2...Fn)只用比较P(F1F2...Fn|C)P(C)就好了 - * 朴素贝叶斯的特点 - * 优点:在数据较少的情况下仍然有效,可以处理多类别问题 - * 缺点:对于输入数据的准备方式较为敏感 - * 适用数据类型:标称型数据 - * 朴素贝叶斯的一般过程 - * 收集数据:可以使用任何方法 - * 准备数据:需要数值型或者布尔型数据 - * 分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好。 - * 训练算法:计算不同的独立特征的条件概率 - * 测试算法:计算错误率 - * 使用算法:文本分类等 - * 优化 - * 为了避免一个概率为0导致P(F1|C)*P(F2|C)....P(Fn|C)整个为0,所以优化为将所有词的出现数都初始化为1,并将分母初始化为2. - * 由于大部分因子比较小,乘积之后得到的数不易比较,程序误差较大。所以取对数后可将乘法转化为加法:P(F1|C)*P(F2|C)....P(Fn|C)P(C) -> log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C)) - * 总结 - * 这一块代码比较乱,最好先把公式理一理再看 - * 可以参考一下[阮一峰的博客](http://www.ruanyifeng.com/blog/2013/12/naive_bayes_classifier.html) - - - - - diff --git a/src/python/04.NaiveBayes/bayes.py b/src/python/04.NaiveBayes/bayes.py index 138e7bb1..096f7b43 100755 --- a/src/python/04.NaiveBayes/bayes.py +++ b/src/python/04.NaiveBayes/bayes.py @@ -64,8 +64,8 @@ def _trainNB0(trainMatrix, trainCategory): # 侮辱性文件的出现概率 pAbusive = sum(trainCategory) / float(numTrainDocs) # 构造单词出现次数列表 - p0Num = zeros(numWords)[0,0,0,.....] - p1Num = zeros(numWords)[0,0,0,.....] + p0Num = zeros(numWords) # [0,0,0,.....] + p1Num = zeros(numWords) # [0,0,0,.....] # 整个数据集单词出现总数 p0Denom = 0.0 @@ -91,22 +91,28 @@ def trainNB0(trainMatrix, trainCategory): :param trainCategory: 文件对应的类别 :return: """ - # 文件数 + # 总文件数 numTrainDocs = len(trainMatrix) - # 单词数 + # 总单词数 numWords = len(trainMatrix[0]) # 侮辱性文件的出现概率 pAbusive = sum(trainCategory) / float(numTrainDocs) # 构造单词出现次数列表 + # p0Num 正常的统计 + # p1Num 侮辱的统计 p0Num = ones(numWords)#[0,0......]->[1,1,1,1,1.....] p1Num = ones(numWords) - # 整个数据集单词出现总数,2.0根据样本/实际调查结果调整分母的值 + # 整个数据集单词出现总数,2.0根据样本/实际调查结果调整分母的值(2主要是避免分母为0,当然值可以调整) + # p0Denom 正常的统计 + # p1Denom 侮辱的统计 p0Denom = 2.0 p1Denom = 2.0 for i in range(numTrainDocs): if trainCategory[i] == 1: + # 累加辱骂词的频次 p1Num += trainMatrix[i] + # 对每篇文章的辱骂的频次 进行统计汇总 p1Denom += sum(trainMatrix[i]) else: p0Num += trainMatrix[i] @@ -120,7 +126,10 @@ def trainNB0(trainMatrix, trainCategory): def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1): """ - 使用算法 + 使用算法: + # 将乘法转坏为加法 + 乘法:P(C|F1F2...Fn) = P(F1F2...Fn|C)P(C)/P(F1F2...Fn) + 加法:P(F1|C)*P(F2|C)....P(Fn|C)P(C) -> log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C)) :param vec2Classify: 待测数据[0,1,1,1,1...] :param p0Vec: 类别1,即侮辱性文档的[log(P(F1|C1)),log(P(F2|C1)),log(P(F3|C1)),log(P(F4|C1)),log(P(F5|C1))....]列表 :param p1Vec: 类别0,即正常文档的[log(P(F1|C0)),log(P(F2|C0)),log(P(F3|C0)),log(P(F4|C0)),log(P(F5|C0))....]列表 @@ -155,6 +164,7 @@ def testingNB(): # 3. 计算单词是否出现并创建数据矩阵 trainMat = [] for postinDoc in listOPosts: + # 返回m*len(myVocabList)的矩阵, 记录的都是0,1信息 trainMat.append(setOfWords2Vec(myVocabList, postinDoc)) # 4. 训练数据 p0V, p1V, pAb = trainNB0(array(trainMat), array(listClasses)) @@ -167,4 +177,5 @@ def testingNB(): print testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb) -testingNB() +if __name__ == "__main__": + testingNB()