【统计学习方法】朴素贝叶斯算法

1 基本概念

1.1 先验概率(prior probability)

是指根据以往经验和分析得到的概率,如全概率公式,它往往作为"由因求果"问题中的"因"出现的概率。---一般统计得到

1.2 条件概率

条件概率是指事件A在另外一个事件B已经发生条件下的发生概率。条件概率表示为:P(A|B),读作“在B的条件下A的概率”。

条件概率计算公式:P(AB)=P(A)P(B|A)=P(B)P(A|B)

详细:https://www.jianshu.com/p/c59851b1c0f3

1.3 后验概率(观察到事件A发生之后,事件B发生的概率)

后验概率是指,某事件 X=x 已经发生,那么该事件是因为事件 Y=y 的而发生的概率。后验概率指的是将观测值分配到已给定数据的组的概率。先验概率指的是在您收集数据之前数据已划入某个组的概率。

后验概率的计算要以先验概率为基础。后验概率可以根据通过贝叶斯公式,用先验概率和似然函数计算出来

知乎:如何理解先验概率与后验概率

1.4 全概率公式

formula

公式表示若事件A1,A2,…,An构成一个完备事件组且都有正概率,则对任意一个事件B都有公式成立。

1.5 贝叶斯公式

由条件概率公式推导:P(A|B) = \frac{P(A)P(B|A)}{P(B)}

结合全概率公式:P(A{_i}|B) = \frac{P(A{_i})P(B|A{_i})}{\sum P(A{_j})P(B|A{_j})} =\frac{P(A{_i})P(B|A{_i})}{P(B)}

公式中,事件A{_i}的概率为P(A{_i}),事件B已发生条件下事件A{_i}的概率为P({A{_i}|B}),事件A{_i}已发生条件下事件B的概率为P(B|A{_i})

1.6 贝叶斯公式的意义

后验概率 = 先验概率 x 调整因子

这就是贝叶斯推断的含义。我们先预估一个"先验概率",然后加入实验结果,看这个实验到底是增强还是削弱了"先验概率",由此得到更接近事实的"后验概率"。

 

2 朴素贝叶斯算法

朴素贝叶斯(Naive Bayes)是一个基于贝叶斯理论的分类器。它会单独考量每一唯独特征被分类的条件概率,进而综合这些概率并对其所在的特征向量做出分类预测。
因此,朴素贝叶斯的基本数据假设是:各个维度上的特征被分类的条件概率之间是相互独立的。它经常被应用在文本分类中,包括互联网新闻的分类,垃圾邮件的筛选。

2.1 公式基础和解释

c{_k}代表列表,x代表特征,是n维的向量,则条件概率——特征为x条件下,属于y类别的概率:

P(Y=c{_k} | X=x) = \frac{P(X=x|Y = c{_k})P(Y=c{_k})}{\sum P(X=x|Y=c{_k})P(Y=c{_k})} = \frac{P(X=x|Y = c{_k})P(Y=c{_k})}{P(X=x)}

我们不能直接得到P(Y=c{_k} | X=x),但是通过训练数据集可以得到:

  • P(X=x|Y = c{_k}),通过预先分好类的训练数据集,计算每个特征的概率分布(预先知道分布模型,常见的如高斯模型,多项式模型,伯努利模型)。
  • P(Y=c{_k}),通过预先分好类的训练数据集,计算每个类别的占比

对于不同的分类分母是一样的{P(X=x),所以我们只需知道P(X=x|Y = c{_k})P(Y=c{_k}),概率值最大的分类作为预测分类。

2.2 高斯模型

2.2.1 基本概念

高斯朴素贝叶斯模型是假设条件概率P(X=x|Y=C{_k})是多元高斯分布,另一方面,由之前的特征的条件独立性假设,我们就可以通过对每个特征的条件概率建模,每个特征的条件概率N(\mu ,\sigma ^{2})也服从高斯分布.

高斯分布函数:\LARGE P(x|\mu,\sigma ) = \frac{1}{\sqrt{2\pi }\sigma}e^{\frac{(x-\mu)^{2}}{2\sigma^{2}}}

 

特征向量某一维特征的高斯分布函数:\LARGE P(x{_i}|\mu{_i},\sigma{_i} ) = \frac{1}{\sqrt{2\pi }\sigma{_i}}e^{\frac{(x-\mu{_i})^{2}}{2\sigma{_i}^{2}}}

 

属于某一分类\LARGE c{_k}的条件概率分布函数:\LARGE P(x{_i}|\mu{_i},\sigma{_i},c{_k} ) = \frac{1}{\sqrt{2\pi }\sigma{_i}}e^{\frac{(x-\mu{_i})^{2}}{2\sigma{_i}^{2}}}(每一种分类的每一种特征都有自己的分布参数,公式编辑器无法打出来)

分布函数的参数我们都可以通过训练数据集统计出来。

根据贝叶斯公式:P(c{_k} |\mu{_i},\sigma{_i},x) = \frac{P(c{_k})P(x{_i}|\mu{_i},\sigma{_i},c{_k} ) )}{P(x|\mu,\sigma)}

