机器学习(二):贝叶斯

贝叶斯

一、引言

南京大学周志华在《机器学习》中介绍:贝叶斯决策论机器学习模式识别等诸多关注数据分析的领域都有极为重要的地位。

根据在属性间依赖的涉及程度,贝叶斯分类器形成了一个“谱”:朴素贝叶斯分类器不考虑属性间的依赖性,贝叶斯网络能表示任意属性间的依赖性,二者分别位于“谱”的两端。介于两者之间的则是一系列半朴素贝叶斯分类器,它们基于各种假设和约束来对属性间的部分依赖性进行建模。

贝叶斯分类器与一般意义上的“贝叶斯学习”有显著区别,前者是根据最大后验概率进行单点估计,后者则是进行分布估计。

二、朴素贝叶斯

朴素贝叶斯算法曾入选“数据挖掘十大算法”。

文氏图可得贝叶斯公式

P(B|A)=\frac{P(A|B)}{P(A))}

贝叶斯公式又被称为贝叶斯定理、贝叶斯规则。由英国数学家贝叶斯(Thomas Bayes 1702-1761)发展,用来描述两个条件概率之间的关系,比如 P(A|B) P(B|A)

那就是朴素贝叶斯分类器,它根据MAP(最大后验假设)划分每个样本的类别,全部PPT(需要登录百度账号)。

 计算样本属于每个类的后验概率,最大的即为样本的类别。

举例

三、贝叶斯网络

 三种基本结构出自数据挖掘算法之贝叶斯网络

 

其他PPT:小样本类人概念学习-贝叶斯学习 

贝叶斯网络学习分为结构学习参数学习,分别用于确定网络的拓扑结构和各个网络结点的条件概率分布

结构学习算法分为基于约束的结构学习算法与基于得分的结构学习算法。参照李弘毅的21-24讲。

基于约束的结构学习算法将贝叶斯网络看成反应随机变量之间独立性关系的图形化结构。该方法先对训练数据集进行独立性检验,明确各结点集之间的一致条件独立性。然后构建尽可能多地覆盖这些条件独立性的网络结构。

基于得分的结构学习算法先根据评分标准评判网络结构与数据集拟合的程度,再搜索评分标准下得分最高的网络结构。常用的评分函数包括 BDe 评分函数和 MDL 评分函数。常见的搜索算法包括 K2 算法,爬山算法等。

参数学习是指在确定网络结构后获得每个结点的条件概率分布,主要通过样本统计来实现。常用的方法有最大似然估计法和贝叶斯参数估计、EM(期望最大化)算法和 Gibbs 抽样算法。

贝叶斯网络参数学习算法主要是根据网络结构G 和数据集 D ,确定各网络结点条件概率分布。常见的参数学习算法有最大似然估计法和贝叶斯估计法。

举例(出自概率图模型之:贝叶斯网络)

一个学生拥有成绩、课程难度、智力、SAT得分、推荐信等变量。通过一张有向无环图可以把这些变量的关系表示出来,可以想象成绩由课程难度和智力决定,SAT成绩由智力决定,而推荐信由成绩决定。该模型对应的概率图如下:

这里写图片描述

四、开源项目

1.zhusuan

开源项目zhusuan,出自清华大学朱军

ZhuSuan是一个用于贝叶斯深度学习python概率编程库 ,它结合了贝叶斯方法和深度学习的互补优势。ZhuSuan建立在 Tensorflow之上。链接:https://zhusuan.readthedocs.io/en/latest/index.html

珠算是清华大学机器学习组开源的一个贝叶斯深度学习的 GPU 库,是一个构建于 TensorFlow 之上的用于生成模型的 Python 库,结合了贝叶斯方法和深度学习的优势进行互补。与目前主要面向神经网络和监督任务的深度学习库不同,珠算的特点是深入到贝叶斯推断中,从而支持各类概率模型,包括传统分层贝叶斯模型以及最近的深度生成模型。https://www.oschina.net/p/zhusuan

