TensorFlow Probability 概率編程入門級實操教程
雷鋒網 AI 科技評論按: TensorFlow Probability(TFP)是一個基于 TensorFlow 的?Python 庫,能夠更容易地結合概率模型和深度學習。數據科學家、統計學以及機器學習研究者或者從業者,都可以用它編碼領域知識 (Domain Knowledge),從而理解數據并寫出自己的應用。針對那些對?TFP 還不那么熟悉的入門者,日前,谷歌?TensorFlow Probability 的產品經理 ?Mike Shwe 及軟件工程師?Josh Dillon、谷歌的軟件工程師?Bryan Seybold 及? Matthew McAteer 、 Cam Davidson-Pilon 共同在?TensorFlow 官網上發布介紹?TensorFlow Probability 的入門級實操性教程——《Bayesian Methods for Hackers》的文章,雷鋒網 AI 科技評論編譯如下。
之前沒有學過概率編程?對 TensorFlow Probability (TFP)還不熟悉?下面我們為你準備了入門級實操性教程——《Bayesian Methods for Hackers》(教程查看地址: https://camdavidsonpilon.github.io/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers/#tensorflow ),這門教程的實例現在也在 TFP 中開放了。作為對所有人開放的開源資源,TFP 版本的概率編程對之前用 PyMC3 寫的那版進行了補充。
《Bayesian Methods for Hackers》具備許多優勢:它不僅能讓概率初學者較容易上手,而且還展示了如何將概率編程應用于現實問題。
每個人都可以學的概率編程
雖然概率編程不要求貝葉斯方法(Bayesian approach),但是該方法提供了一個相對直觀的框架,來表示信念(representing beliefs),并基于新的數據來更新這些信念。《Bayesian Methods for Hackers》使用 TFP 為基礎,以實操的方式來教授這些技術。由于這本書由 Google Colab 所寫,你可以運行并修改其中的 Python 示例。
TensorFlow 團隊開發的?TFP 專門面向數據科學家、統計學家以及以及想要編碼領域知識 (Domain Knowledge)來了解數據并進行數據預測的機器學習研究者和從業者。TFP 是基于 TensorFlow 的 Python 開發庫,能夠更容易地結合概率模型和先進硬件上的深度學習。TFP 可以讓你:
互動地探究數據
快速地評估不同的模型
自動地利用先進的、矢量化的硬件加速器
更輕易、更有把握地啟用。TFP 經專業地開發和測試,可使用現成的 Google-Cloud,并且還有一個強大的開源社區的支持。
正如我們在相關博文中曾討論過的,概率編程有非常多樣化的應用,包括金融、石油和天然氣等各行各業。為什么?——因為不確定性無處不在。現實世界的現象——即便是那些我們完全了解的現象,都受到我們無法控制甚至無法意識到的外部因素的影響。如果忽略這些因素,這些模型所得出的結論可能往好里說是誤導性的或者是完全錯誤的。我們開發出了對所有場景都可用的 TFP,就是為了對我們周圍所有的不確定性進行建模。
解決現實世界的問題
許多貝葉斯教程都是聚焦于解決那些已有分析結果的簡單問題:比如擲硬幣和擲骰子的問題。不過《Bayesian Methods for Hackers》一書是從這些簡單的問題開始,之后迅速轉向更加現實的問題,例如從理解宇宙到檢測某個在線用戶的行為變化等。
在這篇文章接下來的部分,我們將一起探討一個 非常有名的現實世界的問題,這個問題在 Bayesian Hackers 一書中的第二章節(查看地址: https://github.com/CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers/blob/master/Chapter2_MorePyMC/Ch2_MorePyMC_TFP.ipynb )有更詳細的描述:1986 年航天飛機挑戰者的災難。
1986 年 1 月 28 日,美國挑戰者號航天飛機的第 25 次飛行中,由于一處 O 形圈故障,挑戰者號的兩個固體火箭助推器其中的一個發生了爆炸。雖然控制中心的工程師們與 O 形圈制造商就先前飛行中的損壞進行了多次溝通,但制造商堅持認為風險是可以接受的。
下圖將對先前航天飛機任務中的七次 O 形圈損壞事件的觀測,描述成了一個環境溫度的函數。(在 70 度時,有兩次損壞事件。)
你會注意到,隨著溫度的降低,O 形圈損壞的比例會明顯增多,不過沒有明顯的溫度閾值——低于該閾值時 O 形圈就一定會失效。與現實世界中的大多數現象一樣,這個問題涉及不確定性。我們希望在給定溫度 t 下,來確定 O 形圈失效的概率。
我們可以特別使用邏輯函數模擬溫度 t 下 O 形環損壞的概率 p :
其中β確定概率函數的形狀,α是偏移項,控制函數從左向右移動。由于這兩個參數都既是正的或負的,也沒有特定的邊界或大小的偏差,我們可以將它們建模為高斯分布隨機變量:
在 TFP 中,我們可以用
tfp.distributions.Normal
直觀地表示 α 和 β,其代碼片段如下:
temperature_ = challenger_data_[:, 0] ? ?
temperature = tf.convert_to_tensor(temperature_, dtype=tf.float32) ? ?
D_ = challenger_data_[:, 1] ? ? ? ? ? ? ? ?# defect or not? ? ?
D = tf.convert_to_tensor(D_, dtype=tf.float32) ? ?
beta = tfd.Normal(name="beta", loc=0.3, scale=1000.).sample() ? ?
alpha = tfd.Normal(name="alpha", loc=-15., scale=1000.).sample() ? ?
p_deterministic = tfd.Deterministic(name="p", loc=1.0/(1. + tf.exp(beta * temperature_ + alpha))).sample() ? ?
[ ? ?
prior_alpha_, ? ?
prior_beta_, ? ?
p_deterministic_, ? ?
D_, ? ?
] = evaluate([ ? ?
alpha, ? ?
beta, ? ?
p_deterministic, ? ?
D, ? ?
]) ? ?
(如果要運行這個代碼片段,請前往本書第二章的 Google Colab 版本,來運行整個航天飛機示例)。
要注意的是,我們在第 8 行得到 p(t) 的實際值 0 或 1,其中我們使用此前在第 6 行和第 7 行中采樣的α和β值從概率函數(logistic function)中采樣。此外,注意 evaluate() 輔助函數可以讓我們實現圖表和 eager 模式之間的無縫轉換,與此同時將張量值轉換為 numpy。關于 eager 和圖表模型以及這一輔助函數的更詳細的講解,請查看 第二章節的開頭部分 。
為了將溫度 t 下的失效概率 p(t) 與我們觀測的數據聯系起來,我們可以使用帶參數 p(t) 的伯努利隨機變量。要注意的是,一般而言 Ber(p) 是隨機變量,它的值為 1 的概率為 p,其它情況下都為 0。因此,生成模型的最后一部分是溫度值為 的情況下觀測到的有缺陷事件的數量 D,我們可以對其建模為:
給定這一生成模型的情況下,我們希望找到模型參數從而讓模型能夠解釋所觀察到的數據——這正是是概率推理的目標。
TFP 通過使用非標準化的聯合對數概率函數評估模型來執行概率推斷。此 joint_log_prob 的論點是數據和模型狀態。該函數返回參數化模型生成觀測數據的聯合概率的對數。如果要了解更多關于 joint_log_prob 的信息,可以查看 這個 短文介紹。
針對上述挑戰者的示例,這里我們定義 joint_log_prob 的方式如下:
def challenger_joint_log_prob(D, temperature_, alpha, beta): ? ?
""" ? ?
? ?Joint log probability optimization function. ? ?
? ?Args: ? ?
? ? ?D: The Data from the challenger disaster representing presence or ?? ?
? ? ? ? absence of defect ? ?
? ? ?temperature_: The Data from the challenger disaster, specifically the temperature on ?? ?
? ? ? ? the days of the observation of the presence or absence of a defect ? ?
? ? ?alpha: one of the inputs of the HMC ? ?
? ? ?beta: one of the inputs of the HMC ? ?
? ?Returns: ?? ?
? ? ?Joint log probability optimization function. ? ?
? ?""" ? ?
rv_alpha = tfd.Normal(loc=0., scale=1000.) ? ?
rv_beta = tfd.Normal(loc=0., scale=1000.) ? ?
logistic_p = 1.0/(1. + tf.exp(beta * tf.to_float(temperature_) + alpha)) ? ?
rv_observed = tfd.Bernoulli(probs=logistic_p) ? ?
return ( ? ?
rv_alpha.log_prob(alpha) ? ?
+ rv_beta.log_prob(beta) ? ?
+ tf.reduce_sum(rv_observed.log_prob(D)) ? ?
) ? ?
注意 15-18 行怎樣簡單地對生成模型、每行的隨機變量進行編碼。同時也要注意 rv_alpha 和 rv_beta 表示此前對 和 β 分布的隨機變量。相比之下, rv_observed 表示給定一個參數為 和 β 的概率分布情況下溫度和 O 形圈輸出的觀察可能性的條件分布。
接下來,我們使用 joint_log_prob 函數,并將其發送到 tfp.mcmc 模塊。 馬爾可夫鏈蒙特卡洛 (MCMC)算法對未知的輸入值進行有依據的猜測,并計算 joint_log_prob 函數中參數集的可能性。通過多次重復這一過程,MCMC 構建了可能的參數的分布,而構建這一分布是概率推理的目標。
因此,我們將在 challenge_joint_log_prob 函數上設置一種特定類型的稱為「哈密頓蒙特卡洛」的 MCMC:
number_of_steps = 60000 ? ?
burnin = 50000 ? ?
# Set the chain's start state. ? ?
initial_chain_state = [ ? ?
0. * tf.ones([], dtype=tf.float32, name="init_alpha"), ? ?
0. * tf.ones([], dtype=tf.float32, name="init_beta") ? ?
] ? ?
# Since HMC operates over unconstrained space, we need to transform the ? ?
# samples so they live in real-space. ? ?
unconstraining_bijectors = [ ? ?
tfp.bijectors.Identity(), ? ?
tfp.bijectors.Identity() ? ?
] ? ?
# Define a closure over our joint_log_prob. ? ?
unnormalized_posterior_log_prob = lambda *args: challenger_joint_log_prob(D, temperature_, *args) ? ?
# Initialize the step_size. (It will be automatically adapted.) ? ?
with tf.variable_scope(tf.get_variable_scope(), reuse=tf.AUTO_REUSE): ? ?
step_size = tf.get_variable( ? ?
name='step_size', ? ?
initializer=tf.constant(0.5, dtype=tf.float32), ? ?
trainable=False, ? ?
use_resource=True ? ?
) ? ?
# Defining the HMC ? ?
hmc=tfp.mcmc.TransformedTransitionKernel( ? ?
inner_kernel=tfp.mcmc.HamiltonianMonteCarlo( ? ?
target_log_prob_fn=unnormalized_posterior_log_prob, ? ?
num_leapfrog_steps=2, ? ?
step_size=step_size, ? ?
step_size_update_fn=tfp.mcmc.make_simple_step_size_update_policy(), ? ?
state_gradients_are_stopped=True), ? ?
bijector=unconstraining_bijectors) ? ?
# Sampling from the chain. ? ?
[ ? ?
posterior_alpha, ? ?
posterior_beta ? ?
], kernel_results = tfp.mcmc.sample_chain( ? ?
num_results = number_of_steps, ? ?
num_burnin_steps = burnin, ? ?
current_state=initial_chain_state, ? ?
kernel=hmc) ? ?
# Initialize any created variables for preconditions ? ?
init_g = tf.global_variables_initializer() ? ?
最終,我們將真正通過 evaluate() 輔助函數進行推理:
evaluate(init_g) ? ?
[ ? ?
posterior_alpha_, ? ?
posterior_beta_, ? ?
kernel_results_ ? ?
] = evaluate([ ? ?
posterior_alpha, ? ?
posterior_beta, ? ?
kernel_results ? ?
]) ? ?
print("acceptance rate: {}".format( ? ?
kernel_results_.inner_results.is_accepted.mean())) ? ?
print("final step size: {}".format( ? ?
kernel_results_.inner_results.extra.step_size_assign[-100:].mean())) ? ?
alpha_samples_ = posterior_alpha_[burnin::8] ? ?
beta_samples_ = posterior_beta_[burnin::8] ? ?
繪制 α 和 β 的分布圖時,我們注意到這兩個參數的分布相當寬泛,正如我們所預期的那樣,數據點相當少,并且失效和非失效觀測的溫度出現重疊。然而,即使分布寬泛,我們也可以相當確定溫度確實對 O 形圈損壞的概率有影響,因為β的所有樣本都大于 0。同樣,我們也可以確信 α 明顯小于 0,因為所有的樣本都能很好地轉化為負數。
正如我們上面所提到的,我們真正想知道的是: 在給定溫度下,O 形環損壞的預期概率是多少?為了計算這一概率,我們可以對來自后驗的所有樣本求平均值,從而得到概率 p(t) 的可能值。
alpha_samples_1d_ = alpha_samples_[:, None] ?# best to make them 1d ? ?
beta_samples_1d_ = beta_samples_[:, None] ? ?
beta_mean = tf.reduce_mean(beta_samples_1d_.T[0]) ? ?
alpha_mean = tf.reduce_mean(alpha_samples_1d_.T[0]) ? ?
[ beta_mean_, alpha_mean_ ] = evaluate([ beta_mean, alpha_mean ]) ? ?
print("beta mean:", beta_mean_) ? ?
print("alpha mean:", alpha_mean_) ? ?
def logistic(x, beta, alpha=0): ? ?
""" ? ?
? ?Logistic function with alpha and beta. ? ?
? ?Args: ? ?
? ? ?x: independent variable ? ?
? ? ?beta: beta term ?? ?
? ? ?alpha: alpha term ? ?
? ?Returns: ?? ?
? ? ?Logistic function ? ?
? ?""" ? ?
return 1.0 / (1.0 + tf.exp((beta * x) + alpha)) ? ?
t_ = np.linspace(temperature_.min() - 5, temperature_.max() + 5, 2500)[:, None] ? ?
p_t = logistic(t_.T, beta_samples_1d_, alpha_samples_1d_) ? ?
mean_prob_t = logistic(t_.T, beta_mean_, alpha_mean_) ? ?
[ ? ?
p_t_, mean_prob_t_ ? ?
] = evaluate([ ? ?
p_t, mean_prob_t ? ?
]) ? ?
我們可以在整個溫度范圍內計算 95%的可信區間。要注意的是,這個區間是可靠的,而不是在統計分析的頻率論方法中常用到的置信區間。95%可信區間告訴我們,能夠以 95%的概率確定真實值將位于此區間內。例如,在正如下圖中的紫色區域所顯示的,在 50 度時,我們可以 95%確定 O 形圈損壞的概率介于 1.0 和 0.80 之間。諷刺地是,許多人都錯誤地將置信區間解釋為具有這一特征。
挑戰者號災難發生的當天,其溫度為 31 華氏度,這一事實證明了,O 形圈失效的后驗分布將使我們高度確信挑戰者號會出現損壞的問題。
這種非常簡單的概率分析展示了 TFP 和貝葉斯方法的強大:它們可以提供有價值的分析,同時可以對可能帶來嚴重后果的現實世界的問題進行預測。
在《Bayesian Methods for Hackers》一書中,你可以看到大量現實世界示例。對 短信量隨時間變化的分析 ,可以在制造業和生產系統中的各種故障檢測問題得到廣泛應用。在我們首次起草本章節的 TFP 版本的幾周時間內,谷歌的軟件工程師就應用了短信分析的方法來理解生產軟件的文本片狀(text flakiness)。
你可以找到某個分析來 尋找宇宙中的暗物質 。此外,書中還有 預測上市公司的股票收益率的方法 。
我們希望大家能深入了解本書中的概念性實操演示,并將這些技術應用到各自所在領域的問題中。歡迎大家在 Github 中發表評論和提出要求,來幫助我們對這本書不斷改進,從而使其實現最佳狀態!
本文參考: https://en.wikipedia.org/wiki/Space_Shuttle_Challenger_disaster
via: https://medium.com/tensorflow/an-introduction-to-probabilistic-programming-now-available-in-tensorflow-probability-6dcc003ca29e ?雷鋒網 (公眾號:雷鋒網) AI 科技評論編譯。
。