文本分类算法之–贝叶斯分类算法的实现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。


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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • maven中jar和war的区别

    maven中jar和war的区别jar文件包括java普通类、资源文件和普通文件,在maven中即是打包src/main/java和src/main/resources资源文件夹下的所有文件。在打包的时候会自动生成MATA-INF文件夹,用于存储maven的pom信息和MANIFEST.MF文件。例如:war文件包含全部的web应用程序,即所有的java类,配置信息和jsp、js等静态资源。但是需要注意war

  • Mac 如何强制关机?「建议收藏」

    Mac 如何强制关机?「建议收藏」在通常情况下,MacOSX是非常稳定的,但是它偶尔也会发点小脾气,出现应用程序没有响应的情况。如果你正在运行的应用程序失去响应,强制退出一般都能解决,但是偶尔也会出现整个系统都失去响应,鼠标不能用,这时候你只能强制关机了。楼主使用Mac2年多了,只遇到过一次死机哈。下面介绍两种强制关机的解决办法:1、不用学就明白的,跟windows一样的,长按电源键不放,五秒之后电脑就会强行切断电源。不过它有个坏处,就是可能会损坏系统文件,所以建议不要使用这种方法。2、同时按住control+.

  • 设计模式(一)工厂模式Factory(创建型)

    设计模式(一)工厂模式Factory(创建型)设计模式一工厂模式Factory在面向对象编程中,最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下,new操作符直接生成对象会带来一些问题。举例来说,许多类型对象的创造需要一系列的步骤:你可能需要计算或取得对象的初始设置;选择生成哪个子对象实例;或在生成你需要的对象之前必须先生成一些辅助功能的对象。在这些………

  • python动图爱心表白_用python画动态图

    python动图爱心表白_用python画动态图初级画心学Python,感觉你们的都好复杂,那我来个简单的,我是直接把心形看作是一个正方形+两个半圆:于是这就很简单了,十行代码解决:importturtleastt.pensi…

  • SQL基础语句汇总[通俗易懂]

    SQL基础语句汇总[通俗易懂]引言语法基础连接数据库查看数据库使用数据库查看表查看表结构建表修改表添加字段移除字段变更字段插入全字段插入个别字段插入普通查询单表全字段查询单表个别字段查询多表查询条件查询单表条件查询多表条件查询嵌套查询并查询交查询删除更新常用函数求和求平均值计数求最大值求最小值常用的修饰符distinct字段中值唯一limit查询结果数限制

  • mysql 字符串索引 起始_mysql截取字符串「建议收藏」

    mysql 字符串索引 起始_mysql截取字符串「建议收藏」mysql截取字符串mysql索引从1开始一、mysql截取字符串函数1、left(str,index)从左边第index开始截取2、right(str,index)从右边第index开始截取3、substring(str,index)当index>0从左边开始截取直到结束当index<0从右边开始截取直到结束当index=0返回空4、substring(str,index,…

发表回复

您的电子邮箱地址不会被公开。

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