机器学习(九):朴素贝叶斯

一、基本原理

朴素贝叶斯(naive Bayes)算法是一种基于贝叶斯定理与特征条件独立假设的分类方法,属于生成模型。其基本思想是:先验概率+数据=后验概率,即P(class | feature)=\frac{P(class) P(feature| class)}{P(feature)}。其基本流程是:首先基于特征条件独立假设学习输入输出的联合概率分布,然后基于此模型,对给定输入x,利用贝叶斯定理求出后验概率最大的输出y

假设输入空间 \mathbb{X} \in \mathcal{R} ^{n}n维向量集合,输出空间为类别集合{Y} = \left\{c_{1}, c_{2}, \cdots, c_{t} \right\},输入特征向量x \in \mathbb{X},输出所属类别y \in \mathbb{Y}X是输入空间 \mathbb{X} 上的随机变量,Y是输出空间\mathcal{Y}上的随机变量,P(X, Y)X, Y的联合概率分布,训练数据集T=\left\{\left(x^{(1)}, y^{(1)}\right),\left(x^{(2)}, y^{(2)}\right), \cdots,\left(x^{(m)}, y^{(m)}\right)\right\}P(X, Y)独立同分布产生。

朴素贝叶斯分类时对给定的输入x^{(i)} ,计算后验概率分布P\left(Y=c_{k} | X=x^{(i)}\right),将后验概率最大的类作为x^{(i)}所属类别输出。其计算方式如下:P\left(Y=c_{k} | X=x^{(i)}\right)=\frac{P\left(X=x^{(i)} | Y=c_{k}\right) P\left(Y=c_{k}\right)}{\sum_{k=1}^{t} P\left(X=x^{(i)} | Y=c_{k}\right) P\left(Y=c_{k}\right)}
由于对条件概率做了条件独立性假设,则 \begin{aligned} P\left(X=x^{(i)} | Y=c_{k}\right) =P\left(X_{1}^{(i)}=x_{1}^{(i)}, \cdots, X_{n}^{(i)}=x_{n}^{(i)} | Y=c_{k}\right) =\prod_{j=1}^{n} P\left(X_{j}^{(i)}=x_{j}^{(i)} | Y=c_{k}\right) \end{aligned}

由上两式,有 P\left(Y=c_{k} | X=x^{(i)}\right)=\frac{\prod_{j=1}^{n} P\left(X_{j}^{(i)}=x_{j}^{(i)} | Y=c_{k}\right)}{\sum_{k=1}^{t} P\left(Y=c_{k}\right) \prod_{j=1}^{n} P\left(X_{j}^{(i)}=x_{j}^{(i)} | Y=c_{k}\right)} P\left(Y=c_{k}\right)

因此朴素贝叶斯算法的优化模型为 \begin{array}{c} {\underset{c_{k}}{\arg \max } P\left(Y=c_{k} | X=x^{(i)}\right)=\underset{c_{k}}{\arg \max } \frac{\prod_{j=1}^{n} P\left(X_{j}^{(i)}=x_{j}^{(i)} | Y=c_{k}\right)}{\sum_{k=1}^{t} P\left(Y=c_{k}\right) \prod_{j=1}^{n} P\left(X_{j}^{(i)}=x_{j}^{(i)} | Y=c_{k}\right)} P\left(Y=c_{k}\right)} \\ {=\underset{c_{k}}{\arg \max } P\left(Y=c_{k}\right) \prod_{j=1}^{n} P\left(X_{j}^{(i)}=x_{j}^{(i)} | Y=c_{k}\right)}\end{array}

因为对于每一个c_{k},分母\sum_{k=1}^{t} P\left(Y=c_{k}\right) \prod_{j=1}^{n} P\left(X_{j}^{(i)}=x_{j}^{(i)} | Y=c_{k}\right)的值都是相同的。

求解朴素贝叶斯模型相当于求解一个概率值,对于样本数据集可以求出先验概率p\left(Y=c_{k}\right)p\left(Y=c_{k}\right)=\frac{\sum_{i=1}^{m} I\left(y^{(i)}=c_{k}\right)}{t} \quad k=1,2, \cdots, t
其中I(x)为示性函数,x为真时值为1,否则为0。
条件概率为

