人工智能实验报告.docx
《人工智能实验报告.docx》由会员分享,可在线阅读,更多相关《人工智能实验报告.docx(19页珍藏版)》请在冰点文库上搜索。
人工智能实验报告
人工智能实验报告
姓名:
学号:
所学专业:
报告题目:
提交日期:
基于朴素贝叶斯的文本分类器
1问题描述
朴素贝叶斯学习器是贝叶斯学习方法中实用性很高的一种方法,通常被称作是贝叶斯分类器。
在某些领域内,其性能可与神经网络和决策树学习相当。
本文主要介绍朴素贝叶斯在文本分类领域的应用。
本次试验实现了一个文本分类器,并且通过实验验证分类结果比较客观。
1.1待解决问题的解释
随着互联网信息及电子资源的急剧膨胀,文本分类技术成为信息组织与管理的有效手段。
本文意在实现一个基于朴素贝叶斯的文本分类器。
在应用朴素贝叶斯进行文本分类时有两个主要的设计问题:
首先,要决定怎样将任意文档表示为属性值的形式,其次要决定如何估计朴素贝叶斯分类器所需的概率。
对于第一个问题,可这样设计。
给定一篇文本文档,可对每个词的位置定义一个属性,该属性的值为在此位置上找到的词。
如果文档被这样表示,就可以使用朴素贝叶斯的想法进行概率估计了。
对于第二个问题,显而易见可直接利用下面的公式:
其中P(vj)表示这种类别出现的概率,
,docsj为vj类别出现的文档数,Examples是训练集中全部文档数。
而
,其中nk为ai这个单词在vj这个类别出现的次数,n是vj这个类别包含的单词总数,Vocabulary是训练集中词典的词数。
1.2学习方法介绍
贝叶斯分类是统计学分类方法,它是一类利用概率统计知识进行分类的算法。
在许多场合,朴素贝叶斯(NaïveBayes,NB)分类算法可以与决策树和神经网络分类算法相媲美,该算法能运用到大型数据库中,且方法简单、分类准确率高、速度快。
由于贝叶斯定理假设一个属性值对给定类的影响独立于其它属性的值,而此假设在实际情况中经常是不成立的,因此其分类准确率可能会下降。
为此,就出现了许多降低独立性假设的贝叶斯分类算法,如TAN(treeaugmentedBayesnetwork)算法。
朴素贝叶斯算法:
设每个数据样本用一个n维特征向量来描述n个属性的值,即:
X={x1,x2,…,xn},假定有m个类,分别用C1,C2,…,Cm表示。
给定一个未知的数据样本X(即没有类标号),若朴素贝叶斯分类法将未知的样本X分配给类Ci,则一定是
P(Ci|X)>P(Cj|X)1≤j≤m,j≠i
根据贝叶斯定理
由于P(X)对于所有类为常数,最大化后验概率P(Ci|X)可转化为最大化先验概率P(X|Ci)P(Ci)。
如果训练数据集有许多属性和元组,计算P(X|Ci)的开销可能非常大,为此,通常假设各属性的取值互相独立,这样
先验概率P(x1|Ci),P(x2|Ci),…,P(xn|Ci)可以从训练数据集求得。
根据此方法,对一个未知类别的样本X,可以先分别计算出X属于每一个类别Ci的概率P(X|Ci)P(Ci),然后选择其中概率最大的类别作为其类别。
朴素贝叶斯算法成立的前提是各属性之间互相独立。
当数据集满足这种独立性假设时,分类的准确度较高,否则可能较低。
另外,该算法没有分类规则输出。
2算法的伪代码及流程
LEARN_NAIVE_BAYES_TEXT(Examples,V)
Examples为一组文本文档以及他们的目标值。
V为所有可能目标值的集合。
此函数作用是学习概率项
他描述了从类别Vj中的文档总随机抽取的一个单词为单词wk的概率。
该函数也学习类别的先验概率P(vj)。
1收集Examples中所有的单词
Vocabulary←在Examples中任意文本文档中出现的所有词汇的集合
2计算所需要的概率项
和P(vj)
对V中每个目标值vj
docsj←Examples中目标值为vj的文档子集
Textj←将docsj中所有成员链接起来建立的单个文档
n←在Textj中不同单词位置的总数
对Vocabulary中每个单词wk
nk←单词wk出现在Textj中的次数
CLASSIFY_NAIVE_BAYES_TEXT(Doc)
对文档Doc返回其估计的目标值。
Ai代表在doc中的第i个位置上出现的单词。
返回vNB
3算法实现
3.1实验环境与问题规模
实验环境为WindowsXP操作系统,内存2G,IntelCore2(TM)DuoCPU。
问题规模比较大,尤其在训练语料是占用内存较大,速度比较慢。
另外,在训练时,由于文档较多,I/O操作也耗时较多。
3.2数据结构
1.HashMap,存储单词到WordItem的映射,Key是单词,Value是WordItem。
classWordItem{//单词的统计信息包括单词的个数和词频
doublecount;//单词的个数
doublefrequency;//词频,它需要在得出vocabulary的大小之后才能计算
}
2.Vector
classLabel{//类别标签:
体育、经济、政治等等
//m中用来存放每个单词及其统计信息
Mapm=newHashMap();
doublewordCount;//某个类别标签下的所有单词个数
doubledocumentCount;//某个类别标签下的所有文档个数
}
3.3实验结果
本实验选择选用的语料是财经、体育、科技三个类比进行训练。
其中财经类别818篇文档,体育类别929篇文档,科技类别1045篇文档。
为了测试朴素贝叶斯分类器的准确率,我每个类别中随机抽出20篇文档作为测试。
于是,训练集和测试集如下表所示:
训练集
测试集
Finace
798篇
20篇
Sport
909篇
20篇
Technology
1025篇
20篇
己过实验验证,朴素贝叶斯分类器的精确率如下:
Finance:
精确率100%
Sport:
精确率100%
Technology:
精确率100%
3.4系统中间及最终输出结果
1.系统初始界面:
2.选择待训练的文件夹,并完成训练:
3.选择待测试的目标文件,并完成测试分类:
参考文献
《人工智能-一种现代方法》StuartRussell,PeterNorvig著
《机器学习》TomMitchell著
《Java项目开发实践》陆正武,张志立编著
《JavaSE6.0编程指南》吴亚峰,纪超编著
《SwingHacks:
100个业界最尖端的技巧和工具》JoshuaMarinacci,ChrisAdamson著
《Java综合实例经典》吴其庆编著
附录—源代码及其注释
packageMyTextClassify;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.StringReader;
importjava.util.HashMap;
importjava.util.HashSet;
importjava.util.Iterator;
importjava.util.Map;
importjava.util.Set;
importjava.util.Vector;
importjeasy.analysis.MMAnalyzer;
importorg.apache.lucene.analysis.Analyzer;
importorg.apache.lucene.analysis.Token;
importorg.apache.lucene.analysis.TokenStream;
publicclassBeyesClassification{
privateStringlabel=null;
privatelongtrainTime=0;
publicString[]labelsName=null;
publicVector
publicSetvocabulary=newHashSet();
publicStringtrainPath=null;
publicStringtestPath=null;
publicintfindMax(double[]values){
doublemax=values[0];
intmark=0;
for(inti=0;iif(values[i]>max){
max=values[i];
mark=i;
}
}
returnmark;
}
publicString[]sort(String[]pData,intleft,intright){
Stringmiddle,strTemp;
inti=left;
intj=right;
middle=pData[(left+right)/2];
do{
while((pData[i].compareTo(middle)<0)&&(ii++;
while((pData[j].compareTo(middle)>0)&&(j>left))
j--;
if(i<=j){
strTemp=pData[i];
pData[i]=pData[j];
pData[j]=strTemp;
i++;
j--;
}
}while(iif(leftsort(pData,left,j);//递归调用
if(right>i)
sort(pData,i,right);//递归调用
returnpData;
}
VectorreadFile(StringfileName)throwsIOException,FileNotFoundException{
Filef=newFile(fileName);
InputStreamReaderisr=newInputStreamReader(newFileInputStream(f),"GBK");
char[]cbuf=newchar[(int)f.length()];
isr.read(cbuf);
Analyzeranalyzer=newMMAnalyzer();
TokenStreamtokens=analyzer.tokenStream("Contents",newStringReader(newString(cbuf)));
Tokentoken=null;
Vectorv=newVector();
while((token=tokens.next(newToken()))!
=null){
v.add(token.term());
}
returnv;
}
publicvoidsetTrainPath(StringfolderPat){
trainPath=folderPat;
}
publicvoidsetTestPath(StringtestPat){
testPath=testPat;
}
publicvoidtrain(){
longstartTime=System.currentTimeMillis();
Filefolder=newFile(trainPath);
labelsName=folder.list();
labels=newVector
for(inti=0;ilabels.add(newLabel());
FilesubFolder=newFile(trainPath+"\\"+labelsName[i]);
String[]files=subFolder.list();
System.out.println("Processing:
"+labelsName[i]);
GUI.setTextArea("Processing:
"+labelsName[i]);
Vectorv=newVector();
for(intj=0;jtry{
v.addAll(readFile(trainPath+"\\"+labelsName[i]+"\\"+files[j]));
}catch(FileNotFoundExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}
}
//把当前类别标签下的所有文档的所有单词都放入Set集合中,
//目的是为了获得vocabulary的大小
vocabulary.addAll(v);
//对当前类别标签下的所有文档的所有单词进行排序,
//目的是为了方便接下来统计各个单词的信息
String[]allWords=newString[v.size()];
for(intj=0;jallWords[j]=v.elementAt(j);
sort(allWords,0,v.size()-1);
//统计各个单词的信息
Stringprevious=allWords[0];
doublecount=1;
Mapm=newHashMap();
for(intj=1;jif(allWords[j].equals(previous))
count++;
else{
m.put(previous,newWordItem(count));
previous=allWords[j];
count=1;
}
}
labels.elementAt(i).set(m,v.size(),files.length);
longendTime=System.currentTimeMillis();
trainTime=endTime-startTime;
}
//获得了vocabulary的大小后,下面才开始计算词频
for(inti=0;iIteratoriter=labels.elementAt(i).m.entrySet().iterator();
while(iter.hasNext()){
Map.Entryentry=(Map.Entry)iter.next();
WordItemitem=entry.getValue();
item.setFrequency(Math.log10((item.count+1)/(labels.elementAt(i).wordCount+vocabulary.size())));
}
}
}
publicvoidtest(){
Vectorv=null;
try{
v=readFile(testPath);
}catch(FileNotFoundExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}
doublevalues[]=newdouble[labelsName.length];
for(inti=0;idoubletempValue=labels.elementAt(i).documentCount;
for(intj=0;jif(labels.elementAt(i).m.containsKey(v.elementAt(j))){
tempValue+=labels.elementAt(i).m.get(v.elementAt(j)).frequency;
}else{
tempValue+=Math.log10(1/(double)(labels.elementAt(i).wordCount+vocabulary.size()));
}
}
values[i]=tempValue;
}
//for(inti=0;i//所有的概率均取以10为底的log值
//System.out.println(labelsName[i]+"的概率为"+values[i]);
intmaxIndex=findMax(values);
System.out.println(testPath+"belongsto"+labelsName[maxIndex]);
GUI.setTextArea(testPath+"belongsto"+labelsName[maxIndex]);
label=labelsName[maxIndex];
}
publicStringgetLabelName(){
returnlabel;
}
publiclonggetTrainingTime(){
returntrainTime;
}
}
classLabel{//类别标签:
体育、经济、政治等等
//m中用来存放每个单词及其统计信息
Mapm=newHashMap();
doublewordCount;//某个类别标签下的所有单词个数
doubledocumentCount;//某个类别标签下的所有文档个数
publicLabel(){
this.m=null;
this.wordCount=-1;
this.documentCount=-1;
}
publicvoidset(Mapm,doublewordCount,doubledocumentCount){
this.m=m;
this.wordCount=wordCount;
this.documentCount=documentCount;
}
}
classWordItem{//单词的统计信息包括单词的个数和词频
doublecount;//单词的个数
doublefrequency;//词频,它需要在得出vocabulary的大小之后才能计算
publicWordItem(doublecount){
this.count=count;
this.frequency=-1;
}
publicvoidsetFrequency(doublefrequency){
this.frequency=frequency;
}
}
packageMyTextClassify;
importjava.awt.Dimension;
importjava.awt.FileDialog;
importjava.awt.Toolkit;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjavax.swing.JButton;
importjavax.swing.JFileChooser;
importjavax.swing.JFrame;
importjavax.swing.JOptionPane;
importjavax.swing.JPanel;
importjavax.swing.JTextArea;
importjavax.swing.UIManager;
publicclassGUIextendsJFrameimplementsRunnable{
/**
*主程序界面部分
*/
privatestaticfinallongserialVersionUID=1L;
privatestaticBeyesClassificationbayes=newBeyesClassification();
privatestaticJTextAreatextArea;
privatestaticfinalintDEFAULT_WIDTH=564;
privatestaticfinalintDEFAULT_HEIGHT=471;
privatebooleanflagTrain=false;
privatebooleanflagTest=false;
privatestaticJPanelpanel=null;
publicGUI(){
super();
getContentPane().setLayout(null);
setSize(newDimension(DEFAULT_WIDTH,DEFAULT_HEIGHT));
finalJButtonbutton1=newJButton();
button1.addActionListener(newActionListener(){
pub