Java利用樸素貝葉斯分類算法實現信息分類

貝葉斯分類算法 

貝葉斯分類算法是統計學的一種分類方法,它是一類利用概率統計知識進行分類的算法。在許多場合,樸素貝葉斯(Naïve Bayes,NB)分類算法可以與決策樹和神經網絡分類算法相媲美,該算法能運用到大型數據庫中,而且方法簡單、分類準確率高、速度快。

由於貝葉斯定理假設一個屬性值對給定類的影響獨立於其它屬性的值,而此假設在實際情況中經常是不成立的,因此其分類準確率可能會下降。為此,就衍生出許多降低獨立性假設的貝葉斯分類算法,如TAN(tree augmented Bayes network)算法。

那麼既然是樸素貝葉斯分類算法,它的核心算法又是什麼呢?

是下面這個貝葉斯公式:

換個表達形式就會明朗很多,如下:

我們最終求的p(類別|特征)即可!就相當於完成瞭我們的任務。

代碼實例

下面以女生找對象舉例,提取除女生找對象的幾個關鍵特征,比如顏值,性格,身高,上進心,資產情況為擇偶特征,通過事先調研等手段,獲取一部分數據樣本,即各類特征以及擇偶結果(分類)數據集。根據數據集利用樸素貝葉斯函數計算出個各個特征集合在該分類下的值,結果值最大的分類,認為該數據屬於這個分類。由於這個是利用概率學去計算得出的,不一定十分準確,數據集樣本數據越大,準確率就越高。

數據集data.txt

下面數據集每行代碼一條樣本數據,每條數據中的具體特征用逗號“,” 分割,特征順尋依次為

顏值,性格,身高,上進心,資產情況,女生中意結果

帥,好,高,上進,有錢,中意
不帥,好,高,上進,有錢,中意
帥,不好,高,上進,有錢,中意
帥,好,不高,上進,有錢,中意
帥,好,高,不上進,有錢,中意
帥,好,高,上進,不有錢,中意
帥,好,不高,不上進,有錢,不中意
不帥,不好,不高,上進,有錢,中意
不帥,不好,不高,上進,不有錢,不中意
帥,好,不高,上進,不有錢,中意
不帥,好,高,不上進,有錢,不中意
帥,不好,高,上進,有錢,不中意
不帥,好,高,上進,有錢,不中意
帥,不好,高,上進,不有錢,中意
帥,不好,高,不上進,有錢,中意
帥,好,高,上進,不有錢,不中意
帥,不好,不高,不上進,不有錢,不中意
不帥,不好,不高,不上進,不有錢,不中意
帥,好,不高,上進,有錢,中意
不帥,不好,不高,不上進,有錢,不中意
帥,好,高,上進,不有錢,中意
帥,好,不高,不上進,有錢,中意
帥,好,高,不上進,不有錢,不中意
帥,不好,高,不上進,有錢,不中意

代碼實現

 
 
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * @author liuya
 */
public class NaiveBayesModel {
 
    //樣本數據
    private static List<List<String>> data = new ArrayList<>();
    //樣本數據
    private static Set<List<String>> dataSet = new HashSet<>();
    //分類模型
    public static Map<String,String> modelMap = new HashMap<>();
    //樣本數據集
    private static String path = "./src/data.txt";
 
    public static void main(String[] args) {
        //訓練模型
        trainingModel();
        //識別
        classification("帥","好","高","上進","有錢");
        classification("不帥","不好","不高","不上進","不有錢");
    }
 
    /**
     * 導入數據
     * @param path
     * @return
     */
    public static void readData(String path){
        List<String> row = null;
        try {
            InputStreamReader isr = new InputStreamReader(new FileInputStream(new File(path)));
            BufferedReader br = new BufferedReader(isr);
            String str = null;
            while((str = br.readLine()) != null){
                row = new ArrayList<>();
                String[] str1 = str.split(",");
                for(int i = 0; i < str1.length ; i++) {
                    row.add(str1[i]);
                }
                dataSet.add(row);
                data.add(row);
            }
            br.close();
            isr.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("讀取文件內容出錯!");
        }
    }
 
