# 基于朴素贝叶斯的文本分类算法

Text Classification Algorithm Based on Naive Bayes

Abstract:Usually there are three methods for text classification: SVM、KNN and Naïve Bayes. Naïve Bayes is easy to implement and fast, so it is widely used. This article introduced the theory of Naïve Bayes and discussed two popular models: multinomial model(MM) and Bernoulli model(BM) in details, implemented runnable code and performed some data tests.

Keywords: naïve bayes; text classification

### 第1章 贝叶斯原理

#### 1.2贝叶斯定理在分类中的应用

x的集合记为X，称为属性集。一般X和Y的关系是不确定的，你只能在某种程度上说x有多大可能性属于类y1，比如说x有80%的可能性属于类y1，这时可以把X和Y看做是随机变量，P(Y|X)称为Y的后验概率（posterior probability），与之相对的，P(Y)称为Y的先验概率（prior probability）[2]

P(cancer)=0.008,P(无cancer)=0.992

P(阳性|cancer)=0.98,P(阴性|cancer)=0.02

P(阳性|无cancer)=0.03，P(阴性|无cancer)=0.97

P(cancer | 阳性) = P(阳性 | cancer)p(cancer)=0.98*0.008 = 0.0078

P(无cancer | 阳性) =P(阳性 | 无cancer)*p(无cancer)=0.03*0.992 = 0.0298

#### 1.3朴素贝叶斯分类器

1、条件独立性

Good good study,Day day up.

2、朴素贝叶斯如何工作

3、估计分类属性的条件概率

P(xi|Y=y)怎么计算呢？它一般根据类别y下包含属性xi的实例的比例来估计。以文本分类为例，xi表示一个单词，P(xi|Y=y)=包含该类别下包含单词的xi的文章总数/ 该类别下的文章总数。

4、贝叶斯分类器举例

 Day Outlook Temperature Humidity Wind PlayTennis D1 Sunny Hot High Weak No D2 Sunny Hot High Strong No D3 Overcast Hot High Weak Yes D4 Rain Mild High Weak Yes D5 Rain Cool Normal Weak Yes D6 Rain Cool Normal Strong No D7 Overcast Cool Normal Strong Yes D8 Sunny Mild High Weak No D9 Sunny Cool Normal Weak Yes D10 Rain Mild Normal Weak Yes D11 Sunny Mild Normal Strong Yes D12 Overcast Mild High Strong Yes D13 Overcast Hot Normal Weak Yes D14 Rain Mild High Strong No

x = (Outlook = Sunny,Temprature = Cool,Humidity = High,Wind = Strong)

P(Outlook = Sunny|Yes)=2/9 P(Outlook = Sunny|No)=3/5

P(Temprature = Cool |Yes) =3/9 P(Temprature = Cool |No) =1/5

P(Humidity = High |Yes) =3/9 P(Humidity = High |No) =4/5

P(Wind = Strong |Yes) =3/9 P(Wind = Strong |No) =3/5

P(Yes | x)= P(Outlook = Sunny|Yes)×P(Temprature = Cool |Yes)×P(Humidity = High |Yes)×P(Wind = Strong |Yes)×P(Yes)=2/9×3/9×3/9×3/9×3/9×9/14=2/243=9/1701≈0.00529

P(No | x)= P(Outlook = Sunny|No)×P(Temprature = Cool |No)×P(Humidity = High |No)× P(Wind = Strong |No)×P(No)=3/5×1/5×4/5×3/5×5/14=18/875≈0.02057

5、条件概率的m估计

P(Outlook = Cloudy|Yes)=0/9=0 P(Outlook = Cloudy |No)=0/5=0

n是类yj中的样本总数，nc是类yj中取值xi的样本数，m是称为等价样本大小的参数，而p是用户指定的参数。如果没有训练集（即n=0），则P(xi|yj)=p, 因此p可以看作是在类yj的样本中观察属性值xi的先验概率。等价样本大小决定先验概率和观测概率nc/n之间的平衡[2]。

### 第2章 朴素贝叶斯文本分类算法

#### 2.1文本分类问题

={Beijing joins the World Trade Organization, China}

γ:X→C

#### 2.2多项式模型

1、基本原理

V是训练样本的单词表（即抽取单词，单词出现多次，只算一个），|V|则表示训练样本包含多少种单词。在这里，m=|V|, p=1/|V|。

P(tk|c)可以看作是单词tk在证明d属于类c上提供了多大的证据，而P(c)则可以认为是类别c在整体上占多大比例(有多大可能性)。

2、伪代码

//C，类别集合，D，用于训练的文本文件集合

