文本分类算法之–贝叶斯分类算法的实现Java版本

文本分类算法之–贝叶斯分类算法的实现Java版本package com.vista;import java.io.IOException;      import jeasy.analysis.MMAnalyzer;/*** 中文分词器*/public class ChineseSpliter {    /**    * 对给定的文本进行中文分词    * @param text 给定的文本   

大家好,又见面了,我是你们的朋友全栈君。

package com.vista;
import java.io.IOException;      
import jeasy.analysis.MMAnalyzer;


/*
*
* 中文分词器

*/


public
 
class
 ChineseSpliter 
{

    

/*
*
    * 对给定的文本进行中文分词
    * @param text 给定的文本
    * @param splitToken 用于分割的标记,如”|”
    * @return 分词完毕的文本
    

*/

    

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

        String result 

=
 
null
;
        MMAnalyzer analyzer 

=
 
new
 MMAnalyzer();      
        

try
      
        {

            result 

=
 analyzer.segment(text, splitToken);    
        }      
        

catch
 (IOException e)      
        {     
            e.printStackTrace();     
        }     
        

return
 result;
    }
}

复制代码

停用词处理

      去掉文档中无意思的词语也是必须的一项工作,这里简单的定义了一些常见的停用词,并根据这些常用停用词在分词时进行判断。

复制代码

package com.vista;


/*
*
* 停用词处理器
* @author phinecos 


*/


public
 
class
 StopWordsHandler 
{

    

private
 
static
 String stopWordsList[] 
=
{






我们

,



,

自己

,



,



,



,



,



,



,



,



,



,



,



,



,



,



,



,



,



,



,



,



,



,



,



,



,
“”
};
//
常用停用词


    
public
 
static
 boolean IsStopWord(String word)
    {

        

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

            

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

return
 
true
;
        }
        

return
 
false
;
    }
}

复制代码

训练集管理器

      我们的系统首先需要从训练样本集中得到假设的先验概率和给定假设下观察到不同数据的概率。

复制代码

package
 com.vista;

import
 java.io.BufferedReader;

import
 java.io.File;

import
 java.io.FileInputStream;

import
 java.io.FileNotFoundException;

import
 java.io.IOException;

import
 java.io.InputStreamReader;

import
 java.util.Properties;

import
 java.util.logging.Level;

import
 java.util.logging.Logger;

/**

* 训练集管理器

*/


public
 
class
 TrainingDataManager 
{

    

private
 String[] traningFileClassifications;
//
训练语料分类集合


    
private
 File traningTextDir;
//
训练语料存放目录


    
private
 
static
 String defaultPath 
=
 

D:\\TrainningSet

;
    
    

public
 TrainingDataManager() 
    {

        traningTextDir 

=
 
new
 File(defaultPath);
        

if
 (
!
traningTextDir.isDirectory()) 
        {

            

throw
 
new
 IllegalArgumentException(

训练语料库搜索失败! [

 
+
defaultPath 
+
 

]

);
        }
        

this
.traningFileClassifications 
=
 traningTextDir.list();
    }
    

/**

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

@return
 训练文本类别
    

*/

    

public
 String[] getTraningClassifications() 
    {

        

return
 
this
.traningFileClassifications;
    }
    

/**

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

@param
 classification 给定的分类
    * 

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

*/

    

public
 String[] getFilesPath(String classification) 
    {

        File classDir 

=
 
new
 File(traningTextDir.getPath() 
+
File.separator 
+
classification);
        String[] ret 

=
 classDir.list();
        

for
 (
int
 i 
=
 
0
; i 
<
 ret.length; i
++

        {

            ret[i] 

=
 traningTextDir.getPath() 
+
File.separator 
+
classification 
+
File.separator 
+
ret[i];
        }
        

return
 ret;
    }
    

/**

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

@param
 filePath 给定的文本文件路径
    * 

@return
 文本内容
    * 

@throws
 java.io.FileNotFoundException
    * 

@throws
 java.io.IOException
    

*/

    

public
 
static
 String getText(String filePath) 
throws
 FileNotFoundException,IOException 
    {

        InputStreamReader isReader 

=
new
 InputStreamReader(
new
 FileInputStream(filePath),

GBK

);
        BufferedReader reader 

=
 
new
 BufferedReader(isReader);
        String aline;
        StringBuilder sb 

=
 
new
 StringBuilder();
        

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

            sb.append(aline 

+
 

 

);
        }
        isReader.close();
        reader.close();
        

return
 sb.toString();
    }
    

/**

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

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

*/

    

public
 
int
 getTrainingFileCount()
    {

        

int
 ret 
=
 
0
;
        

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

            ret 

+=
getTrainingFileCountOfClassification(traningFileClassifications[i]);
        }
        

return
 ret;
    }
    

