全概率公式、贝叶斯公式

条件概率定义:

AB是样本空间\Omega中的两事件,若P(B)>0,则称
P(A|B)=\frac{P(AB)}{P(B)}\\
为“在B发生下A的条件概率”,简称条件概率。

条件概率特有的三个公式:

  1. 乘法公式:
    P(B)>0,则P(AB)=P(A)P(A|B).
    P\left(A_1 \cdots A_{n-1}\right)>0,则P\left(A_1 \cdots A_n\right)=P\left(A_1\right) P\left(A_2 \mid A_1\right) P\left(A_3 \mid A_2 A_1\right) \cdots P\left(A_n \mid A 1 \cdots A_{n-1}\right)
  2. 全概率公式:
    B_1,B_2,\dots,B_n为样本空间\Omega的一个分割,即B_1,B_2,\dots,B_n互不相容,且\bigcup_{i=1}^n B_i=\Omega,如果P(B_i)>0,i=1,2,\dots,n,则对任一事件A有:P(A)=\sum_{i=1}^n P\left(B_i\right) P\left(A \mid B_i\right)\\
    样本空间$\Omega$.png

    全概率公式的意义:事件A的发生有各种原因,所以A发生的概率即为全部引起A发生的概率的总和
  3. 贝叶斯公式:
    在乘法公式和全概率公式的基础上即可得到著名的贝叶斯公式。设B_1,B_2,\dots,B_n为样本空间\Omega的一个分割,即B_1,B_2,\dots,B_n互不相容,且\bigcup_{i=1}^n B_i=\Omega,如果P(A)>0,P(B_i)>0,i=1,2,\dots,n,P\left(B_i \mid A\right)=\frac{P\left(B_i\right) P\left(A \mid B_i\right)}{\sum_{j=1}^n P\left(B_j\right) P\left(A \mid B_j\right)}, i=1,2, \cdots, n\\

机器学习中的贝叶斯

其中X,y对应于特征和所属类别,给定样本的特征,判断其所属类别,可以通过该公式转换为计算等式右边。
P(y|X)=\frac{P(X|y)P(y)}{P(X)}\\
机器学习中的朴素贝叶斯算法,则假设样本的特征之间相互独立,那么上式可以转换为:
P(y|X)=\frac{P(x_1|y)P(x_2|y)...P(x_n|y)P(y)}{P(x_1)P(x_2)...P(x_n)}\\
由于判断样本所属类别只需要比较属于不同类别概率的大小即可,而上式的分母只跟样本的特征相关而跟所属类别无关,所以实际应用中只需要计算分子的大小,即可判断出样本所属类别。

计算一下:

某个医院早上来了六个门诊的病人,他们的情况如下表所示:

image.png

现在又来了第七个病人,是一个打喷嚏的建筑工人。请问他患上感冒的概率有多大?
根据贝叶斯定理:P(感冒|(打喷嚏,建筑工人))=\frac{P((打喷嚏,建筑工人)|感冒)*P(感冒)}{P((打喷嚏,打喷嚏))}\\
根据朴素贝叶斯条件独立性的假设可知,"打喷嚏"和"建筑工人"这两个特征是独立的,因此,上面的等式就变成了
P(感冒|(打喷嚏,建筑工人))=\frac{P(打喷嚏|感冒)*P(建筑工人|感冒)*P(感冒)}{P(打喷嚏)P(建筑工人)}\\
代入计算得到:P(感冒|(打喷嚏,建筑工人))=\frac{0.66*0.33*0.5}{0.5*0.33}=0.66

实战:朴素贝叶斯之言论过滤器。

import numpy as np
from functools import reduce

# 构造样本
def loadDataSet():
    postingList = [
        ["my", "dog", "has", "flea", "problems", "help", "please"],  # 切分的词条
        ["maybe", "not", "take", "him", "to", "dog", "park", "stupid"],
        ["my", "dalmation", "is", "so", "cute", "I", "love", "him"],
        ["stop", "posting", "stupid", "worthless", "garbage"],
        ["mr", "licks", "ate", "my", "steak", "how", "to", "stop", "him"],
        ["quit", "buying", "worthless", "dog", "food", "stupid"],
    ]
    classVec = [0, 1, 0, 1, 0, 1]  # 类别标签向量,1代表侮辱性词汇,0代表不是
    return postingList, classVec

# 将样本转换为词条向量
def setOfWords2Vec(vocabList, inputSet):
    returnVec = [0] * len(vocabList)  # 创建一个其中所含元素都为0的向量
    for word in inputSet:  # 遍历每个词条
        if word in vocabList:  # 如果词条存在于词汇表中,则置1
            returnVec[vocabList.index(word)] = 1
        else:
            print("the word: %s is not in my Vocabulary!" % word)
    return returnVec