所以对于高斯模型贝叶斯,所谓的训练就是统计各个分类的每个特征的分布函数参数\mu,\sigma,得到参数后,可以将特征向量代入,求得各个分类的似然估计,估计值最大的作为预测分类(最大似然估计)。

2.2.2 代码实现(代码来源https://www.jianshu.com/p/807aa6e828a9

# Example of Naive Bayes implemented from Scratch in Python
import csv
import random
import math


def loadCsv(filename):
    lines = csv.reader(open(filename, "rt", encoding="UTF-8-sig"))
    dataset = list(lines)
    for i in range(len(dataset)):
        dataset[i] = [float(x) for x in dataset[i]]
    return dataset


def splitDataset(dataset, splitRatio):
    trainSize = int(len(dataset) * splitRatio)
    trainSet = []
    copy = list(dataset)
    while len(trainSet) < trainSize:
        index = random.randrange(len(copy))
        trainSet.append(copy.pop(index))
    return [trainSet, copy]

#基于类别分开数据
def separateByClass(dataset):
    separated = {}
    for i in range(len(dataset)):
        vector = dataset[i]
        #.eg:6,148,72,35,0,33.6,0.627,50,1
        #最后一个元素指示是否患病
        if (vector[-1] not in separated):
            separated[vector[-1]] = []
        separated[vector[-1]].append(vector)
    return separated


def mean(numbers):
    return sum(numbers) / float(len(numbers))


def stdev(numbers):
    avg = mean(numbers)
    variance = sum([pow(x - avg, 2) for x in numbers]) / float(len(numbers) - 1)
    return math.sqrt(variance)

# 函数将每一个属性的平均值和标准差组合起来了
def summarize(dataset):
    # zip 函数将每一个属性的平均值和标准差组合起来了
    # 与 zip 相反,可理解为解压,为zip的逆过程,可用于矩阵的转置  --- >>> 转置
    # for attribute in zip(*dataset):
    #     print(attribute)
    # 每一行代表一个属性,有几个属性就有几行
    # 计算均值和标注差
    summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)]
    del summaries[-1]
    return summaries


def summarizeByClass(dataset):
    # 先将同一个类别的数据放在一起。然后计算每一个属性的摘要
    separated = separateByClass(dataset)
    summaries = {}

    # 分类别类别(是否得病)计算均值和标准差
    for classValue, instances in separated.items():
        # 计算平均值和标准差(均值,标准差),每一个属性都有
        summaries[classValue] = summarize(instances)
    return summaries

# 据摘要中我们已经知道了高斯分布的平均值和方差,而且知道了某一个属性值属于某一个类别的似然
def calculateProbability(x, mean, stdev):
    exponent = math.exp(-(math.pow(x - mean, 2) / (2 * math.pow(stdev, 2))))
    return (1 / (math.sqrt(2 * math.pi) * stdev)) * exponent

# 计算某一个属性的值属于每一个类别的概率了
# summaries = {0:[(1, 0.5)], 1:[(20, 5.0)]}
# inputVector = [1.1, '?']
def calculateClassProbabilities(summaries, inputVector):
    probabilities = {}
    for classValue, classSummaries in summaries.items():
        probabilities[classValue] = 1
        # classSummaries 包含所有属性的均值和标准差
        for i in range(len(classSummaries)):
            mean, stdev = classSummaries[i]
            x = inputVector[i]
            # 给定数据的概率通过连乘所有的属性概率得到,结果是一个词典包含了属性值和对应的概率。
            # ---->计算所有类别的联合概率
            probabilities[classValue] *= calculateProbability(x, mean, stdev)
    return probabilities


def predict(summaries, inputVector):
    #计算每个类别的概率
    probabilities = calculateClassProbabilities(summaries, inputVector)
    bestLabel, bestProb = None, -1
    #找出概率最大的标签
    for classValue, probability in probabilities.items():
        if bestLabel is None or probability > bestProb:
            bestProb = probability
            bestLabel = classValue
    return bestLabel


def getPredictions(summaries, testSet):
    predictions = []
    for i in range(len(testSet)):
        result = predict(summaries, testSet[i])
        predictions.append(result)
    return predictions


def getAccuracy(testSet, predictions):
    correct = 0
    for i in range(len(testSet)):
        if testSet[i][-1] == predictions[i]:
            correct += 1
    return (correct / float(len(testSet))) * 100.0


def main():
    filename = 'pima-indians-diabetes.data.csv'
    splitRatio = 0.67
    dataset = loadCsv(filename)
    trainingSet, testSet = splitDataset(dataset, splitRatio)


    print("Split {0} rows into train={1} and test={2} rows".format(len(dataset), len(trainingSet), len(testSet)))
    # prepare model
    # 计算每个属性的均值和标准差
    summaries = summarizeByClass(trainingSet)
    # test model
    predictions = getPredictions(summaries, testSet)
    accuracy = getAccuracy(testSet, predictions)
    print("Accuracy: {0}%".format(accuracy))


main()

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值