朴素贝叶斯分类器

朴素贝叶斯分类器
1.基本公式:
$P(A|B)P(B) = P(B|A)P(A) $ (1)
设输入样本数据为$D={(x_{0},y_{0}),(x_{1},y_{1}),..,(x_{n},y_{n}) }$,其中$x\in X,y \in Y,x_{i}^{(j)}$表示第i个样本中的第j个特征。
$x^{j}$可能的取值$x^{(j)} = { a_{j1},a_{j2},..,a_{jS_{j}}},j=1,2,..,S_{j}$,y可能的取值为$y_{i} \in {c_{0},c_{1},..,c_{k}}$。
公式(1)在样本D空间中的描述为:
$P(y_{i}|x) = \frac{P(x|y_{i})P(y_{i})}{P(x)}$ (2)
即根据输入的样本x输出对应的y中各个分类的概率值。取概率值最高的分类作为最终的预测结果。由于公式2中的$P(x)$对所有的$y$分类的贡献都一样,那么公式2可以化简为:
$P(y_{i}|x) = P(x|y_{i})P(y_{i})$
最终的预测结果为:
$arg max(P(y_{i} = c_{k}|x)),c_{k} \in {c_{0},c_{1},..,c_{K}}$

算法步骤:
1).计算先验概率和条件概率:
$P(y_{i}) = \frac{\sum_{i=1}^{N}I(y_{i} = c_{k})}{N},k = 1,2,..,K$
$P(x^{(j)}=a_{jl}|y_{i} = c_{k}) = \frac{\sum_{i=1}^{N}I(x^{(j)} = a_{jl},y_{i}=c_{k})}{\sum_{i=1}^{N}I(y_{i}=c_{k})}$
2).对于给定的实例$x=(x_{(1)},x_{(2)},..,x_{(n)})^T$ 计算:
$P(Y=c_{k}) \prod_{j=1}^{n}P(X^{(j)} = x^{(j)}|Y=c_{k}),k=1,2,..,K$
3).确定实例$x$的分类:
$y = arg max {P(Y=c_{k}) \prod_{j=1}^{n}P(X^{(j)} = x^{(j)}|P(Y = c_{k}))}$

import numpy as np

class NormBayes:
    def __init__(self):
        self.__label = []
        self.__Prob_yi=[]
        self.__Prob_xi=[]
        self.__lamda = 1
    def fit(self,X,Y):
        '''
        @X - input numpy array as features
        @Y - input label
        '''
        self.__calc_prob_yi(Y)
        self.__calc_prob_xi(X,Y)        

    def __calc_prob_yi(self,Y):
        #clac  priori probability
        self.__label = list(set(Y))
        N = Y.shape[0];k = 0
        self.__Prob_yi = np.zeros((len(self.__label)))
        for l in self.__label:
            count = 0
            for n in range(N):
                if(Y[n] == l):
                    count += 1
            self.__Prob_yi[k] = float(count) / N
            #print "(yi = ",l,")= ",self.__Prob_yi[k]
            k += 1
    def __calc_prob_xi(self,X,Y):
        #conditional probability
        y = list(set(Y))
        num_cls = len(y);
        feat_dim = X.shape[1]
        self.__Prob_xi = np.zeros((num_cls,feat_dim))
        for c in range(num_cls): 
            count_yi = self.__count_label(Y,y[c])
            #print "count_yi=",count_yi
            yi_idx = self.__get_data_idx(Y,y[c])
            subX = self.__get_sub_data(X,yi_idx)
            for f in range(feat_dim):
                count_xi = np.count_nonzero(subX[:,f])                
                #print "count_x",f,"= ",count_xi
                self.__Prob_xi[c][f] = float(count_xi) / count_yi
                #print "(ck=",c,"xi=",f,")= ",self.__Prob_xi[c][f]

    def __count_label(self,Y,y):     
        return list(Y).count(y)

    def __get_data_idx(self,Y,y):
        return [i for i,a in enumerate(Y) if a == y]

    def __get_sub_data(self,X,idx=[]):
        data = np.zeros((len(idx),X.shape[1]))
        for i in range(len(idx)):
            data[i] = X[idx[i]]
        return data
    def predict(self,X):
        '''
        @X - single-predict if you input one sample,  
            multi-predict if you input serval samples
        @return index of label
        '''
        rows,cols = X.shape
        num_cls = len(self.__label)
        rsp = []
        for r in range(rows):            
            prob_y = np.zeros((num_cls))
            for n in range(num_cls):
                prod = 1.
                for c in range(cols):
                    if(X[r][c] != 0):
                        prod *= self.__Prob_xi[n][c]
                prob_y[n] = prod * self.__Prob_yi[n]
            maxIdx = prob_y.argmax()
            rsp.append((self.__label[maxIdx],prob_y[maxIdx]))
        return rsp