\begin{array}{c} {P\left(X_{j}^{(i)}=x_{j}^{(i)} | Y=c_{k}\right)=\frac{\sum_{i=1}^{m} I\left(x_{j}^{(i)}=a_{j l}, y^{(i)}=c_{k}\right)}{\sum_{i=1}^{m} I\left(y^{(i)}=c_{k}\right)}} \\ {j=1,2, \cdots, n} ~~~~ {l=1,2, \cdots, S_{j}}\end{array}

其中x_{j}^{(i)}代表i个样本的第j个特征x_{j}^{(i)} \in\left\{a_{j 1}, a_{j 2}, \cdots, a_{j S_{j}}\right\}a_{j l} 表示第j个特征的第l个值。
由于极大似然估计可能会出现概率为0的情况,而影响后验概率的计算,使分类产生偏差,于是可采用贝叶斯估计 P_{\lambda}\left(Y=c_{k}\right)=\frac{\sum_{i=1}^{m} I\left(y^{(i)}=c_{k}\right)+\lambda}{t+t \lambda}

P_{\lambda}\left(X_{j}^{(i)}=x_{j}^{(i)} | Y=c_{k}\right)=\frac{\sum_{i=1}^{m} I\left(x_{j}^{(i)}=a_{j l}, y^{(i)}=c_{k}\right)+\lambda}{\sum_{i=1}^{m} I\left(y^{(i)}=c_{k}\right)+S_{j} \lambda}

其中\lambda \geqslant 0,当\lambda=1时称为拉普拉斯平滑(Laplace smoothing)。

二、算法实现

以下为MultinomialNB和GaussianNB的手动实现。

  1. 多项式贝叶斯分类器适用于离散特征的分类问题,其实现过程正如原理部分所述。
import numpy as np

class MultinomialNB(object):
    def __init__(self,alpha=1.0,fit_prior=True,class_prior=None):
        self.alpha = alpha
        self.fit_prior = fit_prior
        self.class_prior = class_prior
        self.classes = None
        self.conditional_prob = None
        
    def _calculate_feature_prob(self,feature):
        values = np.unique(feature)
        total_num = float(len(feature))
        value_prob = {}
        for v in values:
            value_prob[v] = np.sum(np.equal(feature,v)+self.alpha)/(total_num+len(values)*self.alpha)
        return value_prob
    
    def fit(self,X,y):
        self.classes = np.unique(y)
        if self.class_prior == None:
            class_num = len(self.classes)
            if not self.fit_prior:
                self.class_prior = [1.0/class_num for _ in range(class_num)]
            else:
                self.class_prior = []
                sample_num = float(len(y))
                for c in self.classes:
                    c_num = np.sum(np.equal(y,c))
                    self.class_prior.append((c_num+self.alpha)/(sample_num+class_num*self.alpha))
        self.conditional_prob = {}
        for c in self.classes:
            self.conditional_prob[c] = {}
            for i in range(len(X[0])):
                feature = X[np.equal(y,c)][:,i]
                self.conditional_prob[c][i] = self._calculate_feature_prob(feature)
        return self
    
    def _get_xj_prob(self,values_prob,target_value):
        return values_prob[target_value]
    
    def _predict_single_sample(self,x):
        label = -1
        max_posterior_prob = 0
        for c_index in range(len(self.classes)):
            current_class_prior = self.class_prior[c_index]
        
        current_conditional_prob = 1.0
        feature_prob = self.conditional_prob[self.classes[c_index]]
        j = 0
        for feature_i in feature_prob.keys():
            current_conditional_prob *= self._get_xj_prob(feature_prob[feature_i],x[j])
            j += 1
        
            if current_class_prior * current_conditional_prob > max_posterior_prob:
                max_posterior_prob = current_class_prior * current_conditional_prob
                label = self.classes[c_index]
        return label
    
    def predict(self,X):
        if X.ndim == 1:
            return self._predict_single_sample(X)
        else:
            labels = []
            for i in range(X.shape[0]):
                label = self._predict_single_sample(X[i])
                labels.append(label)
            return labels
  1. 高斯贝叶斯分类器适用于连续特征的分类问题,连续属性的概率密度函数为:
    p\left(x_{i} | c\right)=\frac{1}{\sqrt{2 \pi} \sigma_{c, i}} \exp \left(-\frac{\left(x_{i}-\mu_{c, i}\right)^{2}}{2 \sigma_{c, i}^{2}}\right)