ZhuSuan提供了深度学习风格的算法,用于构建概率模型和应用贝叶斯推理。支持的推理算法包括:

  • 通过可编程变分后验、各种对象和高级梯度估算器(SGVBREINFORCEVIMCO等)进行变分推理。变分推理和随机变分推理 (SGVBREINFORCEVIMCO )
  • Variational inference with programmable variational posteriors, various objectives and advanced gradient estimators (SGVB, REINFORCE, VIMCO, etc.)
  • 学习和评估模型的重要性抽样,具有可编程的建议。自适应重要程度采样
  • Importance sampling for learning and evaluating models, with programmable proposals
  • Hamiltonian Monte CarloHMC)具有并行链,可选自动参数调整。马尔可夫链蒙特卡洛(MCMC
  • Hamiltonian Monte Carlo (HMC) with parallel chains, and optional automatic parameter tuning

Distributions are basic functionalities for building probabilistic models.The distributions class is the base class for various probabilistic distributions which support batch inputs, generating batches of samples and evaluate probabilities at batches of given values.      Distributions是构建概率模型的基本功能。distributions类是在其给定的值的批次支持批量输入,生成样本的批次和评估概率各种概率分布的基类。

珠算仍在开发中。在第一个稳定版本(1.0)之前,请克隆GitHub存储库并运行。本地安装方法:下载并解压安装包到E:\Anaconda3\Lib\site-packagescodan环境进入E:\Anaconda3\Lib\site-packages\zhusuan-master输入以下pip安装依赖环境:

pip install .

在主目录中。这将自动安装ZhuSuan及其依赖项。

pip install ".[examples]"#单独安装依赖环境

  • 高斯(Gaussian):HMC
  • Toy 2D Intractable Posterior: SGVB
  • 贝叶斯神经网络:SGVB
  • 变自编码器(VAE):SGVBIWAE
  • 卷积 VAESGVB
  • 半监督 VAEKingma, 2014SGVBRWS
  • 深度 Sigmoid 信念网络:RWSVIMCO
  • Logistic Normal 主题模型:HMC

创建单变量正态分布:表示非批输入参数的形状表示将多少独立输入馈入分配。

>>> import zhusuan as zs

>>> a = zs.distributions.Normal(mean=0., logstd=0.)

可以通过调用sample()分发对象的方法生成样本 

单变量分布例子(Normal)

>>> import tensorflow as tf
>>> _ = tf.InteractiveSession()
>>> b = zs.distributions.Normal([[-1., 1.], [0., -2.]], [0., 1.])
>>> b.batch_shape.eval()
array([2, 2], dtype=int32)
>>> b.value_shape.eval()
array([], dtype=int32)
>>> tf.shape(b.sample()).eval()
array([2, 2], dtype=int32)
>>> tf.shape(b.sample(1)).eval()
array([1, 2, 2], dtype=int32)
>>> tf.shape(b.sample(10)).eval()
array([10,  2,  2], dtype=int32)

多变量分布例子(OnehotCategorical):

>>> c = zs.distributions.OnehotCategorical([[0., 1., -1.],
...                                         [2., 3., 4.]])
>>> c.batch_shape.eval()
array([2], dtype=int32)
>>> c.value_shape.eval()
array([3], dtype=int32)
>>> tf.shape(c.sample()).eval()
array([2, 3], dtype=int32)
>>> tf.shape(c.sample(1)).eval()
array([1, 2, 3], dtype=int32)
>>> tf.shape(c.sample(10)).eval()
array([10,  2,  3], dtype=int32)

在某些情况下,将一批随机变量分组到单个事件中,以便可以一起计算它们的概率。group_ndims参数来实现的,该参数默认为0.

通过将给定值传递给log_prob()分布对象的方法来评估对数概率密度函数。

>>> d = zs.distributions.Normal([[-1., 1.], [0., -2.]], 0.,
...                             group_ndims=1)
>>> d.log_prob(0.).eval()
array([-2.83787704, -3.83787727], dtype=float32)
>>> e = zs.distributions.Normal(tf.zeros([2, 1, 3]), 0.,
...                             group_ndims=2)
>>> tf.shape(e.log_prob(tf.zeros([5, 1, 1, 3]))).eval()
array([5, 2], dtype=int32)

贝叶斯网络

ZhuSuan,我们支持将概率模型构建为贝叶斯网络,即有向图形模型。

构建贝叶斯线性回归模型的完整代码如下:

x = tf.placeholder(tf.float32, shape=[5])
alpha = 1.
beta = 0.1
def bayesian_linear_regression(x, alpha, beta):
    bn = zs.BayesianNet() #构建为贝叶斯网络,即有向图形模型
    w = bn.normal("w", mean=0., std=alpha)# w随机节点(随机变量)
    y_mean = tf.reduce_sum(w * x, axis=-1)
    bn.normal("y", y_mean, std=beta)
    return bn

贝叶斯网络将一组随机变量上的联合分布的依赖结构描述为有向图。

>>> print(w)
<zhusuan.framework.bn.StochasticTensor object at ...

线性回归的预测平均值是w输入之间的内积x

y_mean = tf.reduce_sum(w * x, axis=-1)

在某些情况下,通过该deterministic()方法启用跟踪很方便 

y_mean = bn.deterministic("y_mean", tf.reduce_sum(w * x, axis=-1))

支持有关网络当前状态的查询,例如:

# get named node(s)
w = bn["w"]
w, y = bn.get(["w", "y"])
# get log probabilities of stochastic nodes conditioned on the current
# value of other StochasticTensors.
log_pw, log_py = bn.cond_log_prob(["w", "y"])
# get log joint probability given the current values of all stochastic
# nodes
log_joint_value = bn.log_joint()

默认情况下,通过对所有随机节点处的条件对数概率求和来计算对数联合概率。这要求所有随机节点的分布批量形状正确对齐。如果不是,则返回的值可以是任意的。大多数情况下,您可以调整随机节点的group_ndims参数来解决此问题。如果不是这种情况,我们仍然允许通过在MetaBayesianNet实例中重写它来自定义日志联合概率函数, 如:

meta_bn = build_linear_regression(x, alpha, beta)
def customized_log_joint(bn):
    return tf.reduce_sum(
        bn.cond_log_prob("w"), axis=-1) + bn.cond_log_prob("y")
meta_bn.log_joint = customized_log_joint

那么由此BayesianNet构造的所有实例meta_bn都将使用提供的自定义函数来计算结果bn.log_joint()

贝叶斯神经网络

分为建立模型、推理、评估、梯度下降四步。

神经网络的典型训练需要大量标记数据来控制过度拟合的风险。当涉及现实世界的回归任务时,问题变得更加困难。这些任务通常需要使用较少量的训练数据,这些数据的高频特性常常使神经网络更容易陷入过度拟合中。解决该问题的原理方法是贝叶斯神经网络 BNN)。