TrainMultiNomialNB(C,D) {

// 单词出现多次，只算一个

V←ExtractVocabulary(D)

// 单词可重复计算

N←CountTokens(D)

for each c∈C

// 计算类别c下的单词总数

// N和Nc的计算方法和Introduction to Information Retrieval上的不同，个人认为

//该书是错误的，先验概率和类条件概率的计算方法应当保持一致

Nc←CountTokensInClass(D,c)

prior[c]←Nc/N

// 将类别c下的文档连接成一个大字符串

textc←ConcatenateTextOfAllDocsInClass(D,c)

for each t∈V

// 计算类c下单词t的出现次数

Tct←CountTokensOfTerm(textc,t)

for each t∈V

//计算P(t|c)

condprob[t][c]←

return V,prior,condprob

}

ApplyMultiNomialNB(C,V,prior,condprob,d) {

// 将文档d中的单词抽取出来，允许重复，如果单词是全新的，在全局单词表V中都

// 没出现过，则忽略掉

W←ExtractTokensFromDoc(V,d)

for each c∈C

score[c]←prior[c]

for each t∈W

if t∈Vd

score[c] *= condprob[t][c]

return max(score[c])

}

3、举例

 docId doc 类别 In c=China? 1 Chinese Beijing Chinese yes 2 Chinese Chinese Shanghai yes 3 Chinese Macao yes 4 Tokyo Japan Chinese no

P(Chinese | yes)=(5+1)/(8+6)=6/14=3/7

P(Japan | yes)=P(Tokyo | yes)= (0+1)/(8+6)=1/14

P(Chinese|no)=(1+1)/(3+6)=2/9

P(Japan|no)=P(Tokyo| no) =(1+1)/(3+6)=2/9

P(yes | d)=(3/7)3×1/14×1/14×8/11=108/184877≈0.00058417

P(no | d)= (2/9)3×2/9×2/9×3/11=32/216513≈0.00014780

#### 2.3伯努利模型

1、基本原理

P(c)= 类c下文件总数/整个训练样本的文件总数

P(tk|c)=(类c下包含单词tk的文件数+1)/(类c下单词总数+2)

2、伪代码

//C，类别集合，D，用于训练的文本文件集合

TrainBernoulliNB(C, D) {

// 单词出现多次，只算一个

V←ExtractVocabulary(D)

// 计算文件总数

N←CountDocs(D)

for each c∈C

// 计算类别c下的文件总数

Nc←CountDocsInClass(D,c)

prior[c]←Nc/N

for each t∈V

// 计算类c下包含单词t的文件数

Nct←CountDocsInClassContainingTerm(D,c,t)

//计算P(t|c)

condprob[t][c]←(Nct+1)/(Nct+2)

return V,prior,condprob

}

ApplyBernoulliNB(C,V,prior,condprob,d) {

// 将文档d中单词表抽取出来，如果单词是全新的，在全局单词表V中都没出现过，

// 则舍弃

Vd←ExtractTermsFromDoc(V,d)

for each c∈C

score[c]←prior[c]

for each t∈V

if t∈Vd

score[c] *= condprob[t][c]

else

score[c] *= (1-condprob[t][c])

return max(score[c])

}

3、举例

P(Japan | yes)=P(Tokyo | yes)=(0+1)/(3+2)=1/5

P(Beijing | yes)= P(Macao|yes)= P(Shanghai |yes)=(1+1)/(3+2)=2/5

P(Chinese|no)=(1+1)/(1+2)=2/3

P(Japan|no)=P(Tokyo| no) =(1+1)/(1+2)=2/3

P(Beijing| no)= P(Macao| no)= P(Shanghai | no)=(0+1)/(1+2)=1/3

P(yes | d)=P(yes)×P(Chinese|yes) ×P(Japan|yes) ×P(Tokyo|yes)×(1-P(Beijing|yes)) ×(1-P(Shanghai|yes))×(1-P(Macao|yes))

=3/4×4/5×1/5×1/5×(1-2/5) ×(1-2/5)×(1-2/5)=81/15625≈0.005

P(no | d)= 1/4×2/3×2/3×2/3×(1-1/3)×(1-1/3)×(1-1/3)=16/729≈0.022

### 第3章 代码详解

ChineseSpliter用于中文分词，StopWordsHandler用于判断一个单词是否是停止词，ClassifyResult用于保 存结果，IntermediateData用于预处理文本语料库，TrainnedModel用于保存训练后得到的数 据，NaiveBayesClassifier是基础类，包含了贝叶斯分类器的主要代码，MultiNomialNB是多项式模型，类似 的，BernoulliNB是伯努利模型，二者都继承自NaiveBayesClassifier，都只重写了父类的计算先验概率，类条件概率和后验概率 这3个函数。

#### 3.1中文分词

