1. 程式人生 > >貝葉斯模型構建分類器的設計與實現

貝葉斯模型構建分類器的設計與實現

作者:白寧超

2015年9月29日11:10:02  

摘要當前資料探勘技術使用最為廣泛的莫過於文字挖掘領域,包括領域本體構建、短文字實體抽取以及程式碼的語義級構件方法研究。常用的資料探勘功能包括分類、聚類、預測和關聯四大模型。本文針對四大模型之一的分類進行討論。分類演算法包括迴歸、決策樹、支援向量機、貝葉斯等,顯然,不少涉及機器學習的知識(隨後會寫些機器學習專題)。本文重點介紹貝葉斯分類,涉及樸素貝葉斯模型、二項獨立模型、多項模型、混合模型等知識。在本人研究貝葉斯分類過程中,發現很多部落格重複現象嚴重,並且在構建模型過程中存在大量的問題。包括部落格園中最受歡迎的幾篇,整個模型構造就不符合理論。索性自己重新查閱外文文獻,進而得到很大幫助。本文針對幾種模型,採用演算法概述、演算法公式解析、公式推理、優缺點比較等進行總結。()

相關文章

0 引言

     於半月前,針對文字分類進行學習,實驗的目的是通過對下圖1中的不同情感文字構建訓練集模型,對應的下圖2是對訓練集的註釋說明。類標0開頭為喜悅類別,類標1開頭的為憤怒類別,類別2開頭的是厭惡類別,類別3開頭的為低落類別。4個訓練集文字,分別對應4個分類。如何通過訓練集構造分類器,並對測試資料進行驗證是本課題的最終目的。其中會涉及貝葉斯公式的理解與實現,文字的預處理(下圖1中0_simplifyweibo的訓練集是處理過的資料如下圖),分詞工具的使用,不同貝葉斯模型的構造,試驗結果對比。核心思路就兩點:1,模型訓練階段  2,分類預測階段

。完整流程如下:

