科技

PyTorch深度概率推斷工具Brancher,掌握ML和Python基礎即可上手

機器之心報道

參與:一鳴、張倩

近日,來自荷蘭拉德堡德大學(Radboud University)團隊的開發者在 reddit 上釋出了一個 PyTorch 深度概率推斷工具——Brancher,旨在使貝葉斯統計和深度學習之間的整合變得簡單而直觀。與其他概率推斷工具相比,Brancher 對新手更加友好,只具備機器學習和 Python 基礎的人也可以上手使用。專案地址:https://brancher.org/

特點

Brancher 官網顯示,這一工具具有靈活(flexible)、整合(integrated)、直觀(intuitive)的特點。

靈活:易於擴充套件建模帶有 GPU 加速的 PyTorch 後端的框架整合:易於使用帶有 Pandas 和 Seaborn 支援的當前工具直觀:易於利用數學類語法學習符號推理與其他概率建模工具有什麼區別?

專案的主要開發者 LucaAmbrogioni 表示,與 Brancher 緊密相關的兩個模組是 Pyro 和 PyMC3。Brancher 的目標受眾比 Pyro 更廣泛,包括那些只接受過機器學習和 Python 程式設計基本培訓的人。介面設計得儘可能接近數學。缺點是 Brancher 不如 Pyro 靈活。

Brancher 的前端與 PyMC3 非常相似。與 PyMC 的主要區別在於,Brancher 構建在深度學習庫 PyTorch 的頂部。每一個在 PyTorch 中實現的深度學習工具都可以用來在 Brancher 中構建深度概率模型。此外,PyMC 主要利用取樣,而 Brancher 則基於變分推理。

安裝

使用者需要首先安裝 PyTorch,然後使用 pip 命令列:

pip install *brancher*

或從 GitHub 地址克隆程式碼,Github 地址:https://github.com/AI-DI/Brancher

教程

Google Colab 上有相關教程,包括

Brancher 入門使用 Brancher 進行時間序列分析使用 Brancher 進行貝葉斯統計分析Brancher 入門

Brancher 是一個以使用者為中心的概率微分程式包。Brancher 希望能夠為初學者提供友好的服務,在保證計算執行效率和靈活性的前提下減少多餘的程式碼。Brancher 以 PyTorch 為核心構建。

安裝 Brancher 成功後,首先需要使用者匯入相關包:

import torch

import matplotlib.pyplot as plt

from brancher.variables import ProbabilisticModel

from brancher.standard_variables import NormalVariable, LogNormalVariable

from brancher import inference

import brancher.functions as BF

Brancher 是一個物件導向的工具包。因此內部的所有物件都是一個類,可以用來抽象化為概率計算程式。建立所有 Brancher 程式的基礎元件是 RandomVariable 類。通過微分方程連線隨機變數,可以建立概率模型。

例如,可以建立這樣一個模型,其中一個正則隨機變數的均值是由另一個正則隨機變數的正弦函式值決定的。Brancher 可以讓你像在學術論文裡那樣使用符號定義模型。

建立變數:

nu = LogNormalVariable(loc=0., scale=1., name="nu")

mu = NormalVariable(loc=0., scale=10., name="mu")

x = NormalVariable(loc=BF.sin(mu), scale=nu, name="x")

使用定義好的變數建立一個概率模型:

model = ProbabilisticModel([x, mu, nu])

列印模型的內部組成:

model.model_summary

列印結果:

正如我們所預計的那樣,變數 x 是 mu 和 nu 的計算結果。但是,列表中也出現了 mu_mu 或 mu_sigma 這樣沒有提前明確定義的變數。這些確定變數(Deterministic Variables)代表的是概率分佈引數的固定值。確定變數是 Brancher 中的特例,和隨機變數相似,但值是確定的。我們不需要定義他們,只需要在計算時輸入數字即可。

由於現在沒有輸入資料,因此 Observed 一欄為 False,現在我們輸入一些樣本資料,看看概率模型如何工作。

sample = model.get_sample(10)

sample

如果只需要單個變數的結果:

x_sample = x.get_sample(10)

x_sample

我們還可以做到通過輸入某些變數的值後進行取樣,如設定 mu 變數為 100 時,檢視樣本結果:

in_sample = model.get_sample(10, input_values={mu: 100.})

in_sample

為了對某些已知的值進行上取樣,我們需要定義一些觀測值,並使用變分推斷的方法獲得分佈。我們可以首先對 mu 和 nu 變數定義一些真實值,並生產一些觀測結果:

nu_real = 0.5

mu_real = -1.

data = x.get_sample(number_samples=100, input_values={mu: mu_real, nu: nu_real})

現在我們可以告訴 Brancher 變數 x 是從生成資料的值中觀察到的。

x.observe(data)

model.model_summary

這時可以看到變數 x 變為 observed。

如果你想取樣下游 x 的變數 mu 和 nu,你需要執行近似貝葉斯推理。在 Brancher 中,可以通過為所有想要取樣的變數定義一個變分分佈來實現這一點。變分模型本身是一個概率模型,其構造方法與原概率模型完全相同。

指定此分佈的最簡單方法是使用與原始模型中相同的分佈:

