python机器学习——贝叶斯方法

#贝叶斯公式
百度百科
贝叶斯定理由英国数学家贝叶斯 ( Thomas Bayes 1702-1761 ) 发展,用来描述两个条件概率之间的关系,比如 P(A|B) 和 P(B|A)。按照乘法法则,可以立刻导出:P(A∩B) = P(A)*P(B|A)=P(B)*P(A|B)。如上公式也可变形为:P(B|A) = P(A|B)*P(B) / P(A)。

贝叶斯法则是关于随机事件A和B的条件概率和边缘概率的。
这里写图片描述
其中P(A|B)是在B发生的情况下A发生的可能性。 为完备事件组,即 这里写图片描述
在贝叶斯法则中,每个名词都有约定俗成的名称:
Pr(A)是A的先验概率或边缘概率。之所以称为"先验"是因为它不考虑任何B方面的因素。
Pr(A|B)是已知B发生后A的条件概率,也由于得自B的取值而被称作A的后验概率。
Pr(B|A)是已知A发生后B的条件概率,也由于得自A的取值而被称作B的后验概率。
Pr(B)是B的先验概率或边缘概率,也作标准化常量(normalized constant)。
按这些术语,Bayes法则可表述为:
后验概率 = (似然度 * 先验概率)/标准化常量 也就是说,后验概率与先验概率和似然度的乘积成正比。
另外,比例Pr(B|A)/Pr(B)也有时被称作标准似然度(standardised likelihood),Bayes法则可表述为:
后验概率 = 标准似然度 * 先验概率。

用机器学习视角理解
在机器学习的视角下,我们把A理解成“具有某特征”,把B理解成“类别标签”
这里写图片描述
贝叶斯方法把计算“具有某特征的条件下属于某类”的概率转换成需要的计算“属于某类条件下具有某特征”的概率,属于有监督学习。

朴素贝叶斯:
加上条件独立假设的贝叶斯方法就是朴素贝叶斯方法。
由于乘法交换律,朴素贝叶斯方法中算出来交换词语顺序的条件概率完全一样。
朴素贝叶斯简单高效:
“有些独立假设在各个分类之间的分布都是均匀的,所以对于似然的相对大小不产生影响;即便不是如此,也有很大的可能性各个独立假设所产生的消极影响或积极影响互相抵消,最终导致结果受到影响不大。”

#朴素贝叶斯的三种模型

  1. 多项式模型: 重复的词语我们视为其出现多次。统计与判断时,都关注重复次数。
  2. 伯努利模型:将重复的词语都视为其只出现1次。这种方式更加简化与方便。当然它丢失了词频的信息,因此效果可能会差一些。
  3. 混合模型:在计算句子概率时,不考虑重复词语出现的次数,但是在统计计算词语的概率P(“词语”|S)时,却考虑重复词语的出现次数。

这里写图片描述

朴素贝叶斯方法优点:

  1. 对待预测样本进行预测,过程简单速度快。
  2. 对于多分类问题也同样很有效,复杂度也不会有大程度上升。
  3. 在分布独立这个假设成立的情况下,贝叶斯分类器效果奇好,会略胜于逻辑回归,同时我们需要的样本量也更少一点。
  4. 对于类别类的输入特征变量,效果非常好。对于数值型变量特征,我们是默认它符合正态分布的。

朴素贝叶斯方法缺点:

  1. 对于测试集中的一个类别变量特征,如果在训练集里没见过,直接算的话概率就是0了,预测功能就失效了。当然,平滑可以缓解这个问题,最常见的平滑技术就是拉普拉斯估测。
  2. 朴素贝叶斯中有分布独立的假设前提,而现实生活中这些predictor很难是完全独立的。

朴素贝叶斯方法常见应用场景:

  1. 文本分类/垃圾文本过滤/情感判别
  2. 多分类实时预测
  3. 推荐系统

朴素贝叶斯注意点:

  1. 连续数值型的特征不一定服从正态分布,一定要想办法把它们变换调整成满足正态分布。
  2. 对测试数据中的0频次项,一定要记得平滑。
  3. 朴素贝叶斯分类器一般可调参数比较少,比如scikit-learn中的朴素贝叶斯只有拉帕拉斯平滑因子alpha,类别先验概率class_prior和预算数据类别先验fit_prior。集中精力进行数据的预处理,及特征选择。

