贝叶斯定理是关于随机事件A和B的条件概率和边缘概率的一则定理。
如上所示,其中P(A|B)是在B发生的情况下A发生的可能性。在贝叶斯定理中,每个名词都有约定俗成的名称:
- P(A)是A的先验概率或边缘概率。之所以称为"先验"是因為它不考虑任何B方面的因素。
- P(A|B)是已知B发生后A的条件概率(直白来讲,就是先有B而后才有A),也由于得自B的取值而被称作A的后验概率。
- P(B|A)是已知A发生后B的条件概率(直白来讲,就是先有A而后才有B),也由于得自A的取值而被称作B的后验概率。
- P(B)是B的先验概率或边缘概率,也作标准化常量(normalized constant)。
朴素贝叶斯分类是一种十分简单的分类算法,叫它朴素贝叶斯分类是因为这种方法的思想
真的很朴素,朴素贝叶斯的思想基础是这样的:对于给出的待分类项,
求解在此项出现的条件下各个类别出现的概率,哪个最大,就认为此待分类项属于哪个类别。过程如下:
1、找到一个已知分类的待分类项集合,这个集合叫做
训练样本集
。
2、统计得到在各类别下各个特征属性的条件概率估计。即
3、如果各个特征属性是条件独立的,则根据贝叶斯定理有如下推导。
因为分母对于所有类别为常数,因为我们只要将分子最大化皆可。又因为各特征属性是条件独立的,所以有:
根据朴素贝叶斯公式,每个测试样例属于某个类别的概率 = 所有测试样例包含特征词类条件概率P(tk|c)之积 * 先验概率P(c)
在具体计算类条件概率和先验概率时,朴素贝叶斯分类器有两种模型:
(1) 多项式模型( Multinomial Model )–以单词为粒度
类条件概率P(tk|c) = (类c下单词tk在各个文档中出现过的次数之和 + 1) / (类c下单词总数 + 训练样本中不重复特征词总数)
先验概率P(c) = 类c下的单词总数 / 整个训练样本的单词总数
先验概率P(c) = 类c下的单词总数 / 整个训练样本的单词总数
(2) 伯努利模型(Bernoulli Model)–以文件为粒度
类条件概率P(tk|c) = (类c下包含单词tk的文件数 + 1) / (类c下文件总数+2)
先验概率P(c) = 类c下文件总数 / 整个训练样本的文件总数
多项式模型Java简单实现
public class MultinomialBuilder extends AbstractBuilder {
@Override
public void build() {
DataSet dataSet = obtainDataSet();
List<Document> trainData = dataSet.getTrainData();
Map<String, Map<String, Integer>> cmap =
DocumentHelper.wordsInCategoriesStatistics(trainData);
int w_all_count = 0;
for (Map.Entry<String, Map<String, Integer>> entry : cmap.entrySet()) {
Map<String, Integer> wmap = entry.getValue();
for (Map.Entry<String, Integer> kv : wmap.entrySet()) {
w_all_count += kv.getValue();
}
}
List<Document> testData = dataSet.getTestData();
for (Document doc : testData) {
double max = 0;
String category = null;
for (Map.Entry<String, Map<String, Integer>> entry : cmap.entrySet()) {
Map<String, Integer> wmap = entry.getValue();
double cw_count = 0, cw_all_count = 0;
for (Map.Entry<String, Integer> kv : wmap.entrySet()) {
cw_count += 1;
cw_all_count += kv.getValue();
}
cw_all_count += cw_count;
double ptc = 0;
for (String word : doc.getWordSet()) {
double t_count = null == wmap.get(word) ? 1 : wmap.get(word) + 1;
ptc = ptc == 0 ? t_count / cw_all_count : ptc * (t_count / cw_all_count);
}
double pc = cw_all_count / w_all_count;
double p = ptc * pc;
System.out.println(ptc + ":" + pc + ":" + p);
if (p > max) {
max = p;
category = entry.getKey();
}
}
System.out.println("doc category: " + doc.getCategory() + " predict: " + category);
}
}
public static void main(String[] args) {
new MultinomialBuilder().build();
}
}
伯努利模型Java简单实现
public class BernoulliBuilder extends AbstractBuilder {
@Override
public void build() {
DataSet dataSet = obtainDataSet();
List<Document> trainData = dataSet.getTrainData();
Map<String, List<Document>> cmap = DocumentHelper.docsInCategoriesStatistics(trainData);
int c_all_count = trainData.size();
List<Document> testData = dataSet.getTestData();
for (Document doc : testData) {
double max = 0;
String category = null;
for (Map.Entry<String, List<Document>> entry : cmap.entrySet()) {
List<Document> docs = entry.getValue();
double c_count = docs.size() + 2;
double ptc = 0;
for (String word : doc.getWordSet()) {
double t_count = DocumentHelper.wordInDocsStatistics(word, docs) + 1;
ptc = ptc == 0 ? t_count / c_count : ptc * (t_count / c_count);
}
double pc = c_count / c_all_count;
double p = ptc * pc;
System.out.println(ptc + ":" + pc + ":" + p);
if (p > max) {
max = p;
category = entry.getKey();
}
}
System.out.println(doc.getName());
System.out.println("doc category: " + doc.getCategory() + " predict: " + category);
}
}
public static void main(String[] args) {
new BernoulliBuilder().build();
}
}
代码托管:https://github.com/fighting-one-piece/repository-datamining.git