-->訓練文字預處理,構造分類器。(即對貝葉斯公式實現文字分類引數值的求解,暫時不理解沒關係,下文詳解

-->構造預測分類函式

-->對測試資料預處理

-->使用分類器分類

                       

1 四種模型結構

  • 樸素貝葉斯模型     NaiveBayes model                                 NM
  • 二項獨立模型        Bnary independence model                     BIM
  • 多項式模型           multinomial model                                  MM
  • 混合模型              hyorid   model                                        HM
  • 平滑因子混合模型   hyorid model with new smooth factore     HM&NSF 

2 樸素貝葉斯分類器

  • 思想概述

-- 公式 P( Category | Document) = (P ( Document | Category ) * P( Category))/ P(Document)
-- 樸素貝葉斯分類器: P(c|d)~=P(c)*P(d|c)
-- 訓練階段:對每一個W_k,C_i估計先驗條件概率P(w_k|c_i)和概率P(C_i)
-- 分類階段:計算後驗概率,返回使後驗概率最大的類
-- C(d)=argmax {P(C_i)*P(d|c_i)

    對於一個新的訓練文件d,究竟屬於如上四個類別的哪個類別?我們可以根據貝葉斯公式,只是此刻變化成具體的物件。 

> P( Category | Document):測試文件屬於某類的概率

> P( Category)):從文件空間中隨機抽取一個文件d,它屬於類別c的概率。(某類文件數目/總文件數目

> (P ( Document | Category ):文件d對於給定類c的概率(某類下文件中單詞數/某類中總的單詞數

> P(Document):從文件空間中隨機抽取一個文件d的概率(對於每個類別都一樣,可以忽略不計算。此時為求最大似然概率

>  C(d)=argmax {P(C_i)*P(d|c_i)}:求出近似的貝葉斯每個類別的概率,比較獲取最大的概率,此時文件歸為最大概率的一類,分類成功。

綜上:對訓練集構成訓練分類器模型的過程,本質是對引數模型的求解。然後將這些引數在預測方法中使用,根據公式獲取最大概率即可完成文件分類。

  • 公式推導與解析

樸素貝葉斯公式:(假設條件:當文件d屬於類c時,文件d中的元素w的取值與類c中的w的取值是獨立關係[實際顯示不獨立,一種近似處理])

 

公式解析:

> P(d):從文件空間中隨機抽取一個文件d的概率(對於每個類別都一樣,可以忽略不計算。此時為求最大似然概率)   

> P(c):從文件空間中隨機抽取一個文件d,它屬於類別c的概率。(某類文件數目/總文件數目)

> (P ( d| c ):文件d對於給定類c的概率(某類下文件中單詞數/某類中總的單詞數)

> 類別集: c={c1,c2,.....,cn}

> 文件向量: d={w1,w2,.....,wn} 

> 類別集: c={c1,c2,.....,cn}

> P(c| d):測試文件d屬於某類c的概率(估計條件概率)【估計概率:訓練集中進行訓練過程,在某種假設條件下實現的】

> MaxP(c| d):測試文件d屬於某類c的最大概率

先驗條件概率:

 

將(2)式代入(1)得:(下式中p(d)對於所有的類c都是一樣的)

 

注:只要對上式中的分母求出最大值即可。分母中的左部分通過(某類文件數目/總文件數目)易得,右側中通過求文件d和c中單詞量即可。到此,解決思路和思想都有了,下面基於此完成演算法。

  • 演算法介紹與實現

演算法1:文字分類的樸素貝葉斯演算法

訓練階段:對每一個w_k,c_i估計先驗條件概率p(w_k|c_i)和概率p(c_i)。

分類階段:計算後驗概率,返回使後驗概率最大的類。

 

演算法具體實現:

    /**
     * 樸素貝葉斯文字分類器
     * 訓練階段
     * 演算法思想:文件d屬於某類c的概率=文件空間隨機抽取一個文件d屬於某類c的概率*文件中的單詞與總單詞的比例
     *        P(c|d)~=P(c)*P(d|c)
     *        P(c)=classDocnum/classAlldocnum
     * 計算引數:
     *       classDocnum:某類中的文件數目
     *       classAlldocnum:資料集中總的文件數目
     *       classWordfru:某類下文件中單詞頻數
     *       classAllwordnum:某類中總的單詞數
     * @param fileDirPath 訓練集資料夾目錄
     */
package com.naivebayes.bnc;



import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import jeasy.analysis.MMAnalyzer;

/**
 * @公式 P( Category | Document) = (P ( Document | Category ) * P( Category))/ P(Document)
 * @樸素貝葉斯分類器: P(c|d)~=P(c)*P(d|c)
 * @演算法思想:
 *        訓練階段:對每一個W_k,C_i估計先驗條件概率P(w_k|c_i)和概率P(C_i)
 *        分類階段:計算後驗概率,返回使後驗概率最大的類
 *        C(d)=argmax {P(C_i)*P(d|c_i)}
 * @條件:給定目標值時屬性之間相互條件獨立。換言之。該假定說明給定例項的目標值情況下。觀察到聯合的a1,a2...an的概率正好是對每個單獨屬性的概率乘積: P(a1,a2...an | Vj ) =Πi P( ai| Vj ).
 * @缺點: 在屬性個數比較多或者屬性之間相關性較大時,NBC模型的分類效率比不上決策樹模型。
 * @優點:決策樹模型也有一些缺點,比如處理缺失資料時的困難,過度擬合問題的出現,以及忽略資料集中屬性之間的相關性等,適用NBC(樸素貝葉斯分類)
 * @比較:在屬性相關性較小時,NBC模型的效能稍微良好。屬性相關性較小的時候,其他的演算法效能也很好,這是由於資訊熵理論決定的。
 * @author 白寧超
 *
 */
 public class NaiveBayesToClass {
    //統計某類文件的數目
    public static Map<String,Integer> classDocnum=new HashMap<String, Integer>();     
    //屬於類別的單詞 總數
    public static int classAlldocnum=0; 
    //統計某類中某個單詞出現的次數
    public static Map<String,Integer> classWordfru=new HashMap<String, Integer>(); 
    //統計某類中的單詞總數
    public static Map<String,Integer> classAllwordnum=new HashMap<String, Integer>(); 
    /**
     * 樸素貝葉斯文字分類器
     * 訓練階段
     * 演算法思想:文件d屬於某類c的概率=文件空間隨機抽取一個文件d屬於某類c的概率*文件中的單詞與總單詞的比例
     *        P(c|d)~=P(c)*P(d|c)
     *        P(c)=classDocnum/classAlldocnum
     * 計算引數:
     *       classDocnum:某類中的文件數目
     *       classAlldocnum:資料集中總的文件數目
     *       classWordfru:某類下文件中單詞頻數
     *       classAllwordnum:某類中總的單詞數
     * @param fileDirPath 訓練集資料夾目錄
     */
    public static void  BayesModel(String fileDirPath){
        try{
            File dir=new File(fileDirPath);
            if(dir.exists()&&dir.isDirectory()){
                File[] files=dir.listFiles();  //獲取所有訓練集檔案
                for(File file:files){
                    String classNo=file.getName().split("\\_")[0];//獲取檔案類標
                    FileInputStream   stream=new FileInputStream(file);     //獲取檔案流
                    InputStreamReader strRead=new InputStreamReader(stream,"UTF-8"); //對檔案進行讀取,且指定編碼格式
                    BufferedReader bufReader = new BufferedReader(strRead);
                    String line=null;
                    //讀取檔案內容
                    while((line=bufReader.readLine())!=null){
                        //統計某類文件的數目
                        if(classDocnum.containsKey(classNo)){
                            classDocnum.put(classNo, classDocnum.get(classNo)+1);
                        }
                        else{
                            classDocnum.put(classNo, 1);//第一次存資料,沒有類標,但是已經讀取一行,故設定1
                        }
                        String lineText = line.trim(); //除去字串開頭和末尾的空格或其他字元
                        String[] words = lineText.split(" "); 
                        //遍歷所有單詞
                        for(String word:words){
                            //統計某類中的單詞總數
                            if(classAllwordnum.containsKey(classNo)){
                                classAllwordnum.put(classNo, classAllwordnum.get(classNo)+1);
                            }
                            else{
                                classAllwordnum.put(classNo, 1);
                            }
                            //統計某類中某個單詞出現的次數
                            String wordNo=classNo+"_"+word;
                            if(classWordfru.containsKey(wordNo)){
                                classWordfru.put(wordNo, classWordfru.get(wordNo)+1);
                            }
                            else{
                                classWordfru.put(wordNo, 1);
                            }
                        }
                        classAlldocnum++;
                    }
                    strRead.close();
                }
            }
            else{
                System.out.println("找不到目錄檔案"+fileDirPath);
            }    
        }
        catch (Exception e) {
            System.out.println("出錯資訊描述如下:"+e.getMessage());
        }
    }
    /**
     * 對測試文字進行分類預測
     * 預測階段:
     * @param testText  測試資料集
     * @return 返回分類結果
     */
    public static String PredictReslut(String testText){
        //預測結果
        String PredictResult="";
        testText=SplitWords(testText, " ");// 對測試文件進行中文分詞處理
        String[] words=testText.split(" ");  //對字串進行分割
        double argmax = Double.NEGATIVE_INFINITY;//最大類概率(預設值為負無窮小),是否可以寫成0?(無窮小本身就是接近0)
        Iterator iterator=classDocnum.keySet().iterator();//遍歷
        while(iterator.hasNext()){
            String classNo = (String) iterator.next();
            double prior = classDocnum.get(classNo)/(double)classAlldocnum;//先驗概率
            double classcount=(double)(classAllwordnum.get(classNo)+1);//某一類的最大值
            double likelihoodProbability=0;                           //初始化似然概率
            //根據公式求解最大似然概率,其中words相當於屬性即多維的
            for (int i = 0; i < words.length; i++){
                String word_classNo = words[i]+"_"+classNo;              //獲取測試資料的單詞類別
                //與訓練資料詞庫進行對比,求得相似的概率
                if(classWordfru.containsKey(word_classNo)){
                    //將連乘裝換成對數相加【ln(a*b)=lna+lnb】,提高效率
                    likelihoodProbability += Math.log(classWordfru.get(word_classNo)/classcount);
                }
                else{
                    likelihoodProbability += Math.log(1/classcount);
                }
            }
            //利用自然對數e^loga = a,取得原始值 
            likelihoodProbability = Math.exp(likelihoodProbability)*prior;
             System.out.println("classNo:"+classNo);
             System.out.println("最大似然概率:"+argmax);
             System.out.println("似然概率:"+likelihoodProbability);
             if(likelihoodProbability>argmax){
                 argmax = likelihoodProbability;  //最大似然概率一直保持最大的似然概率
                 PredictResult = classNo;  //返回分類的結果
             }
        }
        System.out.println("***************************************************");
        System.out.println("【樸素貝葉斯最終分類結果:】"+PredictResult);
        return PredictResult;
    }
    
    /**
     * 對字串進行中文分詞處理
     * @param text   給定預處理的字串
     * @param splitToken  用於分割的標記。如","
     * @return  處理後的字串
     */
    public static String SplitWords(String text,String splitToken){
        String result = null;
        MMAnalyzer analyzer = new MMAnalyzer();      //極易中文分詞
        try      {
            result = analyzer.segment(text, splitToken);    
        }      
        catch (IOException e){     
            e.printStackTrace();     
        }     
        return result;
    }
}
View Code

執行結果:

 

  • 優缺點對比分析

  1.  * @條件:給定目標值時屬性之間相互條件獨立。換言之。該假定說明給定例項的目標值情況下。觀察到聯合的a1,a2...an的概率正好是對每個單獨屬性的概率乘積: P(a1,a2...an | Vj ) =Πi P( ai| Vj ).
  2.  * @缺點: 在屬性個數比較多或者屬性之間相關性較大時,NBC模型的分類效率比不上決策樹模型。
  3.  * @優點:決策樹模型也有一些缺點,比如處理缺失資料時的困難,過度擬合問題的出現,以及忽略資料集中屬性之間的相關性等,適用NBC(樸素貝葉斯分類)
  4.  * @比較:在屬性相關性較小時,NBC模型的效能稍微良好。屬性相關性較小的時候,其他的演算法效能也很好,這是由於資訊熵理論決定的。

3 二項獨立模型

  • 思想概述

二項獨立模型又稱為多變數伯努利模型,是樸素貝葉斯最常用的實現模型之一。使用二值向量來表示文件,當w=1時,單詞在文件中出現w=0不出現。只是在求解先驗概率時候有所變化,其他和樸素貝葉斯一樣。後面會涉及平滑因子避免分母為0的問題。

  • 分類模型:對於類c_i,單詞w_k的先驗條件概率

二項獨立模型的先驗概率:(假設條件:其在一定假設條件下實現的,即給定的類c_i,文件d中單詞w_k和w_i是否出現是相互獨立的。)

 

公式解析:

> 其使用二值向量來表示一個文件,即d={w1,w2,...,w|v|},其中w_k屬於{0,1}

>|V|:單詞表的尺寸

> w_k=1:單詞w在文件中出現

> P_ki:P(w_k=1|c_i)

其中文件d可以看做|V|重獨立的伯努利試驗,對於給定的c_i,文件d的條件概率可以通過(3)估計這裡n=|V|,同樣文件d的類別可以通過公式(4)決定,把公式(6)代入(2)(4))

 

> (7)式到(8): ΠA*B=ΣlogA+ΣlogB

> (8)式中可知,雖然模型中考慮單詞出現和未出現情況,但是分類起作用的實際上是w_k非零的單詞。

引數估計:

模型中用到的引數都是通過訓練階段,從訓練資料中學習得到的,通常取它們的最大似然估計(即(1)式中去掉分母p(d)),設訓練文件集D={d1,d2,...,d|v|}

類c的概率由下式估計:

 

> n_i:訓練集中類別c_i的 文件數

當類別c_i 的文件數為0,即n_i=0,導致p(c_i)=0.最後最大似然概率為0的後果,該如何避免?

平滑因子的出現:

 

> n_i:訓練集中類別c_i的 文件數

> n_ki:訓練文件集中含有w_k,並且類別c_i的文件數

  • 演算法介紹與實現:

具體程式碼實現:

package com.bernouli.bnc;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import jeasy.analysis.MMAnalyzer;

public class BernouliBayesClass {

    //統計某類中文件的數目
    public static Map<String,Integer> classcountMap=new HashMap<String, Integer>(); 
    //統計訓練集中總文件的數目
    public static Integer datacount=0; 
    //訓練集中所含單詞通過類標進行標記(訓練集的單詞已經去重,不考慮頻數)
    public static Map<String,Integer> likelihoodMap=new HashMap<String, Integer>(); 
    //所有類詞彙集合(總詞彙表的長度)
    public static Set<String> vocabularySet = new HashSet<String>();
    

    /**
     * 建立樸素貝葉斯文字分類模型
     * @param fileDirPath 檔案目錄
     */
    public static void BayesModel(String fileDirPath){
        try{
            File dir=new File(fileDirPath);
            if(dir.exists()&&dir.isDirectory()){
                File[] files=dir.listFiles();  //獲取所有訓練集檔案
                //遍歷訓練集檔案
                for(File file:files){
                    String classNo=file.getName().split("\\_")[0];//獲取檔案類標
                    FileInputStream   stream=new FileInputStream(file);     //獲取檔案流
                    InputStreamReader strRead=new InputStreamReader(stream,"UTF-8"); //對檔案進行讀取,且指定編碼格式
                    BufferedReader bufReader = new BufferedReader(strRead);
                    String line=null;
                    //讀取檔案內容
                    while((line=bufReader.readLine())!=null){
                        //統計某類文件的數目
                        if(classcountMap.containsKey(classNo)){
                            classcountMap.put(classNo, classcountMap.get(classNo)+1);
                        }
                        else{
                            classcountMap.put(classNo, 1);//第一次存資料,沒有類標,但是已經讀取一行,故設定1
                        }
                        String lineText = line.trim(); //除去字串開頭和末尾的空格或其他字元
                        String[] words = lineText.split(" "); 
                        Set<String> wordaSet = arrayToSet(words);//單詞去重,列出詞彙表的尺寸
                        if(!wordaSet.isEmpty()){
                            vocabularySet.addAll(wordaSet);//加入詞彙表集合
                        }
                        //遍歷所有單詞
                        for(String word:words){
                            String wordNo=word+"_"+classNo;
                            if(likelihoodMap.containsKey(wordNo)){
                                likelihoodMap.put(wordNo, likelihoodMap.get(wordNo)+1);
                            }
                            else{
                                likelihoodMap.put(wordNo, 1);
                            }
                        }
                        datacount++;
                    }
                    strRead.close();
                }
            }
            else{
                System.out.println("找不到目錄檔案"+fileDirPath);
            }
            
        }
        catch (Exception e) {
            System.out.println("出錯資訊描述如下:"+e.getMessage());
        }
    }
    /**
     * 將陣列轉換成Set集合(相當於去重)
     * @param words 
     * @return
     */
    public static Set<String> arrayToSet(String[] words){
        Set<String> wordaSet = new HashSet<String>();
        for (String word:words) {
            if(""!=word&&!word.equals("")){
                wordaSet.add(word);
            }
        }
        return wordaSet;
    }
    
    /**
     * 對字串進行中文分詞處理
     * @param text   給定預處理的字串
     * @param splitToken  用於分割的標記。如","
     * @return  處理後的字串
     */
    public static String SplitWords(String text,String splitToken){
        String result = null;
        MMAnalyzer analyzer = new MMAnalyzer();      //極易中文分詞
        try{
            result = analyzer.segment(text, splitToken);    
        }      
        catch (IOException e){     
            e.printStackTrace();     
        }     
        return result;
    }
    
    
    /**
     * 對測試文字進行分類預測
     * @param testText  測試資料集
     * @return 返回分類結果
     */
    public static String PredictReslut(String testText){
        String PredictResult="";
        testText=SplitWords(testText, " ");  // 對測試文件進行中文分詞處理
        String[] words=testText.split(" ");  //對字串進行分割
        Set<String> wordSet = arrayToSet(words);//單詞去重,獲取測試集的單詞表尺寸
        //TODO 不存在的單詞的校驗
        wordSet.addAll(vocabularySet);
        double argmax = Double.NEGATIVE_INFINITY;//最大類概率(預設值為負無窮小),是否可以寫成0?(無窮小本身就是接近0)
        //for (Iterator iterator = classcountMap.keySet().iterator(); iterator.hasNext();) 
        Iterator iterator=classcountMap.keySet().iterator();//遍歷
        while(iterator.hasNext()){
            String classNo = (String) iterator.next();
            double prior = classcountMap.get(classNo)/(double)datacount;//先驗概率
            double likelihoodProbability=0;                           //初始化似然概率
            //根據公式求解最大似然概率,其中words相當於屬性即多維的
            for (String word:wordSet){
                if(""!=word){
                    String word_classNo = word+"_"+classNo;              //獲取測試資料的單詞類別
                    //與訓練資料詞庫進行對比,求得相似的概率
                    if(likelihoodMap.containsKey(word_classNo)){
                        //將連乘裝換成對數相加【ln(a*b)=lna+lnb】,提高效率
                        likelihoodProbability += Math.log((likelihoodMap.get(word_classNo)+1)/((double)classcountMap.get(classNo)+2));
                    }
                    else{
                        likelihoodProbability +=Math.log((1-1/(double)(classcountMap.get(classNo)+2)));
                    }
                }
            }
            //利用自然對數e^loga = a,取得原始值 
             likelihoodProbability += Math.exp(likelihoodProbability)*prior;
             System.out.println("最大似然概率:"+argmax);
             System.out.println("第["+classNo+"]類似然概率:"+likelihoodProbability);
             if(likelihoodProbability>argmax){
                 argmax = likelihoodProbability;  //最大似然概率一直保持最大的似然概率
                 PredictResult = classNo;  //返回分類的結果
             }
        }
        System.out.println("***************************************************");
        System.out.println("【伯努利模型最終分類結果:】"+PredictResult);
        return PredictResult;
    }
    public static void main(String[] args) {
        long beginTime=System.currentTimeMillis();
        String filedir="./data_training";
        
        String testText = "南京 爆炸 事件 中 , 南京 電視臺 生活 頻道 因為 最 早 做 了 現場 直播 而 受到 上級 批評 ; 爆出 “ 最 牛1 官腔 ” 的1 江蘇 電視臺 城市 頻道 也 因 直播 此 事 被 上級 批評 , 相關 欄目 也 面臨 停 播 。 不 知道 是 官員 的1 可悲 、 人民 的1 可悲 , 還 是 記者 的1 可悲 ! 一 個 悲劇 的1 社會 ! 真 TM 齷齪";
        BayesModel(filedir);
        PredictReslut(testText);
         long endTime=System.currentTimeMillis();
         long between=endTime-beginTime;
         System.out.println("共計用時:"+between+"毫秒");
    }

}
View Code

 執行結果:

 

4 多項式模型

  • 概述

比BIM更為常用,與BIM不同,多項式,模型考慮單詞在文件中的詞頻資訊。最終處理還是後驗條件概率在建模和預測的影響,不同於以上先驗概率的求解。下面具體剖析。

  • 分類模型

模型中,文件可以看做一個長度為f的單詞序列(同一個單詞可出現多次),並假設文件的長度與類別無關,而且每個單詞出現的位置與其他單詞獨立,設單詞w_k在文件中詞頻f_k。

文件d在給定類別c_i的條件概率p(d|c_i)可由下面公式

 

將(11)式代入(4)得多項式模型的分類判別規則: 

 

> 多項式模型在判別文件d的類別時,同樣只是使用頻數非零的單詞。(多項式也是通過文件中出現單詞來判定文件類別

  • 引數估計

對於類別c_i的先驗概率估計。多項模型與二項模型一樣,都使用公式(9)

單詞w_k對於類c_i的條件先驗條件概率的估計(多項式考慮同一詞多次出現

 

> n_ki:w_k在類別c_i中出現總次數

> |V|: 訓練集中單詞表的尺寸

  • 演算法介紹與實現

演算法實現:

package com.multinomial.bnc;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;


import jeasy.analysis.MMAnalyzer;

public class MultinoBayesclass {
    
    //詞彙表集合(詞彙表的尺寸,不考慮頻數,即重複單詞)
    public static Set<String> vocabularySet = new HashSet<String>();
    //屬於總的單詞數
    public static Integer datacount=0; 
    //訓練文件中含有單詞並且類標為某類的單詞數
    public static Map<String,Integer> likelihoodMap=new HashMap<String, Integer>(); 
    //訓練集中某類的單詞數
    public static Map<String,Integer> classVocabularyMap=new HashMap<String, Integer>(); 
    

    /**
     * 建立樸素貝葉斯文字分類模型
     * @param fileDirPath 檔案目錄
     */
    public static void BayesModel(String fileDirPath){
        try{
            File dir=new File(fileDirPath);
            if(dir.exists()&&dir.isDirectory()){
                File[] files=dir.listFiles();  //獲取所有訓練集檔案
                //遍歷訓練集檔案
                for(File file:files){
                    String classNo=file.getName().split("\\_")[0];//獲取檔案類標
                    FileInputStream   stream=new FileInputStream(file);     //獲取檔案流
                    InputStreamReader strRead=new InputStreamReader(stream,"UTF-8"); //對檔案進行讀取,且指定編碼格式
                    BufferedReader bufReader = new BufferedReader(strRead);
                    String line=null;
                    //讀取檔案內容
                    while((line=bufReader.readLine())!=null){
                        String lineText = line.trim(); //除去字串開頭和末尾的空格或其他字元
                        String[] words = lineText.split(" "); 
                        //加入詞彙表集合
                        for(String word:words){
                            vocabularySet.add(word);
                            //統計某類中的單詞總數
                            if(classVocabularyMap.containsKey(classNo)){
                                classVocabularyMap.put(classNo, classVocabularyMap.get(classNo)+1);
                            }
                            else{
                                classVocabularyMap.put(classNo, 1);
                            }
                            //統計某類中某個單詞出現的次數
                            String wordNo=word+"_"+classNo;
                            if(likelihoodMap.containsKey(wordNo)){
                                likelihoodMap.put(wordNo, likelihoodMap.get(wordNo)+1);
                            }
                            else{
                                likelihoodMap.put(wordNo, 1);
                            }
                        }
                        datacount++;
                    }
                    strRead.close();
                }
            }
            else{
                System.out.println("找不到目錄檔案"+fileDirPath);
            }
            
        }
        catch (Exception e) {
            System.out.println("出錯資訊描述如下:"+e.getMessage());
        }
    }
    

    
    
    /**
     * 對測試文字進行分類預測
     * @param testText  測試資料集
     * @return 返回分類結果
     */
    public static String PredictReslut(String testText)
    {
        int vsSize = vocabularySet.size();//詞彙表長度
        String PredictResult="";
        testText=SplitWords(testText, " ");// 對測試文件進行中文分詞處理
        String[] words=testText.split(" ");  //對字串進行分割
        double argmax = Double.NEGATIVE_INFINITY;//最大類概率(預設值為負無窮小),是否可以寫成0?(無窮小本身就是接近0)
        Iterator iterator=classVocabularyMap.keySet().iterator();//遍歷
        while(iterator.hasNext())
        {
            String classNo = (String) iterator.next();
            double prior = classVocabularyMap.get(classNo)/(double)datacount;//先驗概率
            double likelihoodProbability=0;                           //初始化似然概率
            //根據公式求解最大似然概率,其中words相當於屬性即多維的
            for (String word:words) 
            {
                if(""!=word)
                {
                    String word_classNo = word+"_"+classNo;              //獲取測試資料的單詞類別
                    //與訓練資料詞庫進行對比,求得相似的概率
                    if(likelihoodMap.containsKey(word_classNo)){
                        //將連乘裝換成對數相加【ln(a*b)=lna+lnb】,提高效率
                        likelihoodProbability +=Math.log((likelihoodMap.get(word_classNo)+1)/((double)classVocabularyMap.get(classNo)+vsSize));
                    }
                    
            
           

相關推薦

模型構建分類設計實現

作者:白寧超 2015年9月29日11:10:02   摘要:當前資料探勘技術使用最為廣泛的莫過於文字挖掘領域,包括領域本體構建、短文字實體抽取以及程式碼的語義級構件方法研究。常用的資料探勘功能包括分類、聚類、預測和關聯四大模型。本文針對四大模型之一的分類進行討論。分類演算法包括迴歸、決策樹、支援

【機器學習實戰】網格搜尋--新聞文字分類調優

#對文字分類的樸素貝葉斯模型的超引數組合進行網格搜尋 #從sklearn.datasets中匯入20類新聞文字抓取器 from sklearn.datasets import fetch_20newsgroups import numpy as np #抓取新

(資料探勘-入門-8)基於樸素的文字分類

主要內容: 1、動機 2、基於樸素貝葉斯的文字分類器 3、python實現 一、動機 之前介紹的樸素貝葉斯分類器所使用的都是結構化的資料集,即每行代表一個樣本,每列代表一個特徵屬性。 但在實際中,尤其是網頁中,爬蟲所採集到的資料都是非結構化的,如新聞、微博、帖子等,如果要對對這一類資料進行分類,應該怎麼辦

機器學習基礎——帶你實戰樸素模型文字分類

本文始發於個人公眾號:TechFlow 上一篇文章當中我們介紹了樸素貝葉斯模型的基本原理。 樸素貝葉斯的核心本質是假設樣本當中的變數服從某個分佈,從而利用條件概率計算出樣本屬於某個類別的概率。一般來說一個樣本往往會含有許多特徵,這些特徵之間很有可能是有相關性的。為了簡化模型,樸素貝葉斯模型假設這些變數是獨

【原始碼】心音分類設計實現

本程式碼為即將發行的關於完整機器學習流程的電子書的完整程式碼。 This submission provides the code explained by the (upcoming) eBook on the complete machine learning workflow.

用於文字相關說話人驗證的J-Vector提取和聯合模型的聯合學習

Joint Learning of J-Vector Extractor and Joint Bayesian Model for Text Dependent Speaker Verification Ziqiang Shi, Liu Liu, Huibin Lin, Rujie L

利用spark做文字分類(樸素模型

樸素貝葉斯模型 樸素貝葉斯法是基於貝葉斯定理與特徵條件獨立假設的分類方法。對於給定的訓練資料集,首先基於特徵條件獨立假設學習輸入/輸出的聯合概率分佈;然後基於此模型,對給定的輸入x,利用貝葉斯定理求出後驗概率最大的輸出y。至於樸素貝葉斯模型的原理部分,這裡就不

分類-3-生成學習-3-樸素模型、laplace平滑、多元伯努利事件模型、多項式事件模型

多元伯努利事件模型( multi-variate Bernoulli event model) 在 GDA 中,我們要求特徵向量 x 是連續實數向量。如果 x 是離散值的話,可以考慮採用樸素貝葉斯的分類方法。 假如要分類垃圾郵件和正常郵件。 我們用

乾貨 | 基於推斷的分類模型& 機器學習你會遇到的“坑”

本文轉載自公眾號“讀芯術”(ID:AI_Discovery)本文3153字,建議閱讀8分鐘。本文

我理解的樸素模型【轉】

package 規則 dia div href 重要 源代碼 容易 計算 轉自:http://www.cnblogs.com/nxld/p/6607943.html 我想說:“任何事件都是條件概率。”為什麽呢?因為我認為,任何事件的發生都不是完全偶然的,它都會以其他事件的

sklearn中的樸素模型及其應用

1.使用樸素貝葉斯模型對iris資料集進行花分類 嘗試使用3種不同型別的樸素貝葉斯: 高斯分佈型 多項式型 伯努利型 2.使用sklearn.model_selection.cross_val_score(),對模型進行驗證 from sklearn.datasets import load

第11次作業 sklearn中的樸素模型及其應用

1.使用樸素貝葉斯模型對iris資料集進行花分類 嘗試使用3種不同型別的樸素貝葉斯: 高斯分佈型 多項式型 伯努利型 from sklearn import datasets iris=datasets.load_iris() from sklearn.naive_bayes import G

【原始碼】MATLAB的BMS工具箱:模型平均(BMA)

Zellner g先驗條件下線性模型的貝葉斯模型平均 Bayesian Model Averaging for linear modelsunder Zellner’s g prior. 可選項包括:固定的(BRIC,UIP, …)和可調的g先驗(經驗貝葉斯,hyper-g)、

(三)樸素運用——文字分類

1、貝葉斯理論 當我們有樣本(包含特徵和類別)的時候,我們非常容易通過 p(x)p(y|x)=p(y)p(x|y) p ( x

基於LVD、模型演算法實現的電商行業商品評論情感分析案例

一、 專案需求 現在大家進行網購,在購物之前呢,肯定會看下相關商品的評論,看下好評和差評,然後再綜合衡量,最後才會決定是否購買相關的商品。對一個指定商品,生產商,賣家,買家認同該商品的哪些優點/不認同

數學之美:馬爾科夫鏈的擴充套件-網路 詞分類

前面介紹的馬爾科夫鏈是一種狀態序列,但在實際中,各個事物之間不僅使用鏈序列起來的,而是互相交叉,錯綜複雜。因此通過各個事物之間的聯絡,可以將馬爾科夫鏈推廣至圖論中。 沒想到貝葉斯網路還可以用於詞分類。在前面我們介紹到通過使用SVD可以對文字進行分類,如果把文字和關鍵詞的

機器學習學習筆記 第十六章 基於的新聞分類

利用貝葉斯分類器進行文字分類 考慮情況 1 對於文字分析,首先我們應該先利用停用詞語料庫對部分大量出現的停用詞進行遮蔽,可以百度直接搜停用詞進行下載 我們對於經常出現的詞,有可能是一個不太重要的詞,比

【演算法】樸素法之分類演算法

樸素貝葉斯法之分類演算法 說明         本文只是對於樸素貝葉斯法的其中的一個分類演算法的學習。參考來源《統計學習方法》。 一、 輸入 訓練資料 T={(x1,y1),(x2,y2),...(

《web安全之機器學習入門》第7章樸素模型檢測webshell

N-gram演算法,認為第N個詞只與前面的第N-1個詞相關。例如對於一個句子,I love my country.那麼2-gram得到的詞集為:["I love","love my","my country"]程式碼如下:檢測webshell的第一種方式的思路為,將php w