BNN中,先前的分布被置于神经网络的权重上以考虑建模不确定性。通过对权重进行贝叶斯推断,可以学习既适合训练数据的预测因子,又可以了解其自身对测试数据的预测的不确定性的原因。在ZhuSuan中实现BNN完整脚本:

 

from __future__ import absolute_import

 

from __future__ import print_function

 

from __future__ import division

 

import os

 

import tensorflow as tf

 

from six.moves import range, zip

 

import numpy as np

 

import zhusuan as zs

 

from examples import conf

 

from examples.utils import dataset

 

@zs.meta_bayesian_net(scope="bnn", reuse_variables=True)

 

def build_bnn(x, layer_sizes, n_particles):# 模型构建函数

 

    bn = zs.BayesianNet()#在生成过程之后,我们需要标准的正态分布来生成权重w

 

    h = tf.tile(x[None, ...], [n_particles, 1, 1])

 

    for i, (n_in, n_out) in enumerate(zip(layer_sizes[:-1], layer_sizes[1:])):

 

        w = bn.normal("w" + str(i), tf.zeros([n_out, n_in + 1]), std=1.,

 

                      group_ndims=2, n_samples=n_particles)# n_samples参数设置为占位符

 

        h = tf.concat([h, tf.ones(tf.shape(h)[:-1])[..., None]], -1)

 

        h = tf.einsum("imk,ijk->ijm", w, h) / tf.sqrt(

 

            tf.cast(tf.shape(h)[2], tf.float32))

 

        if i < len(layer_sizes) - 2:

 

            h = tf.nn.relu(h)

 

 

 

    y_mean = bn.deterministic("y_mean", tf.squeeze(h, 2))

 

    y_logstd = tf.get_variable("y_logstd", shape=[],

 

                               initializer=tf.constant_initializer(0.))

 

    bn.normal("y", y_mean, logstd=y_logstd)

 

    return bn

 

 

 

 

 

@zs.reuse_variables(scope="variational")

 

def build_mean_field_variational(layer_sizes, n_particles):

 

    bn = zs.BayesianNet()

 

    for i, (n_in, n_out) in enumerate(zip(layer_sizes[:-1], layer_sizes[1:])):

 

        w_mean = tf.get_variable(

 

            "w_mean_" + str(i), shape=[n_out, n_in + 1],

 

            initializer=tf.constant_initializer(0.))

 

        w_logstd = tf.get_variable(

 

            "w_logstd_" + str(i), shape=[n_out, n_in + 1],

 

            initializer=tf.constant_initializer(0.))

 

        bn.normal("w" + str(i), w_mean, logstd=w_logstd,

 

                  n_samples=n_particles, group_ndims=2)

 

    return bn

 

 

 

 

 

