機器學習(二):貝葉斯

貝葉斯

一、引言

南京大學周志華在《機器學習》中介紹:貝葉斯決策論機器學習模式識別等諸多關注數據分析的領域都有極爲重要的地位。

根據在屬性間依賴的涉及程度,貝葉斯分類器形成了一個“譜”:樸素貝葉斯分類器不考慮屬性間的依賴性,貝葉斯網絡能表示任意屬性間的依賴性,二者分別位於“譜”的兩端。介於兩者之間的則是一系列半樸素貝葉斯分類器,它們基於各種假設和約束來對屬性間的部分依賴性進行建模。

貝葉斯分類器與一般意義上的“貝葉斯學習”有顯著區別,前者是根據最大後驗概率進行單點估計,後者則是進行分佈估計。

二、樸素貝葉斯

樸素貝葉斯算法曾入選“數據挖掘十大算法”。

文氏圖可得貝葉斯公式

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

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