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.");
            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.
IT:2.8119528E-5
In process.
体育:2.791735E-21
In process.
健康:3.3188528E-12
In process.
军事:2.532662E-19
In process.
招聘:2.3753596E-17
In process.
教育:4.2023427E-19
In process.
文化:6.0595915E-23
In process.
旅游:5.1286412E-17
In process.
汽车:4.085446E-8
In process.
财经:3.7337095E-10
此项属于[IT]

作者:洞庭散人

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

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

文本分类算法之--贝叶斯分类算法的实现Java版本相关推荐

  1. c语言贝叶斯分类,基于朴素贝叶斯分类器的文本分类算法(C语言)

    基于朴素贝叶斯分类器的文本分类算法(C语言) 基于朴素贝叶斯分类器的文本分类算法(C语言).txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了.他只是比对方更珍惜这份感情.#include ...

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

    基于朴素贝叶斯的文本分类算法 摘要:常用的文本分类方法有支持向量机.K-近邻算法和朴素贝叶斯.其中朴素贝叶斯具有容易实现,运行速度快的特点,被广泛使用.本文详细介绍了朴素贝叶斯的基本原理,讨论多项式模 ...

  3. 文本分类算法比较与总结

    本文对常用的几种文本分类算法进行了比较与总结,主要阐述它们之间的优劣,为算法的选择提供依据. 一.Rocchio算法 Rocchio算法应该算是人们思考文本分类问题最先能想到的,也是最符合直觉的解决方 ...

  4. 文本分类算法研究与实现

    1 设计题目 文本分类的算法研究与实现 2 课题背景及研究现状 2.1 课题背景 近年来,随着Internet的迅猛发展,网络信息和数据信息不断扩展,如何有效利用这一丰富的数据信息,己成为广大信息技术 ...

  5. 基于协同训练的半监督文本分类算法

    标签: 半监督学习,文本分类 作者:炼己者 --- 本博客所有内容以学习.研究和分享为主,如需转载,请联系本人,标明作者和出处,并且是非商业用途,谢谢! 如果大家觉得格式看着不舒服,也欢迎大家去看我的 ...

  6. 菜鸟进阶: C++实现KNN文本分类算法

    作者:finallyliuyu(转载请注明原作者和出处) (代码暂不发布源码下载版,以后会发布) KNN文本分类算法又称为(k nearest neighhor).它是一种基于事例的学习方法,也称懒惰 ...

  7. 文本分类算法TextCNN

    目录 前言 一.TextCNN 1-1.TextCNN结构图以及介绍: 1-2.与CNN相比,textCNN的不同之处 1-3.TextCNN的超参数调参 总结 前言 TextCNN是在2014年,由 ...

  8. 【NLP从零入门】预训练时代下,深度学习模型的文本分类算法(超多干货,小白友好,内附实践代码和文本分类常见中文数据集)

    如今NLP可以说是预训练模型的时代,希望借此抛砖引玉,能多多交流探讨当前预训练模型在文本分类上的应用. 1. 任务介绍与实际应用 文本分类任务是自然语言处理(NLP)中最常见.最基础的任务之一,顾名思 ...

  9. 【NLP文本分类算法集锦】零基础入门经典文本分类项目实战(附代码+数据集)

    前言 大家好,我是阿光. 本专栏整理了<NLP文本分类算法集锦>,内包含了各种常见的中英文文本分类算法,以及常见的NLP任务:情感分析.新闻分类以及谣言检测等. 文本分类是NLP的必备入门 ...

最新文章

  1. wes 7 gost 下载_南京地铁实现移动5G全覆盖下载速度快到飞起_机房360
  2. SpringBoot Mybatis解决使用PageHelper一对多分页问题
  3. ICLR 2020 | “同步平均教学”框架为无监督学习提供更鲁棒的伪标签
  4. 通过OAuth 2.0和Okta构建具有安全的服务器到服务器通信的Spring Boot应用
  5. php laravel 返回统一格式,封装的统一的Laravel响应类,返回数据类
  6. Java即时类| hashCode()方法与示例
  7. mac 命令失效问题 命令不存在 : command not found
  8. Android App优化之提升你的App启动速度之实例挑战
  9. 【C++】常用查找算法
  10. 弱电工程项目管理软件
  11. 2021年最新3d材质贴图素材大合集来咯
  12. SharedPreferences in credential encrypted storage are not available until after user is unlocked
  13. HTML制作简单的页面
  14. Linux性能监控命令_nmon 安装与使用
  15. 使用Mathematica绘制星形线(Astroid)
  16. i7z – 用来查看CPU状况
  17. 关于时间转换总是显示1970年的问题
  18. LINUX从零开始——ENGINEER(云计算应用管理)——Day2 [磁盘空间管理、交换空间、VDO]
  19. 17春c语言,2017春C语言程序设计 上(长安大学)
  20. react: 动态设置ant-design/icons图标

热门文章

  1. [信息系统安全实验] 实验1.Web安全
  2. 用流星制作多人TicTacToe游戏
  3. LTspice 中的扬声器模型
  4. 电信联通ADSL共享上网检测的原理与实现
  5. 多子系统多业务模块的复杂数据处理——基于指令集物联网操作系统的项目开发实践
  6. 【应用回归分析】CH3 回归参数的估计3——约束最小二乘估计
  7. 碳中和背景下我国空调系统发展趋势2022(李先庭)
  8. PDM系统在技术状态管理中的应用研究
  9. 窗口跑屏幕外面了怎么办
  10. 计算机打游戏的硬件,电脑玩游戏主要看显卡吗?小白装机硬件选择误区 (全文)...