統計學習方法(四)——樸素貝葉斯法

/*先把標題給寫了、這樣就能常常提醒本身*/java

題記:今天下午去上廁所的一下子時間,就把第四章給掃完了,說是掃完了主要是由於沒有深刻去看,對於某些證實都直接跳過了,看了一下里面的例子,大概懂個意思就好了git

1. 樸素貝葉斯法github

  設輸入空間維向量的集合,輸出空間爲類標記集合,輸入特徵向量,輸出類標記爲的聯合機率分佈,數據集學習

獨立同分布產生。spa

  樸素貝葉斯法就是經過訓練集來學習聯合機率分佈.具體怎麼學習呢? 主要就是從先驗機率分佈和條件機率分佈入手,倆個機率相乘便可得聯合機率。3d

  爲何稱之爲樸素呢,主要是其將條件機率的估計簡化了,對條件機率分佈做了條件獨立性假設,這也是樸素貝葉斯法的基石,具體的假設以下code

                   

此公式在假設條件之下能夠等價於blog

                      

如今, 對於給定的輸入向量,經過學習到的模型計算後驗機率分佈P(Y=Ck|X=x),後驗分佈中最大的類做爲的輸出結果,根據貝葉斯定理可知後驗機率爲get

 

 

上面的公式可能有點歧義,分母的Ck應該寫成Cj纔對,由於P(X=x)=E P(Y=Cj)*P(X=x|Y=Cj)it

對於全部都是相同的,即此能夠將輸出結果簡化爲

                        

至此大概講解了樸素貝葉斯的基本方法步驟了,關於參數估計還有具體實例下次再寫了。夏天真熱啊!

2. 參數估計

  2.1 極大似然估計

上一小節講了對於給定的輸入向量,其輸出結果可表示爲

                         

對此可應用極大似然估計法來估計相應的機率,如先驗機率的極大似然估計是

                        

設第個特徵可能取值的集合爲,條件機率的極大似然估計是

                       

公式看起來可能有點不實在,仍是直接上例子來講明吧!

 

例子:試由下表的訓練數據學習一個樸素貝葉斯分類器並肯定的類標記,表中爲特徵,爲類標記。


解:先驗機率,

條件機率

據此可算出後驗分佈中值最大的,也就是最終的類標記爲-1

   2.2 貝葉斯估計

  極大似然估計的一個多是會出現所要估計的機率值爲0的狀況,這時會影響到後驗機率的計算結果,解決這一問題的方法是採用貝葉斯估計,具體的只須要在極大似然估計的基礎上加多一個參數便可。懶得繼續寫公式了,不想寫了,剛剛碼完代碼!!

 

有興趣的能夠看一下具體的代碼實現

package org.juefan.bayes;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.juefan.basic.FileIO;
/**
 * 這是一個簡易的貝葉斯分類器
 * 只適用於離散數據,連續型數據的暫時請先繞道了^.^
 * @author JueFan
 */
public class NaiveBayes{

    //平滑指數, 默認爲拉普拉斯平滑,極大似然估計則爲0
    private static double Lambda  = 1; 
    //存儲先驗機率數據
    private Map<Object, Double> PriorProbability = new HashMap<>();
    //存儲條件機率數據
    private Map<Object, ArrayList<Map<Object, Double>>> ConditionProbability = new HashMap<>();

    /**
     * 計算類別的先驗機率
     * @param datas 
     */
    public void setPriorPro(ArrayList<Data> datas){
        int counts = datas.size();
        for(Data data: datas){
            if(PriorProbability.containsKey(data.y)){
                PriorProbability.put(data.y, PriorProbability.get(data.y) + 1);
            }else {
                PriorProbability.put(data.y, (double) 1);
            }
        }
        for(Object o: PriorProbability.keySet())
            PriorProbability.put(o, (PriorProbability.get(o) + Lambda)/(counts + Lambda * PriorProbability.size()));
    }

    /**
     * 計算條件機率
     * @param datas
     */
    public void setCondiPro(ArrayList<Data> datas){
        Map<Object, ArrayList<Data>> tmMap = new HashMap<>();
        //按類別先將數據分類存放
        for(Data data: datas){
            if(tmMap.containsKey(data.y)){
                tmMap.get(data.y).add(data);
            }else {
                ArrayList<Data> tmDatas = new ArrayList<>();
                tmDatas.add(data);
                tmMap.put(data.y, tmDatas);
            }
        }
        //條件機率主體
        for(Object o: tmMap.keySet()){
            ArrayList<Map<Object, Double>> tmCon = new ArrayList<>();
            int LabelCount = tmMap.get(o).size();
            //計算每一個特徵的相對頻數
            for(Data data: tmMap.get(o)){
                for(int i = 0; i < data.x.size(); i++){
                    if(tmCon.size() < i + 1){
                        Map<Object, Double> tmMap2 = new HashMap<>();
                        tmMap2.put(data.x.get(i), (double) 1);
                        tmCon.add(tmMap2);
                    }else {
                        if(tmCon.get(i).containsKey(data.x.get(i))){
                            tmCon.get(i).put(data.x.get(i), tmCon.get(i).get(data.x.get(i)) + 1);
                        }else {
                            tmCon.get(i).put(data.x.get(i),  (double) 1);
                        }
                    }
                }
            }
            //計算條件機率
            for(int i = 0; i < tmCon.size(); i++){
                for(Object o1: tmCon.get(i).keySet()){
                    tmCon.get(i).put(o1, (tmCon.get(i).get(o1) + Lambda)/(LabelCount + Lambda * tmCon.get(i).size()));
                }
            }
            ConditionProbability.put(o, tmCon);
        }
    }

    /**
     * 判斷實例的類別
     * @param data
     * @return 判斷結果
     */
    public Object getLabel(Data data){
        Object label = new Object();
        double pro = 0D;
        for(Object o: PriorProbability.keySet()){
            double tmPro = 1;
            tmPro *= PriorProbability.get(o);
            for(int i = 0; i < data.x.size(); i++){
                tmPro *= ConditionProbability.get(o).get(i).get(data.x.get(i));
            }
            if(tmPro > pro){
                pro = tmPro;
                label = o;
            }
            System.out.println(o.toString() + " :的後驗機率爲: " + tmPro);
        }
        return label;
    }

    public static void main(String[] args) {
        ArrayList<Data> datas = new ArrayList<>();
        FileIO fileIO = new FileIO();
        fileIO.setFileName(".//file//bayes.txt");
        fileIO.FileRead();
        for(String data: fileIO.fileList){
            datas.add(new Data(data));
        }

        NaiveBayes bayes = new NaiveBayes();
        bayes.setPriorPro(datas);
        bayes.setCondiPro(datas);

        Data data = new Data("1\t2\tS");
        System.out.println(data.toString() + "\t的判斷類別爲: " + bayes.getLabel(data));
    }
}

 

 對代碼有興趣的能夠上本人的GitHub查看:https://github.com/JueFan/StatisticsLearningMethod/

相關文章
相關標籤/搜索