贝叶斯分类算法基于托马斯贝叶斯发明的贝叶斯定理,他提出的贝叶斯定理对于现代几率论和数理统计的发展有重要的影响。算法
贝叶斯定理:ui
对于随机事件A和B:A发生的几率为P(A),B发生的几率为P(B),在B发生的状况下,A发生的几率为P(A|B)。A和B一块儿发生的联合几率为P(AB)。有:P(A|B) X P(B) = P(AB) = P(B|A) X P(A),则有:this
P(A|B) = P(B|A)P(A) / P(B)spa
文本分类(Text Categorization)是指计算机将一片文档归于预先给定的某一类或几类的过程。文本分类的特征提取过程是分词。目前比较好的中文分词器有中科院的ictclas,庖丁,IK等等。通过分词后,每一个词就是一个特征。分词中能够本身配置停用词库,扩展词库等。特征选择有诸如TF-IDF,CHI等特征选择算法,就不在此赘述。orm
朴素贝叶斯计算先验几率P(C)和条件几率P(X|C)的方法有两种:多项式模型和伯努利模型。二者在计算的时候有两点差异:多项式会统计词频,而伯努利认为单词出现就记为1,没出现记为0,能够看到一个是基于词频,一个是基于文档频率;伯努利在分类时,将词库中的没有出如今待分类文本的词做为反方考虑。索引
在计算条件几率时,当待分类文本中的某个词没有出如今词库中时,几率为0,会致使很严重的问题,须要考虑拉普拉斯平滑(laplace smoothing):它是将全部词出现的次数+1,再进行统计。事件
再一个问题就是几率过小而词数太多,会超double,用log将乘法转成加法。文档
多项式朴素贝叶斯算法伪代码以下:get
public class NaiveBayesManager { it
/**关键词索引 关键词-索引*/
private Map<String, Integer> termIndex;
/**类的索引 类名称-索引*/
private Map<String, Integer> classIndex;
/** 类名 */
private List<String> className;
/**某类的文档中全部特征出现的总次数*/
private int classTermsCount[];
/**某类的文档中某特征出现的次数之和*/
private int classKeyMap[][];
/**类的个数*/
private int numClasses = 0;
/**训练样本的全部特征(出现屡次只算一个)*/
private int vocabulary = 0;
/**训练样本的特征总次数*/
private int totalTermsCount = 0;
/** 创建类名和特征名的索引 */
private void buildIndex(List<Corpus> orignCorpus) {
classIndex = new HashMap<String, Integer>();
termIndex = new HashMap<String, Integer>();
className = new ArrayList<String>();
Integer idTerm = new Integer(-1);
Integer idClass = new Integer(-1);
for (int i = 0; i < orignCorpus.size(); ++i) {
Corpus corpus = orignCorpus.get(i);
List<String> terms = corpus.getSegments();
String label = corpus.getCat();
if (!classIndex.containsKey(label)) {
idClass++;
classIndex.put(label, idClass);
className.add(label);
}
for (String term : terms) {
totalTermsCount++;
if (!termIndex.containsKey(term)) {
idTerm++;
termIndex.put(term, idTerm);
}
}
}
vocabulary = termIndex.size();
numClasses = classIndex.size();
}
/**
* 训练
* */
public void startTraining(List<Corpus> orignCorpus) {
buildIndex(orignCorpus);
classTermsCount = new int[numClasses + 1];
classKeyMap = new int[numClasses + 1][vocabulary + 1];
for (int i = 0; i < orignCorpus.size(); ++i) {
Corpus corpus = orignCorpus.get(i);
List<String> terms = corpus.getSegments();
String label = corpus.getCat();
Integer labelIndex = classIndex.get(label);
for (String term : terms) {
Integer wordIndex = termIndex.get(term);
classTermsCount[labelIndex]++;
classKeyMap[labelIndex][wordIndex]++;
}
}
}
public String classify(List<String> terms) {
int result = 0;
double maxPro = Double.NEGATIVE_INFINITY;
for (int cIndex = 0; cIndex < numClasses; ++cIndex) {
double pro = Math.log10(getPreProbability(cIndex));
for (String term : terms) {
pro += Math.log10(getClassConditonalProbability(cIndex, term));
}
if (maxPro < pro) {
maxPro = pro;
result = cIndex;
}
}
return className.get(result);
}
private double getPreProbability(int classIndex) {
double ret = 0;
int NC = classTermsCount[classIndex];
int N = totalTermsCount;
ret = 1.0 * NC / N;
return ret;
}
private double getClassConditonalProbability(int classIndex, String term) {
double ret = 0;
int NCX = 0;
int N = 0;
int V = 0;
Integer wordIndex = termIndex.get(term);
if (wordIndex != null)
NCX = classKeyMap[classIndex][wordIndex];
N = classTermsCount[classIndex];
V = vocabulary;
ret = (NCX + 1.0) / (N + V); //laplace smoothing. 拉普拉斯平滑处理
return ret;
}
public Map<String, Integer> getTermIndex() {
return termIndex;
}
public void setTermIndex(Map<String, Integer> termIndex) {
this.termIndex = termIndex;
}
public Map<String, Integer> getClassIndex() {
return classIndex;
}
public void setClassIndex(Map<String, Integer> classIndex) {
this.classIndex = classIndex;
}
public List<String> getClassName() {
return className;
}
public void setClassName(List<String> className) {
this.className = className;
}
public int[] getClassTermsCount() {
return classTermsCount;
}
public void setClassTermsCount(int[] classTermsCount) {
this.classTermsCount = classTermsCount;
}
public int[][] getClassKeyMap() {
return classKeyMap;
}
public void setClassKeyMap(int[][] classKeyMap) {
this.classKeyMap = classKeyMap;
}
public int getNumClasses() {
return numClasses;
}
public void setNumClasses(int numClasses) {
this.numClasses = numClasses;
}
public int getVocabulary() {
return vocabulary;
}
public void setVocabulary(int vocabulary) {
this.vocabulary = vocabulary;
}
public int getTotalTermsCount() {
return totalTermsCount;
}
public void setTotalTermsCount(int totalTermsCount) {
this.totalTermsCount = totalTermsCount;
}
public static String getSplitword() {
return splitWord;
}
}