class GaussianNB(MultinomialNB):
    def _calculate_feature_prob(self,feature):
        mu = np.mean(feature)
        sigma = np.std(feature)
        return (mu,sigma)
    
    def _prob_gaussion(self,mu,sigma,x):
        return 1.0/(sigma*np.sqrt(2*np.pi)) * np.exp(-(x-mu)**2/(2*sigma**2))
    
    def _get_xj_prob(self,mu_sigma,target_value):
        return self._prob_gaussion(mu_sigma[0],mu_sigma[1],target_value)
  1. 主函数,数据生成及预测
if __name__ == "__main__":
    X = np.array([
                      [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3],
                      [4,5,5,4,4,4,5,5,6,6,6,5,5,6,6]
                              ])
    X = X.T
    y = np.array([-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1])
    
    #nb = MultinomialNB(alpha=1.0,fit_prior=True)
    nb = GaussianNB(alpha=1.0,fit_prior=True)
    nb.fit(X,y)
    print(nb.alpha)
    print(nb.class_prior)
    print(nb.classes)
    print(nb.conditional_prob)
    print(nb.predict(np.array([2,4])))
  1. 计算结果及参数如下:
1.0
[0.4117647058823529, 0.5882352941176471]
[-1  1]
{-1: {0: (1.6666666666666667, 0.7453559924999299), 1: (4.666666666666667, 0.7453559924999299)}, 
1: {0: (2.2222222222222223, 0.7856742013183862), 1: (5.333333333333333, 0.6666666666666666)}}
1

以下为sklearn包中朴素贝叶斯算法的实现。

from sklearn.naive_bayes import MultinomialNB
from sklearn import datasets
from sklearn import metrics

iris = datasets.load_iris()

mnb = MultinomialNB()
mnb.fit(iris.data,iris.target)

expected = iris.target
predicted = mnb.predict(iris.data)

print(metrics.classification_report(expected,predicted))
print(metrics.confusion_matrix(expected,predicted))

以下为分类结果及其混淆矩阵。

                precision    recall  f1-score   support

           0       1.00      1.00      1.00        50
           1       0.94      0.92      0.93        50
           2       0.92      0.94      0.93        50

   micro avg       0.95      0.95      0.95       150
   macro avg       0.95      0.95      0.95       150
weighted avg       0.95      0.95      0.95       150

[[50  0  0]
 [ 0 46  4]
 [ 0  3 47]]

三、问题探讨

判别模型与生成模型

判别模型:学习得到条件概率分布\mathrm{P}(\mathrm{y} | \mathrm{x}),即在特征x出现的情况下标记y出现的概率。
生成模型:学习得到联合概率分布P(\mathrm{x}, \mathrm{y}),即特征x和标记y共同出现的概率,然后求条件概率分布。

生成模型与判别模型

常见判别模型:k近邻法、感知机、决策树、逻辑回归、线性回归、最大熵模型、支持向量机(SVM)、提升方法、条件随机场(CRF)
常见生成模型:朴素贝叶斯、隐马尔可夫(em算法)、受限玻耳兹曼机(Restricted Boltzmann Machine,RBM)、自编码器(Autoencoder,AE)、深层信念网络(Deep Belief Network,DBN)、高斯混合模型(GMM)

参考资料

[1] https://github.com/yhangf/ML-NOTE
[2] 周志华 著. 机器学习. 北京:清华大学出版社,2016
[3] 李航 著. 统计学习方法. 北京:清华大学出版社,2012
[4] 史春奇等 著. 机器学习算法背后的理论与优化. 北京:清华大学出版社,2019
[5] Peter Harrington 著. 李锐等 译. 机器学习实战. 北京:人民邮电出版社,2013
[6] https://scikit-learn.org/stable/modules/naive_bayes.html

冷眼向洋看世界,热风吹雨洒江天。——毛泽东《七律·登庐山》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容