#贝叶斯网络
把某个研究系统中涉及的随机变量,根据是否条件独立绘制在一个有向图中,就形成了贝叶斯网络。
贝叶斯网络(Bayesian Network),又称有向无环图模型(directed acyclic graphical model),是一种概率图模型,借由有向无环图(Directed Acyclic Graphs, DAG)中得知一组随机变量{X1,X2…Xn}及其n组条件概率分布(Conditional Probability Distributions, CPD)的性质。
一般而言,贝叶斯网络的有向无环图中的节点表示随机变量,它们可以是可观察到的变量,或隐变量、未知参数等。连接两个节点的箭头代表此两个随机变量是具有因果关系(或非条件独立)。若两个节点间以一个单箭头连接在一起,表示其中一个节点是“因(parents)”,另一个是“果(children)”,两节点就会产生一个条件概率值。
每个结点在给定其直接前驱时,条件独立于其非后继。

一个简单的贝叶斯网络
这里写图片描述
这里写图片描述

模拟实现朴素贝叶斯:

nb_tools.py

# -*- coding: utf-8 -*-

import numpy as np
import scipy.stats


class NaiveBayes(object):
    """
        Naive Bayes 类
    """
    def __init__(self, n_feat):
        self.n_feat = n_feat    # 样本的特征维度

    def get_cls_stats(self, X_train, y_train):
        """
            返回训练集中每个类的统计参数
        """
        # 获取类别
        unique_cls_list = list(set(y_train.tolist()))

        # 构造字典
        dataset_stats = {}
        for cls in unique_cls_list:
            # 获取属于该类的样本
            samples_in_cls = X_train[y_train == cls]

            # 获取该类样本中每个特征的统计参数
            samples_in_cls_stats = self.get_samples_stats(samples_in_cls)
            dataset_stats[cls] = samples_in_cls_stats

        return dataset_stats

    def get_samples_stats(self, samples):
        """
            返回一组样本中每个特征(属性)的统计参数
        """
        # 每个特征维度上计算统计参数,即均值和标准差
        samples_stats = [(np.mean(samples[:, i]), np.std(samples[:, i]))
                         for i in range(self.n_feat)]
        return samples_stats

    def predict(self, tr_cls_stats, X_test):
        """
            根据训练样本统计参数预测整个测试样本集
        """
        y_pred = []
        n_sample = X_test.shape[0]  # 测试样本的个数
        for i in range(n_sample):
            # 遍历每个测试样本
            sample = X_test[i, :]
            pred = self.predict_sample(tr_cls_stats, sample)
            y_pred.append(pred)

        return y_pred

    def predict_sample(self, tr_cls_stats, sample):
        """
            根据训练样本统计参数预测单一样本
        """
        cls_probs = self.cal_cls_probs(tr_cls_stats, sample)

        # 初始化
        best_label = None
        best_prob = -1

        for cls, cls_prob in cls_probs.items():
            if best_label is None or cls_prob > best_prob:
                best_prob = cls_prob
                best_label = cls

        return best_label

    def cal_cls_probs(self, tr_cls_stats, sample):
        """
            根据高斯分布及训练集的统计参数返回样本分类的概率
        """
        probs = {}
        for cls, cls_stats in tr_cls_stats.items():
            # 初始化属于cls类的概率
            probs[cls] = 1
            for i in range(len(cls_stats)):
                # 遍历cls类中每个特征维度上的统计参数
                mean, std = cls_stats[i]
                single_feat_vec = sample[i]

                # 根据高斯分布的概率密度函数及每个特征维度上的统计参数求联合该概率
                probs[cls] *= scipy.stats.norm.pdf(single_feat_vec, mean, std)

        return probs


def cal_acc(true_labels, pred_labels):
    """
        计算准确率
    """
    n_total = len(true_labels)
    correct_list = [true_labels[i] == pred_labels[i] for i in range(n_total)]

    acc = sum(correct_list) / n_total
    return acc

main.py

# -*- coding: utf-8 -*-


from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from nb_tools import NaiveBayes, cal_acc


def run_main():
    """
        主函数
    """
    n_feat = 100    # 特征个数
    X, y = make_classification(
        n_samples=400,
        n_features=n_feat,
        n_classes=2,
        random_state=5)

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,
                                                        random_state=17)

    nb_model = NaiveBayes(n_feat)

    # 样本特征为连续值,假设其符合高斯分布,则需要求出每个特征的均值和标准差
    # 这里称为统计参数 stats

    # 获取训练集中每个类别的统计参数
    tr_cls_stats = nb_model.get_cls_stats(X_train, y_train)
    for cls, samples_stats in tr_cls_stats.items():
        print('类{}的统计参数:'.format(cls))
        for i, feat_stats in enumerate(samples_stats):
            # 查看每个特征的统计参数
            print('第{}个特征的统计参数{}'.format(i, feat_stats))

    # 根据训练样本的统计参数进行预测
    y_pred = nb_model.predict(tr_cls_stats, X_test)

    # 准确率
    print('准确率:{}'.format(cal_acc(y_test, y_pred)))


if __name__ == '__main__':
    run_main()


运行结果:
在这里插入图片描述

  • 6
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐亦亦乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值