Qnu = LogNormalVariable(0., 1., "nu", learnable=True)

Qmu = NormalVariable(0., 1., "mu", learnable=True)

model.set_posterior_model(ProbabilisticModel([Qmu, Qnu]))

現在我們需要使用一些隨機優化來學習變分近似的引數。這種技術被稱為隨機變分推理,該技術非常強大,因為它可以將貝葉斯推理很好地融入到深度學習框架中(實際上 brancher 的目的是與深度神經網路一起作為構建複雜概率模型的模組)。

現在讓 Brancher 知道,變數分佈的引數可以使用「learnable」flag 學習。接下來學習這些引數:

inference.perform_inference(model,

number_iterations=500,

number_samples=50,

optimizer="Adam",

lr=0.01)

loss_list = model.diagnostics["loss curve"]

現在把損失函式畫出來,以確保一切順利。

plt.plot(loss_list)

現在從後驗取一些樣本:

post_sample = model.get_posterior_sample(1000)

post_sample.describe

與真值一起繪製後驗分佈:

g = plt.hist(post_sample["mu"], 50)

plt.axvline(x=mu_real, color="k", lw=2)

[Image: image.png]

可以用 Brancher 繪製的函式視覺化後驗分佈。這個函式依賴於 Seaborn,Seaborn 是一個非常方便的視覺化庫,與 panda 結合使用非常好。

from brancher.visualizations import plot_posterior

plot_posterior(model, variables=["mu", "nu", "x"])

更多教程請參考:

使用 Brancher 進行時間序列分析,地址:https://colab.research.google.com/drive/1WuVUqr9pahhO4E4ema4vjDxxH-aMvMqb使用 Brancher 進行貝葉斯統計分析,地址:https://colab.research.google.com/drive/1L3kp7V48mRQYQDimn16OX1l0c0s20JFd案例

作者提供了許多使用 Brancher 的案例,包括:

自動迴歸建模變分自動編碼器多元迴歸自動迴歸建模完整程式碼:

import matplotlib.pyplot as plt

import numpy as np

from brancher.variables import RootVariable, RandomVariable, ProbabilisticModel

from brancher.standard_variables import NormalVariable, LogNormalVariable, BetaVariable

from brancher import inference

import brancher.functions as BF

# Probabilistic model #

T = 200

nu = LogNormalVariable(0.3, 1., 'nu')

x0 = NormalVariable(0., 1., 'x0')

b = BetaVariable(0.5, 1.5, 'b')

x = [x0]

names = ["x0"]

for t in range(1, T):

names.append("x{}".format(t))

x.append(NormalVariable(b*x[t-1], nu, names[t]))

AR_model = ProbabilisticModel(x)

# Generate data #

data = AR_model._get_sample(number_samples=1)

time_series = [float(data[xt].cpu.detach.numpy) for xt in x]

true_b = data[b].cpu.detach.numpy

true_nu = data[nu].cpu.detach.numpy

print("The true coefficient is: {}".format(float(true_b)))

# Observe data #

[xt.observe(data[xt][:, 0, :]) for xt in x]

# Variational distribution #

Qnu = LogNormalVariable(0.5, 1., "nu", learnable=True)

Qb = BetaVariable(0.5, 0.5, "b", learnable=True)

variational_posterior = ProbabilisticModel([Qb, Qnu])

AR_model.set_posterior_model(variational_posterior)

# Inference #

inference.perform_inference(AR_model,

number_iterations=200,

number_samples=300,

optimizer='Adam',

lr=0.05)

loss_list = AR_model.diagnostics["loss curve"]

# Statistics

posterior_samples = AR_model._get_posterior_sample(2000)

nu_posterior_samples = posterior_samples[nu].cpu.detach.numpy.flatten

b_posterior_samples = posterior_samples[b].cpu.detach.numpy.flatten

b_mean = np.mean(b_posterior_samples)

b_sd = np.sqrt(np.var(b_posterior_samples))

print("The estimated coefficient is: {} +- {}".format(b_mean, b_sd))

# Two subplots, unpack the axes array immediately

f, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4)

ax1.plot(time_series)

ax1.set_title("Time series")

ax2.plot(np.array(loss_list))

ax2.set_title("Convergence")

ax2.set_xlabel("Iteration")

ax3.hist(b_posterior_samples, 25)

ax3.axvline(x=true_b, lw=2, c="r")

ax3.set_title("Posterior samples (b)")

ax3.set_xlim(0,1)

ax4.hist(nu_posterior_samples, 25)

ax4.axvline(x=true_nu, lw=2, c="r")

ax4.set_title("Posterior samples (nu)")

plt.show

從左到右依次為「Time Series」、「Convergence」、「Posterior Samples (b)」、「Posterior Samples (n)」

更多案例請參考:

使用變分自動編碼器學習識別 MNIST 手寫數字:https://colab.research.google.com/drive/1EvQS1eWWYdVlhuoP-y1RXED9a2CNu3XQ多元迴歸分析:https://colab.research.google.com/drive/1ZyhidyCGEH_epDRt29HzvR65V8EN0kpX

Reference:科技日報

看更多!請加入我們的粉絲團

轉載請附文章網址

不可錯過的話題