/**

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

@param
 classification 给定的分类
    * 

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

*/

    

public
 
int
 getTrainingFileCountOfClassification(String classification)
    {

        File classDir 

=
 
new
 File(traningTextDir.getPath() 
+
File.separator 
+
classification);
        

return
 classDir.list().length;
    }
    

/**

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

@param
 classification 给定的分类
    * 

@param
 key 给定的关键字/词
    * 

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

*/

    

public
 
int
 getCountContainKeyOfClassification(String classification,String key) 
    {

        

int
 ret 
=
 
0
;
        

try
 
        {

            String[] filePath 

=
 getFilesPath(classification);
            

for
 (
int
 j 
=
 
0
; j 
<
 filePath.length; j
++

            {

                String text 

=
 getText(filePath[j]);
                

if
 (text.contains(key)) 
                {

                    ret

++
;
                }
            }
        }
        

catch
 (FileNotFoundException ex) 
        {

        Logger.getLogger(TrainingDataManager.

class
.getName()).log(Level.SEVERE, 
null
,ex);
    
        } 
        

catch
 (IOException ex)
        {

            Logger.getLogger(TrainingDataManager.

class
.getName()).log(Level.SEVERE, 
null
,ex);
        }
        

return
 ret;
    }
}

复制代码

先验概率

      先验概率是我们需要计算的两大概率值之一

复制代码

package
 com.vista;

/**

* 先验概率计算
* <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表示训练文本集总数量。

*/


public
 
class
 PriorProbability 
{

    

private
 
static
 TrainingDataManager tdm 
=
new
 TrainingDataManager();
    

/**

    * 先验概率
    * 

@param
 c 给定的分类
    * 

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

*/

    

public
 
static
 
float
 calculatePc(String c)
    {

        

float
 ret 
=
 0F;
        

float
 Nc 
=
 tdm.getTrainingFileCountOfClassification(c);
        

float
 N 
=
 tdm.getTrainingFileCount();
        ret 

=
 Nc 
/
 N;
        

return
 ret;
    }
}

复制代码

分类条件概率

      这是另一个影响因子,和先验概率一起来决定最终结果

复制代码

package
 com.vista;


/**

* <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发生的条件概率。


*/


public
 
class
 ClassConditionalProbability 
{

    

private
 
static
 TrainingDataManager tdm 
=
 
new
 TrainingDataManager();
    

private
 
static
 
final
 
float
 M 
=
 0F;
    
    

/**

    * 计算类条件概率
    * 

@param
 x 给定的文本属性
    * 

@param
 c 给定的分类
    * 

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

*/

    

public
 
static
 
float
 calculatePxc(String x, String c) 
    {

        

float
 ret 
=
 0F;
        

float
 Nxc 
=
 tdm.getCountContainKeyOfClassification(c, x);
        

float
 Nc 
=
 tdm.getTrainingFileCountOfClassification(c);
        

float
 V 
=
 tdm.getTraningClassifications().length;
        ret 

=
 (Nxc 
+
 
1

/
 (Nc 
+
 M 
+
 V); 
//
为了避免出现0这样极端情况,进行加权处理


        
return
 ret;
    }
}

复制代码

分类结果

      用来保存各个分类及其计算出的概率值,

复制代码

package
 com.vista;

/**

* 分类结果

*/


public
 
class
 ClassifyResult 
{

    

public
 
double
 probility;
//
分类的概率


    
public
 String classification;
//
分类


    
public
 ClassifyResult()
    {

        

this
.probility 
=
 
0
;
        

this
.classification 
=
 
null
;
    }
}

复制代码

朴素贝叶斯分类器

      利用样本数据集计算先验概率和各个文本向量属性在分类中的条件概率,从而计算出各个概率值,最后对各个概率值进行排序,选出最大的概率值,即为所属的分类。

复制代码

package
 com.vista;

import
 com.vista.ChineseSpliter;

import
 com.vista.ClassConditionalProbability;

import
 com.vista.PriorProbability;

import
 com.vista.TrainingDataManager;

import
 com.vista.StopWordsHandler;

import
 java.util.ArrayList;

import
 java.util.Comparator;

import
 java.util.List;

import
 java.util.Vector;


/**

* 朴素贝叶斯分类器

*/


public
 
class
 BayesClassifier 
{

    

private
 TrainingDataManager tdm;
//
训练集管理器


    
private
 String trainnigDataPath;
//
训练集路径


    
private
 
static
 
double
 zoomFactor 
=
 
10.0f
;
    

/**

    * 默认的构造器,初始化训练集
    

*/

    

public
 BayesClassifier() 
    {

        tdm 

=
new
 TrainingDataManager();
    }

    
/**

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

@param
 X 给定的文本属性向量
    * 

@param
 Cj 给定的类别
    * 

@return
 分类条件概率连乘值,即<br>
    

*/

    

float
 calcProd(String[] X, String Cj) 
    {

        

float
 ret 
=
 
1.0F
;
        

//
 类条件概率连乘


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

            String Xi 

=
 X[i];
            

//
因为结果过小,因此在连乘之前放大10倍,这对最终结果并无影响,因为我们只是比较概率大小而已


            ret 
*=
ClassConditionalProbability.calculatePxc(Xi, Cj)
*
zoomFactor;
        }
        

//
 再乘以先验概率


        ret 
*=
 PriorProbability.calculatePc(Cj);
        

return
 ret;
    }
    

/**

    * 去掉停用词
    * 

@param
 text 给定的文本
    * 

@return
 去停用词后结果
    

*/

    

public
 String[] DropStopWords(String[] oldWords)
    {

        Vector

<
String
>
 v1 
=
 
new
 Vector
<
String
>
();
        

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

            

if
(StopWordsHandler.IsStopWord(oldWords[i])
==
false
)
            {

//
不是停用词


                v1.add(oldWords[i]);
            }
        }
        String[] newWords 

=
 
new
 String[v1.size()];
        v1.toArray(newWords);
        

return
 newWords;
    }
    