    public static void trainingModel() {
        readData(path);
        String category1="中意";
        String category2="不中意";
        dataSet.forEach(e->{
          double categoryP1=  calculateBayesian(e.get(0),e.get(1),e.get(2),e.get(3),e.get(4),category1);
          double categoryP2=  calculateBayesian(e.get(0),e.get(1),e.get(2),e.get(3),e.get(4),category2);
            String result=categoryP1>categoryP2?category1:category2;
            modelMap.put(e.get(0)+"-"+e.get(1)+"-"+e.get(2)+"-"+e.get(3)+"-"+e.get(4),result);
        });
    }
 
    /**
     * 分類的識別
     * */
    public static void  classification(String look, String character, String height, String progresses, String wealthy){
        String key=look+"-"+character+"-"+height+"-"+progresses+"-"+wealthy;
        String result=modelMap.get(key);
        System.out.println("特征為"+look+","+character+","+height+","+progresses+","+wealthy+"的對象,女生"+result);
    }
 
 
    /**
     * 分類的核心是比較樸素貝葉斯的結果值,結果值大的認為就屬於該分類(會有誤差,數據集量越大,結果判定的準確率就會越高)由於分母相同可以直接比較分子來確定分類
     * */
    public static double calculateBayesian(String look, String character, String height, String progresses, String wealthy,String category) {
        //獲取P(x|y)的分母
      //  double denominator = getDenominator(look,character,height,progresses,wealthy);
        //獲取P(x|y)的分子
        double molecule = getMolecule(look,character,height,progresses,wealthy,category);
        return molecule/1;
    }
 
    /**
     * 獲取p(x|y)分子
     * @return
     */
    public static double getMolecule(String look, String character, String height, String progresses, String wealthy,String category) {
        double resultCP = getProbability(5, category);
        double lookCP = getProbability(0, look, category);
        double characterCP = getProbability(1, character, category);
        double heightCP = getProbability(2, height, category);
        double progressesCP = getProbability(3, progresses, category);
        double wealthyCP = getProbability(4, wealthy, category);
        return lookCP * characterCP * heightCP * progressesCP * wealthyCP * resultCP;
 
    }
 
    /**
     * 獲取p(x|y)分母
     * @return
     */
    public static double getDenominator(String look, String character, String height, String progresses, String wealthy) {
        double lookP = getProbability(0, look);
        double characterP = getProbability(1, character);
        double heightP = getProbability(2, height);
        double progressesP = getProbability(3, progresses);
        double wealthyP = getProbability(4, wealthy);
        return lookP * characterP * heightP * progressesP * wealthyP;
    }
 
 
    /**
     * 獲取某特征的概率
     * @return
     */
    private static double getProbability(int index, String feature) {
        int size = data.size();
        int num = 0;
        for (int i = 0; i < size; i++) {
            if (data.get(i).get(index).equals(feature)) {
                num++;
            }
        }
        return (double) num / size;
    }
 
    /**
     * 獲取某類別下某特征的概率
     * @return
     */
    private static double getProbability(int index, String feature, String category) {
        List<List<String>> filterData=data.stream().filter(e -> e.get(e.size() - 1).equals(category)).collect(Collectors.toList());
        int size =filterData.size();
        int num = 0;
        for (int i = 0; i < size; i++) {
            if (data.get(i).get(index).equals(feature)) {
                num++;
            }
        }
        return (double) num / size;
    }
}

輸出結果

使用場景

比如網站垃圾信息分類,文章自動分類,網站垃圾郵件分類,文件分類等。

以反垃圾啊郵件為例說明分類算法的使用,先將批量已經分類的郵件樣本(如5000封正常的郵件,2000封垃圾郵件),輸入分類算法進行訓練,得到一個垃圾郵件分類模型,然後利用分類算法結合分類模型對待處理郵件進行分類識別。

根據已經分類的樣本信息提取出一組特征信息的概率,比如郵件中“信用卡”這個詞出現在垃圾郵件的中的概率為20%,在非垃圾郵件的概率為1%,就得到一個分類模型。然後從待識別處理的郵件中提取特征值,結合分類模型,就可以判斷其分類是不是垃圾郵件。由於貝葉斯算法得到的分類判斷是概率值,所以可能會出現誤判。

以上就是Java利用樸素貝葉斯分類算法實現信息分類的詳細內容,更多關於Java 信息分類的資料請關註WalkonNet其它相關文章!

推薦閱讀: