贝叶斯其人

  • 托马斯·贝叶斯(Thomas Bayes,1702-1761),18世纪英国神学家、数学家、数理统计学家和哲学家,概率论理论创始人,贝叶斯统计的创立者。
  • 他对统计推理的主要贡献是使用了 "逆概率" 这个概念,并把它作为一种普遍的推理方法提出来。
  • 贝叶斯定理原本是概率论中的一个定理,这一定理可用一个数学公式来表达,这个公式就是著名的贝叶斯公式。

贝叶斯定理的使用场景

  • 有甲、乙两条生产线,
  • 甲生产线的产品合格率为90%,乙生产线的产品合格率为95%,
  • 两条生产线的生产量占比分别为30%和70%,
  • 现在发现了一件不合格品,
  • 问题:这个不合格品是甲生产线生产出来的概率是多少?
症状 职业 疾病
发热 护士 感冒
发热 农民 过敏
头晕 建筑工人 脑震荡
头晕 建筑工人 感冒
发热 教师 感冒
头晕 教师 脑震荡
  • 某个医院早上收了六个病人,如上表,
  • 现在又来了第七个病人,是一个身上发热的建筑工人,
  • 问题:请问他患上感冒的概率有多大?
  • 对于SNS社区来说,不真实账号(使用虚假身份或用户的小号)是一个普遍存在的问题,作为SNS社区的运营商,希望可以检测出这些不真实账号,从而在一些运营分析报告中避免这些账号的干扰,亦可以加强对SNS社区的了解与监管。
  • 拼写纠正:当用户输入了一个不在字典中的单词,如何判断:“这个家伙到底真正想输入的单词是什么呢?”
  • 中文分词:机器学习的核心方法,如给定一个句子(字串):“南京市长江大桥”,如何对这个句子进行分词(词串)才是最靠谱的?
    • (1)南京市 / 长江大桥 ?
    • (2)南京市长 / 江大桥 ?
    • (3)南京 / 市长 / 江大桥 ?
  • 这三个分词,到底哪个更靠谱呢?
  • 邮件过滤器:问题:给定一封邮件,如何判定它是否属于垃圾邮件?
  • 反欺诈:如何在金融、保险、电信等多个领域,去除高危人群、身份假冒、账号异常、申请异常、设备异常、使用异常?

前导公式1:条件概率公式

  • Probability
    • 可能性; 或然性; 很可能发生的事; 概率; 几率; 或然率;
    • 使用 P 来表示概率的符号
  • 条件概率
    • 是指 事件A事件B 发生的条件下发生的概率,表示为:P(A|B)
    • P(B) 的意思是 “事件 B 的概率”
    • P(A|B) 的意思是 “在事件 B 发生的条件下,事件 A 发生的概率”
    • P(A|B) 也叫在 B 发生的情况下 A 发生的 “条件概率”
  • 事件A与事件B的概率 = 事件B的概率 $\times$ 在事件B发生的条件下事件A发生的概率 $$P(AB) = P(B)\times P(A|B)$$
  • 或 $$P(AB) = P(A)\times P(B|A)$$
  • 移项,得: $$P(A|B) = \frac{P(AB)}{P(B)}= \frac{P(A)\times P(B|A)}{P(B)}= P(A)\times \frac{P(B|A)}{P(B)}$$

前导公式2:全概率公式

完备事件组(划分) 的定义:
设S为试验E的样本空间,B1,B2,…,Bn为E的一组事件。若
(i) Bi ∩ Bj = ∅ (i≠j且i、j=1,2,…,n);
(ii) B1∪B2∪…∪Bn = S,
则称B1,B2,…,Bn为样本空间S的一个 完备事件组(划分)
注:定义为充要条件,所以定义反过来说也成立

  • 如果A和A'构成样本空间的一个划分,那么事件B的概率,就等于A和A'的概率分别乘以B对这两个事件的条件概率之和。 $$P(B)=P(B|A)P(A) + P(B|A')P(A')$$
  • 将全概率公式代入条件概率: $$P(A|B) = P(A)\times \frac{P(B|A)}{P(B|A)P(A) + P(B|A')P(A')}$$
  • 即得到了贝叶斯公式

贝叶斯公式

贝叶斯推断的逻辑

$$P(A|B) = P(A)\times \frac{P(B|A)}{P(B|A)P(A) + P(B|A')P(A')}$$
  • $P(A)$
    • 称为“先验概率”(Prior probability)
    • 即在B事件发生之前,我们对A事件概率的一个判断。
  • $P(A|B)$
    • 称为“后验概率”(Posterior probability)
    • 即在B事件发生之后,我们对A事件概率的重新评估。
  • $\frac{P(B|A)}{P(B|A)P(A) + P(B|A')P(A')}$
    • 称为 “可能性函数”(Likelyhood)
    • 这是一个调整因子,使得预估概率更接近真实概率。
  • 条件概率可以理解成下面的式子:
    • 后验概率 = 先验概率 x 调整因子
  • 这就是贝叶斯推断的逻辑
    • 我们先预估一个“先验概率”,然后加入实验结果,看这个实验到底是增强还是削弱了“先验概率”,由此得到更接近事实的“后验概率”。

贝叶斯与朴素贝叶斯

  • $NaiveBayes$
  • “朴素” 的意思是 条件独立。引入朴素贝叶斯的目的是为了降低计算量
  • 条件独立的含义
    • 每个事件受其他事件影响
    • 举例:每一次抛硬币都是绝对独立的。过去的抛掷对本次抛掷是完全没有影响的。
    • 反例:相关事件:布袋里有2颗蓝色球和3颗红色球。随机拿一颗(不放回布袋中)之后,再拿第二颗,拿到蓝色球的概率是多少?此时第二次与第一次是有关联的。

贝叶斯定理的Python实现

  • 首先查看数据集
In [52]:
df = pd.read_csv('naivebayes_data.csv')
df
Out[52]:
x1 x2 Y
0 1 S -1
1 1 M -1
2 1 M 1
3 1 S 1
4 1 S -1
5 2 S -1
6 2 M -1
7 2 M 1
8 2 L 1
9 2 L 1
10 3 L 1
11 3 M 1
12 3 M 1
13 3 L 1
14 3 L -1

朴素贝叶斯算法 极大似然估计

  • 极大似然估计,是统计推断的一部分内容,主要目的为通过有限的样本来估计整体的分布情况。
In [53]:
import pandas as pd
import numpy as np

class NaiveBayes(object):
    def getTrainSet(self):
        dataSet = pd.read_csv('naivebayes_data.csv')
        dataSetNP = np.array(dataSet)
        trainData = dataSetNP[:,0:dataSetNP.shape[1]-1]
        labels = dataSetNP[:,dataSetNP.shape[1]-1]
        return trainData, labels
    def classify(self, trainData, labels, features):
        labels = list(labels)
        P_y = {}
        for label in labels:
            P_y[label] = labels.count(label)/float(len(labels))
        P_xy = {}
        for y in P_y.keys():
            y_index = [i for i, label in enumerate(labels) if label == y]
            for j in range(len(features)):
                x_index = [i for i, feature in enumerate(trainData[:,j]) if feature == features[j]]
                xy_count = len(set(x_index) & set(y_index))
                pkey = str(features[j]) + '*' + str(y)
                P_xy[pkey] = xy_count / float(len(labels))
        P = {}
        for y in P_y.keys():
            for x in features:
                pkey = str(x) + '|' + str(y)
                P[pkey] = P_xy[str(x)+'*'+str(y)] / float(P_y[y])
        F = {}
        for y in P_y:
            F[y] = P_y[y]
            for x in features:
                F[y] = F[y]*P[str(x)+'|'+str(y)]
        features_label = max(F, key=F.get)
        return features_label
In [54]:
nb = NaiveBayes()
# 训练数据
trainData, labels = nb.getTrainSet()
# x1,x2
features = [2,'S']
# 该特征应属于哪一类
result = nb.classify(trainData, labels, features)
print(features,'属于',result)
[2, 'S'] 属于 -1

朴素贝叶斯算法 贝叶斯估计 拉普拉斯平滑

  • 由于训练量不足,会令分类器质量大大降低,从而引入拉普拉斯平滑
  • 对每个类别下所有划分的计数加1,这样如果训练样本集数量充分大时,并不会对结果产生影响
  • λ=1
  • K=2(种类的数量)
  • S=3(特征的个数)
In [55]:
import pandas as pd
import numpy as np

class NavieBayesB(object):
    def __init__(self):
        self.A = 1
        self.K = 2
        self.S = 3
    def getTrainSet(self):
        trainSet = pd.read_csv('naivebayes_data.csv')
        trainSetNP = np.array(trainSet)
        trainData = trainSetNP[:,0:trainSetNP.shape[1]-1]
        labels = trainSetNP[:,trainSetNP.shape[1]-1]
        return trainData, labels
    def classify(self, trainData, labels, features):
        labels = list(labels)
        P_y = {}
        for label in labels:
            P_y[label] = (labels.count(label) + self.A) / float(len(labels) + self.K*self.A)
        P = {}
        for y in P_y.keys():
            y_index = [i for i, label in enumerate(labels) if label == y]
            y_count = labels.count(y)
            for j in range(len(features)):
                pkey = str(features[j]) + '|' + str(y)
                x_index = [i for i, x in enumerate(trainData[:,j]) if x == features[j]]
                xy_count = len(set(x_index) & set(y_index))
                P[pkey] = (xy_count + self.A) / float(y_count + self.S*self.A)
        F = {}
        for y in P_y.keys():
            F[y] = P_y[y]
            for x in features:
                F[y] = F[y] * P[str(x)+'|'+str(y)]
        features_y = max(F, key=F.get)
        return features_y
In [56]:
nb = NavieBayesB()
# 训练数据
trainData, labels = nb.getTrainSet()
# x1,x2
features = [2,'S']
# 该特征应属于哪一类
result = nb.classify(trainData, labels, features)
print(features,'属于',result)
[2, 'S'] 属于 -1

爱与彼岸财经分析团队编制

爱与彼岸财经分析