/**

    * 对给定的文本进行分类
    * 

@param
 text 给定的文本
    * 

@return
 分类结果
    

*/

    @SuppressWarnings(


unchecked

)
    

public
 String classify(String text) 
    {

        String[] terms 

=
 
null
;
        terms

=
 ChineseSpliter.split(text, 

 

).split(

 

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


        terms 
=
 DropStopWords(terms);
//
去掉停用词,以免影响分类


        
        String[] Classes 

=
 tdm.getTraningClassifications();
//
分类


        
float
 probility 
=
 
0.0F
;
        List

<
ClassifyResult
>
 crs 
=
 
new
 ArrayList
<
ClassifyResult
>
();
//
分类结果


        
for
 (
int
 i 
=
 
0
; i 
<
Classes.length; i
++

        {

            String Ci 

=
 Classes[i];
//
第i个分类


            probility 
=
 calcProd(terms, Ci);
//
计算给定的文本属性向量terms在给定的分类Ci中的分类条件概率
            

//
保存分类结果


            ClassifyResult cr 
=
 
new
 ClassifyResult();
            cr.classification 

=
 Ci;
//
分类


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


            System.out.println(

In process文本分类算法之--贝叶斯分类算法的实现Java版本.

);
            System.out.println(Ci 

+
 



 
+
 probility);
            crs.add(cr);
        }
        

//
对最后概率结果进行排序


        java.util.Collections.sort(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
 crs.get(
0
).classification;
    }
    
    

public
 
static
 
void
 main(String[] args)
    {

        String text 

=
 

微软公司提出以446亿美元的价格收购雅虎中国网2月1日报道 美联社消息,微软公司提出以446亿美元现金加股票的价格收购搜索网站雅虎公司。微软提出以每股31美元的价格收购雅虎。微软的收购报价较雅虎1月31日的收盘价19.18美元溢价62%。微软公司称雅虎公司的股东可以选择以现金或股票进行交易。微软和雅虎公司在2006年底和2007年初已在寻求双方合作。而近两年,雅虎一直处于困境:市场份额下滑、运营业绩不佳、股价大幅下跌。对于力图在互联网市场有所作为的微软来说,收购雅虎无疑是一条捷径,因为双方具有非常强的互补性。(小桥)

;
        BayesClassifier classifier 

=
 
new
 BayesClassifier();
//
构造Bayes分类器


        String result 
=
 classifier.classify(text);
//
进行分类


        System.out.println(

此项属于[

+
result
+

]

);
    }
}

复制代码

训练集与分类测试

作为测试,这里选用Sogou实验室的文本分类数据,我只使用了mini版本。迷你版本有10个类别 ,共计100篇文章,总大小244KB

使用的测试文本:

复制代码

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

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

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

微软和雅虎公司在2006年底和2007年初已在寻求双方合作。而近两年,雅虎一直处于困境:市场份额下滑、运营业绩不佳、股价大幅下跌。对于力图在互联网市场有所作为的微软来说,收购雅虎无疑是一条捷径,因为双方具有非常强的互补性。
(
小桥
)

复制代码

使用mini版本的测试结果:

复制代码

In process
文本分类算法之--贝叶斯分类算法的实现Java版本.

IT:

2.8119528E-5

In process

文本分类算法之--贝叶斯分类算法的实现Java版本.

体育:

2.791735E-21

In process

文本分类算法之--贝叶斯分类算法的实现Java版本.

健康:

3.3188528E-12

In process

文本分类算法之--贝叶斯分类算法的实现Java版本.

军事:

2.532662E-19

In process

文本分类算法之--贝叶斯分类算法的实现Java版本.

招聘:

2.3753596E-17

In process

文本分类算法之--贝叶斯分类算法的实现Java版本.

教育:

4.2023427E-19

In process

文本分类算法之--贝叶斯分类算法的实现Java版本.

文化:

6.0595915E-23

In process

文本分类算法之--贝叶斯分类算法的实现Java版本.

旅游:

5.1286412E-17

In process

文本分类算法之--贝叶斯分类算法的实现Java版本.

汽车:

4.085446E-8

In process

文本分类算法之--贝叶斯分类算法的实现Java版本.

财经:

3.7337095E-10

此项属于[IT]

复制代码

作者:洞庭散人

出处:http://phinecos.cnblogs.com/    

本博客遵从
Creative Commons Attribution 3.0 License,若用于非商业目的,您可以自由转载,但请保留原作者信息和文章链接URL。


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/138760.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pycharm编码设置为utf-8._python字符编码使用ascii编码对么

    pycharm编码设置为utf-8._python字符编码使用ascii编码对么我试着读入两个文本文件,一个用UTF8编码。我在PyCharm中使用python3。在两个文件中的示例:1.itsgroupareinSpain.itsgroupareinAntarctica.2.susgruposestanenEspaña.susgruposestanenAntártida.在命令行中,我使用:^{pr2}$把文件读入标准输入.在在我的…

    2022年8月28日
    2
  • cuda编程手册(cuda 编程)

    http://www.cnblogs.com/stewart/archive/2013/01/05/2846860.html目录:1.什么是CUDA2.为什么要用到CUDA3.CUDA环境搭建4.第一个CUDA程序5.CUDA编程5.1.基本概念5.2.线程层次结构5.3.存储器层次结构5.4.运行时

    2022年4月16日
    372
  • 【PHP SPL笔记】

    这几天,我在学习PHP语言中的SPL。这个东西应该属于PHP中的高…

    2022年1月18日
    32
  • imread参数_imread函数图片路径matlab

    imread参数_imread函数图片路径matlabimread的函数原型是:Matimread(conststring&filename,intflags=1);Mat是OpenCV里的一个数据结构,在这里我们定义一个Mat类型的变量img,用于保存读入的图像,在本文开始有写到,我们用imread函数来读取图像,第一个字段标识图像的文件名(包括扩展名),第二个字段用于指定读入图像的颜色和深度,它的取值可以有以下几种:

    2022年10月14日
    0
  • SCSA—信息安全概述

    SCSA—信息安全概述数字化时代威胁升级:攻击频发、传统安全防护逐渐失效、安全风险能见度低、缺乏自动化防御手段一、信息安全概述:1)信息安全:防止任何对数据进行未授权访问的措施,或者防止造成信息有意无意泄漏、破坏、丢失等问题的发生,让数据处于远离危险、免于威胁的状态或特性2)网络安全:计算机网络环境下的信息安全二、信息安全的脆弱性及常见安全攻击1.网络的开放性:互联网的美妙之处在于你与每一个相连,它的可怕之处在于每一个人与你相连2.协议栈的脆弱性及常见攻击1)协议栈的自身脆弱性:缺乏数据源验证机制、缺乏机密性保障机

    2022年6月20日
    30
  • Java.Utils:网络工具包[通俗易懂]

    Java.Utils:网络工具包[通俗易懂]packagecom.boob.common.utils;importorg.springframework.util.MultiValueMap;importorg.springframework.web.util.UriComponentsBuilder;importjavax.net.ssl.HttpsURLConnection;importjavax.servlet….

    2022年7月16日
    10

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号