`
javasalatu
  • 浏览: 787875 次
  • 性别: Icon_minigender_2
  • 来自: 北京
博客专栏
96df99eb-e89d-3228-9c8e-967fc745ec52
程序员的自我经营之道
浏览量:7930
文章分类
社区版块
存档分类
最新评论

朴素贝叶斯中文文本分类器的研究与实现(1)[88250原创]

 
阅读更多
<meta content="text/html; charset=utf-8" http-equiv="CONTENT-TYPE"> <meta content="OpenOffice.org 2.3 (Linux)" name="GENERATOR"> <style type="text/css"> <!-- @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in } H2 { margin-bottom: 0.08in } H2.cjk { font-family: "AR PL ShanHeiSun Uni" } H3 { margin-bottom: 0.08in } H3.western { font-family: "Helvetica" } H3.cjk { font-family: "AR PL ZenKai Uni" } H4 { margin-bottom: 0.08in } H4.western { font-family: "Helvetica"; font-size: 11pt; font-style: italic } H4.cjk { font-family: "AR PL ZenKai Uni"; font-size: 11pt; font-style: italic } H4.ctl { font-size: 11pt; font-style: italic } H5 { margin-bottom: 0.08in } H5.western { font-family: "Helvetica"; font-size: 11pt } H5.cjk { font-family: "AR PL ZenKai Uni"; font-size: 11pt } H5.ctl { font-size: 11pt } TD P { margin-bottom: 0in } TH P { margin-bottom: 0in } PRE.cjk { font-family: "AR PL ShanHeiSun Uni", monospace } H1 { margin-bottom: 0.08in } H1.western { font-family: "Helvetica"; font-size: 16pt } H1.cjk { font-family: "AR PL ZenKai Uni"; font-size: 16pt } H1.ctl { font-family: "Tahoma"; font-size: 16pt } CODE.cjk { font-family: "AR PL ShanHeiSun Uni", monospace } TT.cjk { font-family: "AR PL ShanHeiSun Uni", monospace } --> </style>

<meta content="text/html; charset=utf-8" http-equiv="CONTENT-TYPE">

<meta content="OpenOffice.org 2.3 (Linux)" name="GENERATOR"> <style type="text/css"> <!-- @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in } --> </style>




转载请保留作者信息:

作者:88250

Blog:http:/blog.csdn.net/DL88250

MSN & Gmail & QQ:DL88250@gmail.com

引言

将文本信息按预先指定的类别归类的技术可以追溯到上世纪60年代。不过,在最近的10年里,由于文本信息数字化而带来的海量数据,导致我们不得不将这些信息进行分类。由此,文本信息的自动分类得到了广泛的关注和快速的发展。

一 些研究表明,机器学习技术解决这个问题是较为有效的方法:通过一种广义的诱导学习建立相应的自动分类器,形成预先文档信息的一个或多个特征的分类集合。基 于机器学习的分类方式在分类效果和灵活性上都比之前基于知识工程和专家系统(通过某个领域里的专家人为地定义分类器)的文本分类模式有所突破,大量节省了 专家人力的投入,可以很方便地用于各种不同的领域。

目前,文本自动分类算法基本都是基于概率统计模型的,例如贝叶斯分类算法(Naive Bayes,Bayes Network),支持向量机(SVM),最大熵模型(Maximum Entropy Model),K近邻算法(KMM)等等。本文就基于概率模型的朴素贝叶斯分类算法作了一些讨论,并根据理论描述使用Java语言构建了一个素朴贝叶斯分类器。实验表明,贝叶斯分类算法简单,可以取得了优良的分类效果。


正文

一 贝叶斯理论与中文文本分类概述

1. 基本概念

条件概率

定义 设A, B是两个事件,且P(A)>0 称

P(B∣A)=P(AB)/P(A)

为在条件A下发生的条件事件B发生的条件概率。

乘法公式

设P(A)>0 则有

P(AB)=P(B∣A)P(A)

全概率公式和贝叶斯公式

定义 设S为试验E的样本空间,B1, B2, …Bn为E的一组事件,若

  1. BiBj≠Ф, i≠j, i, j=1, 2, …,n;

B1∪B2∪…∪Bn=S

则称B1, B2, …, Bn为样本空间的一个划分。

定理 设试验E的样本空间为,A为E的事件,B1, B2, …,Bn为的一个划分,且P(Bi)>0 (i=1, 2, …n),则

P(A)=P(A∣B1)P(B1)+P(A∣B2)+ …+P(A∣Bn)P(Bn)

称为全概率公式。

定理 设试验俄E的样本空间为S,A为E的事件,B1, B2, …,Bn为的一个划分,则

P(Bi∣A)=P(A∣Bi)P(Bi)/∑P(B|Aj)P(Aj)=P(B|Ai)P(Ai)/P(B)

称为贝叶斯公式。

说明:i,j均为下标,求和均是1到n



2. 朴素贝叶斯模型的假设与文本特征变量

文本特征变量

文本特征变量可以描述为文本中的字/词构成的属性。例如给出文本:

Ding Liang is a programmer.

可以获得该文本的特征变量集:{Ding, Liang, is, a, programmer.}

朴素贝叶斯模型是文本分类模型中的一种简单但性能优越的的分类模型。为了简化计算过程,假定各待分类文本特征变量是相互独立的,即“朴素贝叶斯模型的假设”。相互独立表明了所有特征变量之间的表述是没有关联的。如上例中,[Ding]和[Liang]这两个特征变量就是没有任何关联的。

虽然这种条件独立的假设在许多应用领域未必能很好满足,甚至是不成立的。但这种简化的贝叶斯分类器在许多实际应用中还是得到了较好的分类精度。


在上例中,文本是英文,但由于中文本身是没有自然分割符(如空格之类符号),所以要获得中文文本的特征变量向量首先需要对文本进行中文分词

3. 中文分词

中文分词的概念、意义以及算法简介可以查看 这篇文章 :-)

关于中文分词的实际可用工具,前人已经做了很多成功的实践:

ICTCLAS

中科院的ICTCLAS(Institute of Computing Technology, Chinese Lexical Analysis System)应该是目前最好的中文分词系统了。不过1.0版本后收费了,而且是在Windows下封装的DLL库,要作移植比较困难。

ICTCLAS4J

Java版本的开源LCTCLAS,由于代码的开发人员没有太多考虑到跨平台,导致了在非Windows平台上的配置比较繁琐。并且,其提供的接口不是很友好,其词库的依赖关系颇为复杂。

海量分词组件

海量信息的中文智能分词组件虽然可以免费使用,但是也是提供的DLL,没有平台移植性。

极易中文分词组件

由极易软件提供的极易中文分词组件可以免费使用,提供Lucene接口,跨平台,性能可靠。



本次分类器是使用Java语言编写的,所以选择了极易中文分词组件作为基本的分词工具。



4. 朴素贝叶斯分类推导

根据联合概率公式(全概率公式)





M——训练文本集合中经过踢出无用词去除文本预处理之后关键字的数量。

二 用Java构造朴素贝叶斯中文文本分类器

在前面,我们介绍了贝叶斯理论与中文分词技术。现在,让我们实践吧!

1. 开发环境与工具配置

OS: Ubuntu 7.10 GNU/Linux

IDE:NetBeans 6.0.1

JDK: 1.6.0_03-b05

Lucene:lucene-core-2.3.0.jar

分词工具:je-analysis-1.5.3.jar (极易分词组件1.5.3)

2. 朴素贝叶斯分类器设计

工程分为了两个包:bayes和util

Package cn.edu.ynu.sei.classifier.bayes

Class Summary

BayesClassifier

朴素贝叶斯分类器

ClassifyResult

分类结果实体



n.edu.ynu.sei.classifier.bayes
Class BayesClassifier

java.lang.Object   extended by cn.edu.ynu.sei.classifier.bayes.BayesClassifier

public class BayesClassifierextends java.lang.Object

朴素贝叶斯分类器

cNB=arg Max P(cj)∏1C P(xi|cj)


<!-- ======== CONSTRUCTOR SUMMARY ======== --><!-- -->

Constructor Summary

BayesClassifier()
默认的构造器,初始化训练库路径

<!-- ========== METHOD SUMMARY =========== --><!-- -->

Method Summary

java.lang.String

classify(java.lang.Stringtext)
对给定的文本进行分类

<!-- -->

Methods inherited from class java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

<!-- ========= CONSTRUCTOR DETAIL ======== --><!-- -->

Constructor Detail

<!-- -->BayesClassifier

public BayesClassifier()
默认的构造器,初始化训练库路径

<!-- ============ METHOD DETAIL ========== --><!-- -->

Method Detail

<!-- -->classify

public java.lang.String classify(java.lang.Stringtext)
对给定的文本进行分类
Parameters:
text - 给定的文本
Returns:
分类结果



cn.edu.ynu.sei.classifier.bayes
Class ClassifyResult

java.lang.Object   extended by cn.edu.ynu.sei.classifier.bayes.ClassifyResult

public class ClassifyResultextends java.lang.Object

分类结果实体


<!-- =========== FIELD SUMMARY =========== --><!-- -->

Field Summary

java.lang.String

classification
类别

float

p
概率

<!-- ======== CONSTRUCTOR SUMMARY ======== --><!-- -->

Constructor Summary

ClassifyResult()

<!-- ========== METHOD SUMMARY =========== --><!-- -->

Method Summary

<!-- -->

Methods inherited from class java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

<!-- ============ FIELD DETAIL =========== --><!-- -->

Field Detail

<!-- -->classification

public java.lang.String classification
类别

<!-- -->p

public float p
概率

<!-- ========= CONSTRUCTOR DETAIL ======== --><!-- -->

Constructor Detail

<!-- -->ClassifyResult

public ClassifyResult()




Package cn.edu.ynu.sei.classifier.util

Class Summary

ChineseSpliter

中文分词器 简单地封装了一下极易中文分词组件

ClassConditionalProbability

条件概率计算

KeySearcher

关键字/词搜索器 简单地封装了一下极易中文分词组件

PriorProbability

先验概率计算

TrainingDataManager

训练语料库搜索器

cn.edu.ynu.sei.classifier.util
Class ChineseSpliter

java.lang.Object   extended by cn.edu.ynu.sei.classifier.util.ChineseSpliter

public class ChineseSpliterextends java.lang.Object

中文分词器 简单地封装了一下极易中文分词组件


<!-- ======== CONSTRUCTOR SUMMARY ======== --><!-- -->

Constructor Summary

ChineseSpliter()

<!-- ========== METHOD SUMMARY =========== --><!-- -->

Method Summary

staticjava.lang.String

split(java.lang.Stringtext, java.lang.StringsplitToken)
中文分词

<!-- -->

Methods inherited from class java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

<!-- ========= CONSTRUCTOR DETAIL ======== --><!-- -->

Constructor Detail

<!-- -->ChineseSpliter

public ChineseSpliter()

<!-- ============ METHOD DETAIL ========== --><!-- -->

Method Detail

<!-- -->split

public static java.lang.String split(java.lang.Stringtext,                                      java.lang.StringsplitToken)
中文分词
Parameters:
text - 给定的文本
splitToken - 用于分割的标记
Returns:
分词完毕的文本

cn.edu.ynu.sei.classifier.util
Class ClassConditionalProbability

java.lang.Object   extended by cn.edu.ynu.sei.classifier.util.ClassConditionalProbability

public class ClassConditionalProbabilityextends java.lang.Object

条件概率计算

类条件概率

P(xj|cj)=( N(X=xi, C=cj )+1 ) / ( N(C=cj)+M+V )
其中,N(X=xi, C=cj)表示类别cj中包含属性x i的训练文本数量;N(C=cj)表示类别cj中的训练文本数量;M值用于避免 N(X=xi, C=cj)过小所引发的问题;V表示类别的总数。

条件概率

定义 设A, B是两个事件,且P(A)>0 称
P(B∣A)=P(AB)/P(A)
为在条件A下发生的条件事件B发生的条件概率。


<!-- ======== CONSTRUCTOR SUMMARY ======== --><!-- -->

Constructor Summary

ClassConditionalProbability()

<!-- ========== METHOD SUMMARY =========== --><!-- -->

Method Summary

staticfloat

calculatePxc(java.lang.Stringx, java.lang.Stringc)
计算类条件概率

<!-- -->

Methods inherited from class java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

<!-- ========= CONSTRUCTOR DETAIL ======== --><!-- -->

Constructor Detail

<!-- -->ClassConditionalProbability

public ClassConditionalProbability()

<!-- ============ METHOD DETAIL ========== --><!-- -->

Method Detail

<!-- -->calculatePxc

public static float calculatePxc(java.lang.Stringx,                                  java.lang.Stringc)
计算类条件概率
Parameters:
x - 给定的文本属性
c - 给定的分类
Returns:
给定条件下的类条件概率

cn.edu.ynu.sei.classifier.util
Class PriorProbability

java.lang.Object   extended by cn.edu.ynu.sei.classifier.util.PriorProbability

public class PriorProbabilityextends java.lang.Object

先验概率计算

先验概率计算

P(cj)=N(C=cj)/N
其中,N(C=cj)表示类别cj中的训练文本数量; N表示训练文本集总数量。


<!-- ======== CONSTRUCTOR SUMMARY ======== --><!-- -->

Constructor Summary

PriorProbability()

<!-- ========== METHOD SUMMARY =========== --><!-- -->

Method Summary

staticfloat

calculatePc(java.lang.Stringc)
先验概率

<!-- -->

Methods inherited from class java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

<!-- ========= CONSTRUCTOR DETAIL ======== --><!-- -->

Constructor Detail

<!-- -->PriorProbability

public PriorProbability()

<!-- ============ METHOD DETAIL ========== --><!-- -->

Method Detail

<!-- -->calculatePc

public static float calculatePc(java.lang.Stringc)
先验概率
Parameters:
c - 给定的分类
Returns:
给定条件下的先验概率

cn.edu.ynu.sei.classifier.util
Class TrainingDataManager

java.lang.Object   extended by cn.edu.ynu.sei.classifier.util.TrainingDataManager

public class TrainingDataManagerextends java.lang.Object

训练语料库搜索器


<!-- ======== CONSTRUCTOR SUMMARY ======== --><!-- -->

Constructor Summary

TrainingDataManager()
默认的构造器

TrainingDataManager(java.lang.StringtraningDataDirPath)
带参数的构造器

<!-- ========== METHOD SUMMARY =========== --><!-- -->

Method Summary

int

getCountContainKeyOfClassification(java.lang.Stringclassification, java.lang.Stringkey)
返回给定分类中包含关键字/词的训练文本的数目

java.lang.String[]

getFilesPath(java.lang.Stringclassification)
根据训练文本类别返回这个类别下的所有训练文本路径(full path)

staticjava.lang.String

getText(java.lang.StringfilePath)
返回给定路径的文本文件内容

int

getTrainingFileCount()
返回训练文本集中所有的文本数目

int

getTrainingFileCountOfClassification(java.lang.Stringclassification)
返回训练文本集中在给定分类下的训练文本数目

java.lang.String[]

getTraningClassifications()
返回训练文本类别,这个类别就是目录名

<!-- -->

Methods inherited from class java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

<!-- ========= CONSTRUCTOR DETAIL ======== --><!-- -->

Constructor Detail

<!-- -->TrainingDataManager

public TrainingDataManager(java.lang.StringtraningDataDirPath)
带参数的构造器
Parameters:
traningDataDirPath - 训练语料库根目录路径

<!-- -->TrainingDataManager

public TrainingDataManager()
默认的构造器

<!-- ============ METHOD DETAIL ========== --><!-- -->

Method Detail

<!-- -->getTraningClassifications

public java.lang.String[] getTraningClassifications()
返回训练文本类别,这个类别就是目录名
Returns:
训练文本类别

<!-- -->getFilesPath

public java.lang.String[] getFilesPath(java.lang.Stringclassification)
根据训练文本类别返回这个类别下的所有训练文本路径(full path)
Parameters:
classification - 给定的分类
Returns:
给定分类下所有文件的路径(full path)

<!-- -->getText

public static java.lang.String getText(java.lang.StringfilePath)                                 throws java.io.FileNotFoundException,                                        java.io.IOException
返回给定路径的文本文件内容
Parameters:
filePath - 给定的文本文件路径
Returns:
文本内容
Throws:
java.io.FileNotFoundException
java.io.IOException

<!-- -->getTrainingFileCount

public int getTrainingFileCount()
返回训练文本集中所有的文本数目
Returns:
训练文本集中所有的文本数目

<!-- -->getTrainingFileCountOfClassification

public int getTrainingFileCountOfClassification(java.lang.Stringclassification)
返回训练文本集中在给定分类下的训练文本数目
Parameters:
classification - 给定的分类
Returns:
训练文本集中在给定分类下的训练文本数目

<!-- -->getCountContainKeyOfClassification

public int getCountContainKeyOfClassification(java.lang.Stringclassification,                                               java.lang.Stringkey)
返回给定分类中包含关键字/词的训练文本的数目
Parameters:
classification - 给定的分类
key - 给定的关键字/词
Returns:
给定分类中包含关键字/词的训练文本的数目



以上便是当前阶段下的分类器设计,为了更进一步说明,下面列出关键的源代码:-)



3. 关键源代码清单

/*

*@(#)TrainingDataManager.java

*

*Thisprogramisfreesoftware;youcanredistributeitand/ormodify

*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby

*theFreeSoftwareFoundation;eitherversion3oftheLicense,or

*(atyouroption)anylaterversion.

*

*Thisprogramisdistributedinthehopethatitwillbeuseful,

*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof

*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe

*GNULibraryGeneralPublicLicenseformoredetails.

*

*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense

*alongwiththisprogram;ifnot,writetotheFreeSoftware

*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.

*/

packagecn.edu.ynu.sei.classifier.util;



importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.FileNotFoundException;

importjava.io.IOException;

importjava.io.InputStreamReader;

importjava.util.Properties;

importjava.util.logging.Level;

importjava.util.logging.Logger;



/**

*训练语料库搜索器

*
@author88250

*
@version1.0.0.0,Feb18,2008

*/

publicclassTrainingDataManager{



privateString[]traningFileClassifications;



privateFiletraningTextDir;



/**

*带参数的构造器

*
@paramtraningDataDirPath训练语料库根目录路径

*/

publicTrainingDataManager(StringtraningDataDirPath){

traningTextDir
=newFile(traningDataDirPath);



if(!traningTextDir.isDirectory()){

thrownewIllegalArgumentException("训练语料库搜索失败!["+

traningDataDirPath
+"]");

}



this.traningFileClassifications=traningTextDir.list();

}



/**

*默认的构造器

*/

publicTrainingDataManager(){

try{

Propertiesproperties
=newProperties();

FileInputStreaminputFile;

inputFile
=newFileInputStream("/home/daniel/TempData/BayesTextClassifySystem/Training.properties");

properties.load(inputFile);



StringtraningDataDirPath
=properties.getProperty("path");

traningTextDir
=newFile(traningDataDirPath);



if(!traningTextDir.isDirectory()){

thrownewIllegalArgumentException("训练语料库搜索失败!["+

traningDataDirPath
+"]");

}



this.traningFileClassifications=traningTextDir.list();

}
catch(IOExceptionex){

Logger.getLogger(TrainingDataManager.
class.getName()).

log(Level.SEVERE,
null,ex);

}

}



/**

*返回训练文本类别,这个类别就是目录名

*
@return训练文本类别

*/

publicString[]getTraningClassifications(){

returnthis.traningFileClassifications;

}



/**

*根据训练文本类别返回这个类别下的所有训练文本路径(fullpath)

*
@paramclassification给定的分类

*
@return给定分类下所有文件的路径(fullpath)

*/

publicString[]getFilesPath(Stringclassification){

FileclassDir
=newFile(traningTextDir.getPath()+

File.separator
+

classification);

String[]ret
=classDir.list();

for(inti=0;i<ret.length;i++){

ret[i]
=traningTextDir.getPath()+

File.separator
+

classification
+

File.separator
+

ret[i];

}



returnret;

}



/**

*返回给定路径的文本文件内容

*
@paramfilePath给定的文本文件路径

*
@return文本内容

*
@throwsjava.io.FileNotFoundException

*
@throwsjava.io.IOException

*/

publicstaticStringgetText(StringfilePath)throwsFileNotFoundException,

IOException{

InputStreamReaderisReader
=

newInputStreamReader(newFileInputStream(filePath),

"GBK");

BufferedReaderreader
=newBufferedReader(isReader);



Stringaline;

StringBuildersb
=newStringBuilder();



while((aline=reader.readLine())!=null){

sb.append(aline
+" ");

}

isReader.close();

reader.close();



returnsb.toString();

}



/**

*返回训练文本集中所有的文本数目

*
@return训练文本集中所有的文本数目

*/

publicintgetTrainingFileCount(){

intret=0;

for(inti=0;i<traningFileClassifications.length;i++){

ret
+=

getTrainingFileCountOfClassification(traningFileClassifications[i]);

}



returnret;

}



/**

*返回训练文本集中在给定分类下的训练文本数目

*
@paramclassification给定的分类

*
@return训练文本集中在给定分类下的训练文本数目

*/

publicintgetTrainingFileCountOfClassification(Stringclassification){

FileclassDir
=newFile(traningTextDir.getPath()+

File.separator
+

classification);

returnclassDir.list().length;

}



/**

*返回给定分类中包含关键字/词的训练文本的数目

*
@paramclassification给定的分类

*
@paramkey给定的关键字/词

*
@return给定分类中包含关键字/词的训练文本的数目

*/

publicintgetCountContainKeyOfClassification(Stringclassification,

Stringkey){

intret=0;



try{

String[]filePath
=getFilesPath(classification);

for(intj=0;j<filePath.length;j++){

Stringtext
=getText(filePath[j]);

if(text.contains(key)){

ret
++;

}

}

}
catch(FileNotFoundExceptionex){

Logger.getLogger(TrainingDataManager.
class.getName()).

log(Level.SEVERE,
null,

ex);

}
catch(IOExceptionex){

Logger.getLogger(TrainingDataManager.
class.getName()).

log(Level.SEVERE,
null,

ex);

}

returnret;



}

}



/*

*@(#)PriorProbability.java

*

*Thisprogramisfreesoftware;youcanredistributeitand/ormodify

*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby

*theFreeSoftwareFoundation;eitherversion3oftheLicense,or

*(atyouroption)anylaterversion.

*

*Thisprogramisdistributedinthehopethatitwillbeuseful,

*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof

*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe

*GNULibraryGeneralPublicLicenseformoredetails.

*

*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense

*alongwiththisprogram;ifnot,writetotheFreeSoftware

*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.

*/

packagecn.edu.ynu.sei.classifier.util;



/**

*先验概率计算

*<h3>先验概率计算</h3>

*P(c<sub>j</sub>)=N(C=c<sub>j</sub>)<b>/</b>N<br>

*其中,N(C=c<sub>j</sub>)表示类别c<sub>j</sub>中的训练文本数量;

*N表示训练文本集总数量。

*
@author88250

*
@version1.0.0.0,Feb19,2008

*/

publicclassPriorProbability{



privatestaticTrainingDataManagertdm=

newTrainingDataManager();



/**

*先验概率

*
@paramc给定的分类

*
@return给定条件下的先验概率

*/

publicstaticfloatcalculatePc(Stringc){

floatret=0F;



floatNc=tdm.getTrainingFileCountOfClassification(c);



floatN=tdm.getTrainingFileCount();

ret
=Nc/N;



returnret;

}

}



/*

*@(#)ClassConditionalProbability.java

*

*Thisprogramisfreesoftware;youcanredistributeitand/ormodify

*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby

*theFreeSoftwareFoundation;eitherversion3oftheLicense,or

*(atyouroption)anylaterversion.

*

*Thisprogramisdistributedinthehopethatitwillbeuseful,

*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof

*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe

*GNULibraryGeneralPublicLicenseformoredetails.

*

*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense

*alongwiththisprogram;ifnot,writetotheFreeSoftware

*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.

*/

packagecn.edu.ynu.sei.classifier.util;



/**

*<b>类</b>条件概率计算

*

*<h3>类条件概率</h3>

*P(x<sub>j</sub>|c<sub>j</sub>)=(N(X=x<sub>i</sub>,C=c<sub>j

*</sub>)+1)<b>/</b>(N(C=c<sub>j</sub>)+M+V)<br>

*其中,N(X=x<sub>i</sub>,C=c<sub>j</sub>)表示类别c<sub>j</sub>中包含属性x<sub>

*i</sub>的训练文本数量;N(C=c<sub>j</sub>)表示类别c<sub>j</sub>中的训练文本数量;M值用于避免

*N(X=x<sub>i</sub>,C=c<sub>j</sub>)过小所引发的问题;V表示类别的总数。

*

*<h3>条件概率</h3>

*<b>定义</b>设A,B是两个事件,且P(A)>0称<br>

*<tt>P(B∣A)=P(AB)/P(A)</tt><br>

*为在条件A下发生的条件事件B发生的条件概率。

*
@author88250

*
@version1.0.0.0,Feb19,2008

*/

publicclassClassConditionalProbability{



privatestaticTrainingDataManagertdm=

newTrainingDataManager();



privatestaticfinalfloatM=0F;



/**

*计算类条件概率

*
@paramx给定的文本属性

*
@paramc给定的分类

*
@return给定条件下的类条件概率

*/

publicstaticfloatcalculatePxc(Stringx,Stringc){

floatret=0F;



floatNxc=tdm.getCountContainKeyOfClassification(c,x);

floatNc=tdm.getTrainingFileCountOfClassification(c);

floatV=tdm.getTraningClassifications().length;

ret
=(Nxc+1)/(Nc+M+V);



returnret;

}

}



/*

*@(#)BayesClassifier.java

*

*Thisprogramisfreesoftware;youcanredistributeitand/ormodify

*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby

*theFreeSoftwareFoundation;eitherversion3oftheLicense,or

*(atyouroption)anylaterversion.

*

*Thisprogramisdistributedinthehopethatitwillbeuseful,

*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof

*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe

*GNULibraryGeneralPublicLicenseformoredetails.

*

*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense

*alongwiththisprogram;ifnot,writetotheFreeSoftware

*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.

*/

packagecn.edu.ynu.sei.classifier.bayes;



importcn.edu.ynu.sei.classifier.util.ChineseSpliter;

importcn.edu.ynu.sei.classifier.util.ClassConditionalProbability;

importcn.edu.ynu.sei.classifier.util.PriorProbability;

importcn.edu.ynu.sei.classifier.util.TrainingDataManager;

importjava.io.FileInputStream;

importjava.io.IOException;

importjava.util.ArrayList;

importjava.util.Comparator;

importjava.util.List;

importjava.util.Properties;

importjava.util.Properties;

importjava.util.logging.Level;

importjava.util.logging.Logger;



/**

*朴素贝叶斯分类器

*<p>

*c<sub>NB</sub>=argMaxP(c<sub>j</sub>)&prod;<sub>1</sub><sup>C</sup>

*P(x<sub>i</sub>|c<sub>j</sub>)

*</p>

*
@author88250

*
@version1.0.0.0,Feb19,2008

*/

publicclassBayesClassifier{



privateTrainingDataManagertdm;



/**

*默认的构造器,初始化训练库路径

*/

publicBayesClassifier(){

try{

Propertiesproperties
=newProperties();



FileInputStreaminputFile;

inputFile
=newFileInputStream("/home/daniel/TempData/BayesTextClassifySystem/Training.properties");



properties.load(inputFile);



tdm
=

newTrainingDataManager(properties.getProperty("path"));

}
catch(IOExceptionex){

Logger.getLogger(BayesClassifier.
class.getName()).

log(Level.SEVERE,
null,ex);

}

}



/**

*计算给定的文本属性向量<code>X</code>在给定的分类<code>Cj</code>中的类条件概率

*<code>ClassConditionalProbability</code>连乘(&prod;)值

*
@paramX给定的文本属性向量

*
@paramCj给定的类别

*
@return类条件概率连乘(&prod;)值,即<br>

*P(c<sub>j</sub>)&prod;<sub>1</sub><sup>C</sup>P(x<sub>i</sub>|c<sub>j</sub>)

*
@seecn.edu.ynu.sei.classifier.util.ClassConditionalProbability

*/

floatcalcProd(String[]X,StringCj){

floatret=0F;



//类条件概率连乘

for(inti=0;i<

X.length;i
++){

StringXi
=X[i];

ret
+=

ClassConditionalProbability.calculatePxc(Xi,Cj);

}

//再乘以先验概率

ret
*=PriorProbability.calculatePc(Cj);



returnret;

}



/**

*对给定的文本进行分类

*
@paramtext给定的文本

*
@return分类结果

*/

@SuppressWarnings(
"unchecked")

publicStringclassify(

Stringtext){

String[]X
=ChineseSpliter.split(text,"").split("/s");

String[]C
=tdm.getTraningClassifications();

floatp=0F;

List
<ClassifyResult>crs=newArrayList<ClassifyResult>();



for(inti=0;i<

C.length;i
++){

StringCi
=C[i];

p
=

calcProd(X,Ci);

ClassifyResultcr
=newClassifyResult();

cr.classification
=Ci;

cr.p
=p;

System.out.println(
"Inprocess....");

System.out.println(Ci
+""+p);

crs.add(cr);

}



java.util.Collections.sort(crs,

newComparator(){



publicintcompare(Objecto1,

Objecto2){

ClassifyResultm1
=

(ClassifyResult)o1;

ClassifyResultm2
=

(ClassifyResult)o2;

floatret=m1.p-m2.p;

if(ret<0){

return1;

}
else{

return-1;

}

}

});



returncrs.get(0).classification;

}

}



三 训练库与分类测试

作为测试,我用的是Sogou实验室的文本分类数据下载了mini版本和精简版本。

迷你版本有10个类别 ,共计100篇文章,总大小284.7KB

精简版本有9个类别,共计17910篇文章,总大小 48.6 MB

测试机器配置:

Pm 750(1.86G), 1.0GB RAM


对于给定的文本:

[ 微软公司提出以446亿美元的价格收购雅虎

中国网21日报道 美联社消息,微软公司提出以446亿美元现金加股票的价格收购搜索网站雅虎公司。

微软提出以每股31美元的价格收购雅虎。微软的收购报价较雅虎131日的收盘价19.18美元溢价62%。微软公司称雅虎公司的股东可以选择以现金或股票进行交易。

微软和雅虎公司在2006年底和2007年初已在寻求双方合作。而近两年,雅虎一直处于困境:市场份额下滑、

运营业绩不佳、股价大幅下跌。对于力图在互联网市场有所作为的微软来说,收购雅虎无疑是一条捷径,因为双方具有非常强的互补性。(小桥)

]



使用mini版本的测试结果:

init:

deps-jar:

compile:

compile-test-single:

Testsuite: cn.edu.ynu.sei.classifier.bayes.BayesClassifierTest

classify

In process....

文化:0.70500064

In process....

健康:0.9200004

In process....

旅游:0.8250006

In process....

招聘:0.89000064

In process....

汽车:1.1150006

In process....

教育:0.82000035

In process....

体育:0.7400004

In process....

IT1.1150006

In process....

财经:1.0150005

In process....

军事:0.76500034



属于[ IT ]

Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 4.572 sec



可以看出,对于该文本,“汽车”的相似度和“IT”是一样的。



使用精简版本的测试结果:

Compiling 1 source file to /home/daniel/Work/Sources/Java/BayesTextClassifier/build/test/classes

compile-test-single:

Testsuite: cn.edu.ynu.sei.classifier.bayes.BayesClassifierTest

classify

In process....

文化:0.7996222

In process....

健康:0.691568

In process....

旅游:0.6269246

In process....

招聘:0.95492196

In process....

教育:0.64076483

In process....

体育:0.41798678

In process....

IT1.2663554

In process....

财经:1.1997666

In process....

军事:0.9136235

属于[ IT ]

Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 594.815 sec





关于分类器的评估

使用Mini版本训练库时,分类耗时4.572秒;

使用精简版本训练库时,分类耗时594.815秒,也就是9分多钟。

测试用的文章只有261个字,在没有经过任何降维处理的情况下,使用稍大一点的词库后,性能问题出来了。

另外,分类器的评估有专门的评估模型和方法,这里不再赘述。



后话

当前,是实验的第一阶段,注重的是“纯”朴素贝叶斯理论研究和实现,所以,在分类效率上可能较为低下。但是,基于本次构建的朴素贝叶斯分类器,下一阶段将对她作出优化处理。目前想到的优化手段:

  1. 文本先进行降维处理,具体方法就是踢出一些无用的词汇(例如:的,吗,么。。。。等等助词之类的)

  2. 在先验条件的处理上要考虑对训练库进行处理后的先验条件数据保存,下次直接读取就可以用了

  3. 找台多核的机子做多线程处理 :-)

好了,本文到此就结束了。下一次的题目是《朴素贝叶斯中文文本分类器的研究与实现(2)[88250原创],期待大家的关注!

分享到:
评论

相关推荐

    朴素贝叶斯文本分类器(java实现)

    朴素贝叶斯文本分类器是一种广泛应用的机器学习算法,尤其在自然语言处理领域,用于将文本数据归类到预定义的类别中。本程序的Java实现深入探讨了这一概念,并提供了完整的工具集,包括源代码、实验报告、可执行程序...

    人工智能-项目实践-朴素贝叶斯分类器-朴素贝叶斯文本分类器

    人工智能_项目实践_朴素贝叶斯分类器_朴素贝叶斯文本分类器 **数据:**搜狗文本分类语料库 **分类器:**朴素贝叶斯分类器 NBC(Naive Bayesian Classifier) **编程语言:**Python+jieba分词库+nltk+sklearn

    基于朴素贝叶斯实现的文本分类

    在这个项目中,我们将深入探讨如何利用Python来实现朴素贝叶斯进行文本分类,并观察在某些情况下,分类准确率可以达到95%以上。 一、朴素贝叶斯理论基础 朴素贝叶斯分类器基于贝叶斯定理,该定理表述为:P(A|B) = P...

    朴素贝叶斯算法文本分类JAVA实现

    在Java环境下实现朴素贝叶斯分类器,我们可以分为以下几个步骤: 1. 数据预处理: 在文本分类任务中,首先需要对文本数据进行预处理,包括分词、去除停用词(如“的”、“是”等常见无实际意义的词语)、词干提取...

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

    这一假设虽然往往不符合实际情况,但在很多情况下,朴素贝叶斯分类器仍然能够取得不错的分类效果,特别是在文本分类领域。 贝叶斯分类器在分类中的应用涉及计算先验概率和后验概率。先验概率通常基于训练集中的类...

    机器学习文本分类基于TF-IDF+朴素贝叶斯文本数据的分类与分析源码(高分大作业).zip

    机器学习文本分类基于TF-IDF+朴素贝叶斯文本数据的分类与分析源码(高分大作业).zip本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够...

    朴素贝叶斯文本分类器(新浪微博)

    朴素贝叶斯文本分类器是一种基于概率统计的机器学习算法,尤其在文本分类领域中广泛应用。这个特定的项目,"朴素贝叶斯文本分类器(新浪微博)"是针对新浪微博的数据进行情感分析,将微博内容分为积极和消极两类,...

    朴素贝叶斯分类器算法

    朴素贝叶斯分类器是一种基于概率的机器学习算法,它基于贝叶斯定理和特征条件独立假设。在"朴素贝叶斯分类器算法"中,我们主要关注以下几个知识点: 1. **贝叶斯定理**:贝叶斯定理是统计学中的一个重要概念,用于...

    朴素贝叶斯对于文本分类

    朴素贝叶斯(Naive Bayes)是一种基于概率论的机器学习算法,尤其...这些文件可能一起提供了朴素贝叶斯算法在文本分类中的实现细节和示例。通过阅读和理解这些文件,可以深入掌握如何在实际项目中运用朴素贝叶斯方法。

    基于Hadoop实现朴素贝叶斯文本分类器.zip

    《基于Hadoop实现朴素贝叶斯文本分类器》 在当今大数据时代,高效的数据处理和分析成为了企业竞争力的关键。Hadoop作为开源的分布式计算框架,以其高容错性、可扩展性和低成本的优势,广泛应用于海量数据的处理。而...

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

    朴素贝叶斯分类器是一种基于概率的机器学习方法,它在文本分类领域有着广泛的应用。该模型基于贝叶斯定理,并且通过“朴素”这一假设来简化计算,即假设特征之间是相互独立的。这一假设使得朴素贝叶斯分类器能够高效...

    高效朴素贝叶斯Web新闻文本分类模型的简易实现1

    总的来说,本文提供了一种简单易行的方法,利用jieba和TF-IDF优化朴素贝叶斯分类器在中文Web新闻文本分类中的性能。这种方法对于处理大量中文文本数据的场景,如新闻聚合、情感分析、信息检索等,具有实用价值。同时...

    Hadoop与MapReduce课程设计Java基于朴素贝叶斯的文本分类器项目源代码+课程设计报告

    本项目以Hadoop和MapReduce为技术基础,采用Java语言开发了一个基于朴素贝叶斯算法的文本分类器。文本分类器作为一种文本挖掘技术,在信息检索、数据挖掘、垃圾邮件过滤等领域有着广泛的应用。朴素贝叶斯算法是一种...

    基于朴素贝叶斯算法的文本分类程序_Python

    朴素贝叶斯算法是一种在机器学习领域广泛应用的概率型分类方法,尤其在文本分类中表现出色。这个程序是用Python语言实现的,它利用朴素贝叶斯理论对文本数据进行分类。下面将详细介绍朴素贝叶斯算法及其在Python中的...

    C++实现朴素贝叶斯分类器

    在实际应用中,C++实现的朴素贝叶斯分类器可以用于文本分类(如垃圾邮件过滤)、情感分析、推荐系统等多种场景。其简洁的代码结构和高效性能使其成为初学者和专业人士的首选工具之一。通过调整和优化,还可以进一步...

    基于python实现的新闻文本分类 - 自实现朴素贝叶斯分类器,文本分类一百万条新闻+源代码+文档说明+数据

    本项目利用100万的新闻文本,利用朴素贝叶斯来进行文本分类,新闻包括[car、culture、energy、entertainment、finance、health、house、IT、military、sport]十个类,每个类10w条新闻,并且其中,50万数据用以训练,...

    java实现朴素贝叶斯分类算法

    在Java中实现朴素贝叶斯分类器,我们需要理解以下几个关键知识点: 1. **贝叶斯定理**:贝叶斯定理是概率论中的一个公式,它描述了在已知某些条件下,事件A发生的条件概率P(A|B)如何根据先验概率P(A)和证据B的概率P...

    人工智能-项目实践-朴素贝叶斯分类器-朴素贝叶斯文本分类器源码+实验报告(大作业&课设)

    人工智能-项目实践-朴素贝叶斯分类器-朴素贝叶斯文本分类器源码+实验报告(大作业&课设),含有代码注释,满分大作业资源,新手也可看懂,期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。...

    朴素贝叶斯 文本分类

    通过深入研究这个Java项目,我们可以掌握朴素贝叶斯文本分类的基本概念,并学习如何将理论应用于实践中。这个项目不仅提供了理论知识,还有实际的代码示例,是学习和应用朴素贝叶斯算法的好资源。

Global site tag (gtag.js) - Google Analytics