# 构造词典
def createVocabList(dataSet):
    vocabSet = set([])  # 创建一个空的不重复列表
    for document in dataSet:
        vocabSet = vocabSet | set(document)  # 取并集
    return list(vocabSet)


def trainNB0(trainMatrix, trainCategory):
    """
    贝叶斯条件概率公式:P(y|X)=P(X|y)P(y)/P(X),朴素假设特征之间相互独立
    待计算的是P(侮辱|stupid,dog,my,has,...) = (P(stupid,dog,my,has,...|侮辱)*P(侮辱文档数|总文档数)/P(stupid,dog,my,has,...))
    统计了侮辱和非侮辱文档中各自词汇出现的条件概率。比如P(stupid|侮辱文档数),P(dog|侮辱文档数),P(my|非侮辱文档数),P(has|非侮辱文档数)。
    以及先验概率P(侮辱文档数|总文档数)。
    """
    numTrainDocs = len(trainMatrix)  # 计算训练的文档数目
    numWords = len(trainMatrix[0])  # 计算每篇文档的词条数
    pAbusive = sum(trainCategory) / float(numTrainDocs)  # 文档属于侮辱类的概率
    p0Num = np.zeros(numWords)
    p1Num = np.zeros(numWords)  # 创建numpy.zeros数组,词条出现数初始化为0
    p0Denom = 0.0
    p1Denom = 0.0  # 分母初始化为0
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:  # 统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:  # 统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = p1Num / p1Denom
    p0Vect = p0Num / p0Denom
    return p0Vect, p1Vect, pAbusive  # 返回属于侮辱类的条件概率数组,属于非侮辱类的条件概率数组,文档属于侮辱类的概率


def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    """
    贝叶斯条件概率公式:P(y|X)=P(X|y)P(y)/P(X)。
    朴素贝叶斯假设特征之间相互独立,此时上述公式变为:P(y|X)=P(x1|y)P(x2|y)...P(xn|y)P(y)/P(x1)P(x2)...P(xn)。
    可以发现等式右边的分母P(x1)P(x2)...P(xn)只跟特征有关系,跟类别没有关系,也就是说比较不同类别之间的条件概率大小时,
    由于分母相等,直接比较分子之间的大小关系即可。所以下面的实际计算过程中也只计算了分子。
    """
    p1 = reduce(lambda x, y: x * y, vec2Classify * p1Vec) * pClass1  # 对应元素相乘
    p0 = reduce(lambda x, y: x * y, vec2Classify * p0Vec) * (1.0 - pClass1)
    print("p0:", p0)
    print("p1:", p1)
    if p1 > p0:
        return 1
    else:
        return 0


def testingNB():
    listOPosts, listClasses = loadDataSet()  # 创建实验样本
    myVocabList = createVocabList(listOPosts)  # 创建词汇表
    trainMat = []
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))  # 将实验样本向量化
    p0V, p1V, pAb = trainNB0(np.array(trainMat), np.array(listClasses))  # 训练朴素贝叶斯分类器
    testEntry = ["love", "my", "dalmation"]  # 测试样本1
    thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))  # 测试样本向量化
    if classifyNB(thisDoc, p0V, p1V, pAb):
        print(testEntry, "属于侮辱类")  # 执行分类并打印分类结果
    else:
        print(testEntry, "属于非侮辱类")  # 执行分类并打印分类结果
    testEntry = ["stupid", "garbage"]  # 测试样本2

    thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))  # 测试样本向量化
    if classifyNB(thisDoc, p0V, p1V, pAb):
        print(testEntry, "属于侮辱类")  # 执行分类并打印分类结果
    else:
        print(testEntry, "属于非侮辱类")

if __name__ == "__main__":
    testingNB()

执行结果

发现第二个样本明显包含了侮辱性的词汇,却误判为非侮辱类。


实验结果

这是由于在代入样本的词条向量和训练集中得到的词条概率计算乘积时,只要有一个为0,就会导致结果为0。比如my没有出现在样本2中,计算分子乘积时就会导致结果为0。

解决办法:朴素贝叶斯改进之拉普拉斯平滑

可以将所有词的出现数初始化为1而不是0,并将分母初始化为2。这种做法就叫做拉普拉斯平滑(Laplace Smoothing)又被称为加1平滑,是比较常用的平滑方法,它就是为了解决0概率问题。
详细参考

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

推荐阅读更多精彩内容