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


相关推荐

  • document.getElementById 学习总结「建议收藏」

    document.getElementById 学习总结「建议收藏」document.getElementById获取控件对象为空的解决方法 1.下面是一个简单的例子,页面加载时显示一段信息代码如下:         alert(“hello!!!”);        在页面加载之前,会输出一些信息 执行后,确实是“在页面加载前,输出了信息”

  • MVC三层架构(详解)「建议收藏」

    MVC三层架构(详解)「建议收藏」1:初始MVC(1):三层架构三层架构是指:视图层View、服务层Service,与持久层Dao。它们分别完成不同的功能。View层:用于接收用户提交请求的代码在这里编写。Service层:系统的业务逻辑主要在这里完成。Dao层:直接操作数据库的代码在这里编写。为了更好的降低各层间的耦合度,在三层架构程序设计中,采用面向抽象编程。即上层对下层的调用,是通过接口实现的。而下层对上层的真正服务提供者,是下层接口的实现类。服务标准(接口)是相同的,服务提供者(实现类)可以更换。这就

  • 用Pandas 处理大数据的3种超级方法

    用Pandas 处理大数据的3种超级方法原文链接:3simplewaystohandlelargedatawithPandas作者|GeorgeSeif译者|jojoa易上手,文档丰富的Pandas已经成为时下最火的数据处理库。此外,Pandas数据处理能力也一流。其实无论你使用什么库,大量的数据处理起来往往回遇到新的挑战。数据处理时,往往会遇到没有足够内存(RAM)这个硬件问题。企业往往…

  • pycharm默认主题_pycharm主题插件

    pycharm默认主题_pycharm主题插件一、Pycharm基本设置(小白篇)1、打开Pycharm设置,【File】-【Settings】2、设置解释器,【File】-【Settings】-【Project:项目名字】-【ProjectInterpreter】-【设置图标】-【Add】-【浏览到目标解释器】,选择相应解释器即可。3、设置pycharm主题,【File】-【Settings】-【Appearance&Behavior】-【Appearance】;Theme:修改主题、Usecustomf

  • Flicker-detect Sensor_sensorless sensing

    Flicker-detect Sensor_sensorless sensingSensor在日光灯作为光源下获取图像数据时会产生flicker,其根本原因是照在不同pixel上光能量不同产生的,所接受的光能量的不同也就是图像的亮度的不同。电源的频率有两种标准:50Hz(大陆)和60Hz(台湾、日本)的正弦波形,当然能量是没有方向性的,因此对应的能量是一个频率为100Hz和120Hz的波形,如下图1所示:图1、60Hz电源频率及能量波形      由于能量在时间…

    2022年10月13日
  • VB.NET章鱼哥出品—怎样解决MDI子窗口被父窗口中的控件覆盖的问题

    VB.NET章鱼哥出品—怎样解决MDI子窗口被父窗口中的控件覆盖的问题

发表回复

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

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