public String split(final String text, final String splitToken) {

String result = null;

try {

result = analyzer.segment(text, splitToken);

catch (IOException e) {

e.printStackTrace();

}

return result;

}

#### 3.2停止词处理

private static String[] stopWordsList = {

// 来自 c:\Windows\System32\NOISE.CHS

“的”, “一”, “不”, “在”, “人”, “有”, “是”, “为”, “以”, “于”, “上”, “他”, “而”,

“后”, “之”, “来”, “及”, “了”, “因”, “下”, “可”, “到”, “由”, “这”, “与”, “也”,

“此”, “但”, “并”, “个”, “其”, “已”, “无”, “小”, “我”, “们”, “起”, “最”, “再”,

“今”, “去”, “好”, “只”, “又”, “或”, “很”, “亦”, “某”, “把”, “那”, “你”, “乃”,

“它”,

// 来自网络

“要”, “将”, “应”, “位”, “新”, “两”, “中”, “更”, “我们”, “自己”, “没有”, ““”, “””,

“，”, “（”, “）”, “” };

public static boolean isStopWord(final String word) {

for (int i = 0; i < stopWordsList.length; ++i) {

if (word.equalsIgnoreCase(stopWordsList[i])) {

return true;

}

}

return false;

}

#### 3.3预处理数据

D:\Reduced

|– C000008

|– C000010

|– C000013

|– C000014

|– C000016

|– C000020

|– C000022

|– C000023

|– C000024

IntermediateData.java主要用于处理文本数据，将所需要的信息计算好，存放到数据库文件中。

public HashMap[] filesOfXC;

public int[] filesOfC;

public int files;

public HashMap[] tokensOfXC;

public int[] tokensOfC;

public int tokens;

public HashSet vocabulary;

IntermediateData d:\Reduced\ gbk d:\reduced.db

#### 3.3训练

protected void calculatePc() {

}

protected void calculatePxc() {

}

protected double calcProd(final String[] x, final int cj) {

return 0;

}

public final void train(String intermediateData, String modelFile) {

// 加载中间数据文件

model = new TrainnedModel(db.classifications.length);

model.classifications = db.classifications;

model.vocabulary = db.vocabulary;

// 开始训练

calculatePc();

calculatePxc();

db = null;

try {

// 用序列化，将训练得到的结果存放到模型文件中

ObjectOutputStream out = new ObjectOutputStream(

new FileOutputStream(modelFile));

out.writeObject(model);

out.close();

catch (IOException e) {

e.printStackTrace();

}

}

MultiNomialNB –t d:\reduced.db d:\reduced.mdl

#### 3.4分类

MultiNomialNB d:\reduced.mdl d:\temp.txt gbk

MultiNomialNB -r d:\reduced\ gbk d:\reduced.mdl

public final String classify(final String text) {

String[] terms = null;

// 中文分词处理(分词后结果可能还包含有停用词）

terms = textSpliter.split(text, ” “).split(” “);

// 去掉停用词，以免影响分类

terms = ChineseSpliter.dropStopWords(terms);

double probility = 0.0;

// 分类结果

List crs = new ArrayList();

for (int i = 0; i < model.classifications.length; i++) {

// 计算给定的文本属性向量terms在给定的分类Ci中的分类条件概率

probility = calcProd(terms, i);

// 保存分类结果

ClassifyResult cr = new ClassifyResult();

cr.classification = model.classifications[i]; // 分类

cr.probility = probility; // 关键字在分类的条件概率

System.out.println(“In process….”);

System.out.println(model.classifications[i] + “：” + probility);

}

// 找出最大的元素

ClassifyResult maxElem = (ClassifyResult) java.util.Collections.max(

crs, new Comparator() {

public int compare(final Object o1, final Object o2) {

final ClassifyResult m1 = (ClassifyResult) o1;

final ClassifyResult m2 = (ClassifyResult) o2;

final double ret = m1.probility – m2.probility;

if (ret < 0) {

return -1;

else {

return 1;

}

}

});

return maxElem.classification;

}

### 参考文献

[1] Christopher D. Manning, Prabhakar Raghavan, Hinrich Schütze, Introduction to Information Retrieval, Cambridge University Press, 2008, chapter 13, Text classification and Naive Bayes.

[2]Pang-Ning Tan, Michael Steinbach, Vipin Kumar, 《数据挖掘导论》，北京：人民邮电出版社，2007，第140~145页。

[2] 石志伟, 吴功宜, “基于朴素贝叶斯分类器的文本分类算法”, 第一届全国信息检索与内容安全学术会议，2004

[3] 洞庭散人，“基于朴素贝叶斯分类器的文本分类算法（上）”，“基于朴素贝叶斯分类器的文本分类算法（下）”，2008

[4]DL88250, “朴素贝叶斯中文文本分类器的研究与实现（1）”，“朴素贝叶斯中文文本分类器的研究与实现（2）”，2008

• 本文已收录于以下专栏：

举报原因： 您举报文章：基于朴素贝叶斯的文本分类算法 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)