例1.练一个贝叶斯分类器并确定$x=(2,S)^T$的类标记y,表中$X^{(1)},X^{(2)}$为特征,取值的集合分别为:$A_{1} \in {1,2,3},A_{2} \in {S,M,L}$
$Y$为类标记,$Y \in {-1,1}$

123456789101112131415
$X^{(1)}$111112222233333
$X^{(2)}$SMMSSSMMLLLMMLL
$Y$-1-111-1-1-11111111-1
X = np.array([[1,0,0,1,0,0],[1,0,0,0,1,0],[1,0,0,0,1,0],
             [1,0,0,1,0,0],[1,0,0,1,0,0],[0,1,0,1,0,0],
              [0,1,0,0,1,0],[0,1,0,0,1,0],[0,1,0,0,0,1],
              [0,1,0,0,0,1],[0,0,1,0,0,1],[0,0,1,0,1,0],
              [0,0,1,0,1,0],[0,0,1,0,0,1],[0,0,1,0,0,1]])
Y = np.array([-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1])
#Y = np.array([0,0,1,1,0,0,0,1,1,1,1,1,1,1,0])

#single-predict
#x = np.array([[0,1,0,1,0,0]])
#multi-predict
x = np.array([[0,1,0,1,0,0],[1,0,0,0,1,0],[0,0,1,0,1,0]])

clf = NormBayes()
clf.fit(X,Y)
print clf.predict(x)
[(-1, 0.066666666666666666), (-1, 0.066666666666666666), (1, 0.11851851851851851)]

例2.贷款申请样本数据表

| ID | 年龄 | 有工作 | 有自己的房子 | 信贷情况 | 类别 | | ---- | -------- | ---------- | -------------- | ------------ | -------- | | 1 | 青年 | 否 | 否 | 一般 | 否 | | 2 | 青年 | 否 | 否 | 好 | 否 | | 3 | 青年 | 是 | 否 | 好 | 是 | | 4 | 青年 | 是 | 是 | 一般 | 是 | | 5 | 青年 | 否 | 否 | 一般 | 否 | | 6 | 中年 | 否 | 否 | 一般 | 否 | | 7 | 中年 | 否 | 否 | 好 | 否 | | 8 | 中年 | 是 | 是 | 好 | 否 | | 9 | 中年 | 否 | 是 | 非常好 | 是 | | 10 | 中年 | 否 | 是 | 非常好 | 是 | | 11 | 老年 | 否 | 是 | 非常好 | 是 | | 12 | 老年 | 否 | 是 | 好 | 是 | | 13 | 老年 | 是 | 否 | 好 | 是 | | 14 | 老年 | 是 | 否 | 非常好 | 是 | | 15 | 老年 | 否 | 否 | 一般 | 否 |

试预测:$x = (老年,是,否,一般,是)$ 是否发放贷款

X = np.array([[1,0,0,0,0,1,0,0,0],[1,0,0,0,0,0,1,0,0],[1,0,0,1,0,0,1,0,1],
             [1,0,0,1,1,1,0,0,1],[1,0,0,0,0,1,0,0,0],[0,1,0,0,0,1,0,0,0],
             [0,1,0,0,0,0,1,0,0],[0,1,0,1,1,0,1,0,0],[0,1,0,0,1,0,0,1,1],
             [0,1,0,0,1,0,0,1,1],[0,0,1,0,1,0,0,1,1],[0,0,1,0,1,0,1,0,1],
             [0,0,1,1,0,0,1,0,1],[0,0,1,1,0,0,0,1,1],[0,0,1,0,0,1,0,0,0]])
Y = np.array([0,0,1,1,0,0,0,1,1,1,1,1,1,1,0])
x = np.array([[0,0,1,1,0,1,0,0,1]])

clf = NormBayes()
clf.fit(X,Y)
print clf.predict(x)
[(1, 0.014631915866483762)]

转载于:https://my.oschina.net/u/733649/blog/864119

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值