def main():

 

    tf.set_random_seed(1237)

 

    np.random.seed(2345)

 

 

 

    # Load UCI Boston housing data

 

    data_path = os.path.join(conf.data_dir, "housing.data")

 

    x_train, y_train, x_valid, y_valid, x_test, y_test = \

 

        dataset.load_uci_boston_housing(data_path)

 

    x_train = np.vstack([x_train, x_valid])

 

    y_train = np.hstack([y_train, y_valid])

 

    n_train, x_dim = x_train.shape

 

 

 

    # Standardize data

 

    x_train, x_test, _, _ = dataset.standardize(x_train, x_test)

 

    y_train, y_test, mean_y_train, std_y_train = dataset.standardize(

 

        y_train, y_test)

 

 

 

    # Define model parameters

 

    n_hiddens = [50]

 

 

 

    # Build the computation graph

 

    n_particles = tf.placeholder(tf.int32, shape=[], name="n_particles")

 

    x = tf.placeholder(tf.float32, shape=[None, x_dim])

 

    y = tf.placeholder(tf.float32, shape=[None])

 

    layer_sizes = [x_dim] + n_hiddens + [1]

 

    w_names = ["w" + str(i) for i in range(len(layer_sizes) - 1)]

 

 

 

    model = build_bnn(x, layer_sizes, n_particles)

 

    variational = build_mean_field_variational(layer_sizes, n_particles)

 

 

 

    def log_joint(bn):

 

        log_pws = bn.cond_log_prob(w_names)

 

        log_py_xw = bn.cond_log_prob('y')

 

        return tf.add_n(log_pws) + tf.reduce_mean(log_py_xw, 1) * n_train

 

 

 

    model.log_joint = log_joint

 

 

 

    lower_bound = zs.variational.elbo(

 

        model, {'y': y}, variational=variational, axis=0)

 

    cost = lower_bound.sgvb()

 

 

 

    optimizer = tf.train.AdamOptimizer(learning_rate=0.01)

 

    infer_op = optimizer.minimize(cost)

 

 

 

    # prediction: rmse & log likelihood

 

    y_mean = lower_bound.bn["y_mean"]

 

    y_pred = tf.reduce_mean(y_mean, 0)

 

    rmse = tf.sqrt(tf.reduce_mean((y_pred - y) ** 2)) * std_y_train

 

    log_py_xw = lower_bound.bn.cond_log_prob("y")

 

    log_likelihood = tf.reduce_mean(zs.log_mean_exp(log_py_xw, 0)) - tf.log(

 

        std_y_train)

 

 

 

    # Define training/evaluation parameters

 

    lb_samples = 10

 

    ll_samples = 5000

 

    epochs = 500

 

    batch_size = 10

 

    iters = (n_train-1) // batch_size + 1

 

    test_freq = 10

 

 

 

    # Run the inference

 

    with tf.Session() as sess:

 

        sess.run(tf.global_variables_initializer())

 

        for epoch in range(1, epochs + 1):

 

            perm = np.random.permutation(x_train.shape[0])

 

            x_train = x_train[perm, :]

 

            y_train = y_train[perm]

 

            lbs = []

 

            for t in range(iters):

 

                x_batch = x_train[t * batch_size:(t + 1) * batch_size]

 

                y_batch = y_train[t * batch_size:(t + 1) * batch_size]

 

                _, lb = sess.run(

 

                    [infer_op, lower_bound],

 

                    feed_dict={n_particles: lb_samples,

 

                               x: x_batch, y: y_batch})

 

                lbs.append(lb)

 

            print('Epoch {}: Lower bound = {}'.format(epoch, np.mean(lbs)))

 

 

 

            if epoch % test_freq == 0:

 

                test_rmse, test_ll = sess.run(

 

                    [rmse, log_likelihood],

 

                    feed_dict={n_particles: ll_samples,

 

                               x: x_test, y: y_test})

 

                print('>> TEST')

 

                print('>> Test rmse = {}, log_likelihood = {}'

 

                      .format(test_rmse, test_ll))

 

 

 

 

 

if __name__ == "__main__":

 

    main()

我们使用名为Boston housing的回归数据集 。这有N=506N=506 数据点,用 D=13D=13尺寸。用于建模多元回归的BNN的生成过程如下:

 

这个生成过程从输入功能开始(x),通过深度神经网络转发(fNN L 图层,每个图层的参数(Wi)满足分解的多元标准正态分布。通过这种前向转换,模型能够学习输入之间的复杂关系(x)和输出(y)。最后,将一些噪声添加到输出中以获得模型的易处理可能性,这通常是回归问题中的高斯噪声。贝叶斯神经网络的图形模型表示如下。

 

学习节点https://zhusuan.readthedocs.io/en/latest/tutorials/bnn.html#build-the-model

2.pgmpy

pgmpy是一个用于处理概率图形模型的python库。

支持的文档和算法列表在我们的官方网站 http://pgmpy.org/
使用pgmpy的示例:https://github.com/pgmpy/pgmpy/tree/dev/examples使用pgmpy
概率图形模型基础教程:https://github.com/pgmpy/pgmpy_notebook

相关学习https://blog.csdn.net/ld326/article/details/81480206

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章