100贝叶斯方法数据分析实战--贝叶斯理论

贝叶斯理论

贝叶斯推断

何为贝叶斯推断?还记得我们是如何调试程序的 bug 的吗?即使我们编程技巧娴熟,也无法保证自己所写的代码毫无 bug。因此,在实现一个复杂的算法之前,我们一般会先用一个简单的测试用例来进行测试。如果测试用例通过,我们才会将其应用在复杂的问题上。然后,再用一个复杂的测试用例进行测试,如果通过,我们就可以把它用在更加复杂的测试用例上……。这样一步一步的测试,我们才能渐渐的相信我们的代码没有 bug。
如果以前你按照过这样的思路思考自己的代码,那么恭喜你。你已经是在利用贝叶斯的思路思考问题了。
简单的来说,贝叶斯的思路其实就是不断地考虑新的证据来坚定自己的信念。因此,利用贝叶斯解决问题是很难得到一个准确的结果的。但是,这种方法却可以不断增强你的自信率。就像刚才所举的例子一样,我们永远不可能保证我们的代码没有一丝 bug ,除非我们把所有的可能的问题都进行了测试(这在实际操作中是不可能实现的)。但是,我们可以对代码进行大量的测试,如果这些案例都通过了,我们就可以很有把握的说,这段代码没有问题。
这就是贝叶斯推断,我们可以通过更多新的的证据来坚定我们的信念,但是我们很少能够做出非常绝对的判断。

贝叶斯推断与传统统计推断

贝叶斯推断与其他传统统计推断的不同之处在于其保留了“不确定性”。这听起来像是一种很差的统计技术。统计不应该是一种从“随机性”中得出“确定性”的方法吗?为了更好的理解这个问题,让我们来解释一下贝叶斯学派思考问题的方式。
传统的统计学派,频率派,认为概率是事件在长时间内发生的频率。例如,在频率学派眼中,飞机发生事故的概率指的是,飞机事故的频率值。对于很多事件来说,这种解释是合理的。但是,对于某些没有长期频率的事件来说,这种解释就有点差强人意了。例如,在总统选举时,我们常说某某候选人获选的概率。但是,一个人获选总统的事件只会发生一次,我们无法用频率来估算这种事件的概率。
而贝叶斯学派对于概率的解释是,对某个事件发生的信心。如果,某人把 0 赋给某个事件,则表示他相信这个事件绝对不会发生。如果他将1赋给某个事件,则表示他相信这个事件必定发生。0−1 之间的其它值,可以表示他相信该事件发生的程度。当然这种概率的定义在一定时候也可以和频率产生联系。比如,在除却所有外部信息的情况下,一个人对飞机失事的信心应该等同于他所了解到的飞机发生事故的频率。但是,在表示总统选举时,贝叶斯的概率定义方法则更有意义,它表示你对选举人A获胜的信心有多少。

这样定义有一个好处,就是每一个人都能够给同一个事件赋予不同的概率值。这是非常符合实际。因为人与人之间是有差异的,不同人对同一个事件是否发生的信心应该是不同的。虽然概率不同,但这并不代表着他们中有人错,有人对。下面的这些例子就详细的阐述了,人对事件发生的信心与概率之间的关系:
在抛一个没有被动过手脚的硬币时大家都知道硬币为正或反的概率都是0.5。但是,假设你预先偷看了结果,知道下次一定为正面。那么这个时候,你认为硬币为正面的概率是多少?显然,你的预先偷看,并不能改变硬币的实际结果,但这使得你对结果赋予的概率值不同了。
一个病人表现出了x,y,z三种症状,但是有很多疾病都会表现出这三种症状。因此不同的医生,可能会因为经验的不同,而对何种疾病导致的这些症状的见解不同。

为了能够更好的和传统概率术语对齐,我们把对事件A发生的信心记作P(A) ,称作先验概率。
伟大的经济学家、思想家 John Maynard Keynes 说过,“当事实改变,我的观念也在改变,你呢?”。这句名言很直观的说明了贝叶斯学派思考事务的方式。随着证据的改变而更新自己的想法与信念。即使证据和我们初始的信念相反,我们也不能忽视证据。
这里我们使用P(A∣X) 表示更新后的信念。即在得到证据 X 后,A 事件发生的概率。为了和先验概率相对应,我们将更新后的概率称之为后验概率。

我们将上面的两个例子中的先验概率和后验概率提取出来:
P(A)=0.5表示硬币有 50% 的概率是正面。P(A∣X)=1,表示你已知下次硬币抛出的信息X的情况下,你预测下次抛出点的硬币信息是正面的概率(显然,你已经知道了结果,再叫你预测结果,那么概率肯定是 100% 或者 0 %) 。
P(A) 表示病人可能患有 A 疾病的概率。P(A∣X)表示,做了血液测试(即获得信息X)后,该疾病为 A 的可能性。

如上,在获得新的证据X后,我们并没有完全否决先前的信念。而是选择了重新调整之前的信念,使其更加符合目前的证据,这样也可以让我们的预测结果更加准确。

贝叶斯推断的实践

如果把频率推断和贝叶斯推断看做两个函数。那么这两个函数所需要的输入就是各种统计数据,但是输出却是不同的。频率推断返回的是一个估计值(通常是统计量,如平均值等),而贝叶斯推断返回的则是一个概率值。
例如在代码测试的例子中,如果你向频率推断函数问道,“我的代码通过了 X 集合中的所有测试,我的代码是不是已经没有 bug 了?”,此时频率推断会给你返回“Yes” 。而如果向贝叶斯推断函数问道,“虽然我的代码常会有 bug ,但是这次的代码已经通过了X集合中的所有测试,我的代码是不是已经没有 bug了?”,此时概率推断会返回两个概率值,如:“yes”的概率为 80% ,“no”的概率为 20% 。
显然,贝叶斯函数的返回结果和频率函数的结果非常不同。并且我们可以注意到,在对贝叶斯函数说话时,我们添加了一个额外的信息,“虽然我的代码常会有bug”。这个信息其实就是传入函数的一个参数,也就是我们之前所说的先验信念。
简单的说,贝叶斯推断就是根据先验信念和真实数据进行推断,推断出所需要参数的后验信念。
更多的数据
当我们添加更多的数据样本时,初始的信念会不断被刷新。假设你的先验信念是非常荒谬的,类似于“太阳今天会爆炸”,然后每天你都会被打脸。你或许会想要一种思维方式来修正你的想法,或者让你的想法变得不是那么荒谬。我想贝叶斯推断会是一个不错的选择。
如果 N 表示我们所拥有的证据数量,那么当 N 趋于无穷大的时候,贝叶斯的结果会和频率派的结果一致。因此对于足够大的 N,使用传统的统计推断也是比较客观的。但是,对于较小的 N ,统计推断就不那么稳定了。而贝叶斯推论却可以通过引入先验概率和返回概率结果,来保留这种不确定性(因为返回结果为概率值)。
当然,也有人认为,对于大的 N 来说,两种统计技术是无差别的,因为结果类似,并且频率派的计算更为简单,因此更加倾向于频率派的方法。
事实上,样本从来都不是足够大的。当 N 太小时,你需要获得更多的数据去进行足够精确的估计。当 N “足够大”时,也可能会划分数据进而研究更多的问题,因此你就可能会需要更多的数据,因此 N 永远无法做到足够大。
上面的这些话是否代表着频率派的模型是错误的呢?事实上,频率法依旧是很多领域最好的方法。例如,最小方差线性回归、LASSO 回归、EM 算法等。这些算法都是非常高效且快速的。
抛硬币实例
让我们以统计书籍中最常见的投硬币为例,详细的阐述一下,贝叶斯推断的全过程。假设我们开始不知道硬币投掷的概率,但是我们相信硬币被投掷为正面的概率一定是一个具体的值,它可能是 0.01、0.02、0.03 等等。我们需要用贝叶斯推断来寻找这个值,让我们利用 Python 的画图工具,以图像的形式展示这个过程。
首先,让我们先导入所需要用到的工具包:

# stats  Scipy 的统计函数库,定义了常见的分布和函数
# 防止画图时的备注出现乱码
import scipy.stats as stats
from IPython.core.pylabtools import figsize
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline

这里让我们对抛硬币实验进行计算机模拟,产生 500 个随机 0-1结果,代码如下:

# stats.bernoulli.rvs :,伯努利分布, 调用该函数产生 0-1 随机数
# data存的就是每次投掷硬币的结果
data = stats.bernoulli.rvs(0.5, size=500)
data

假设在投掷硬币开始之前,我们不知道投掷硬币为正面的概率是多少。也就是说,在进行第 0 次实验时,我们认为硬币投为正面的概率可能为0.1,0.2,0.3,……等,现在让我们画个图来展示我们现在的想法。

N = 0  # 表示第0次训练
x = np.linspace(0, 1, 100)  # 将正面概率的取值等分为100份0.01,0.02,0.03...
heads = data[:N].sum()  # 计算出前N次正面的次数,此时N为0
# 这是分布函数(下一章节会详细阐述),现在可以先将其理解为我们心中的信念
# 通过传入前N次实验投掷为正面的次数,然后得到我们对正面概率为0.01,0.02....的坚信程度
y = stats.beta.pdf(x, 1 + heads, 1 + N - heads)

# 画图并且在图中添加相应的注释
plt.xlabel("$p$, probability of heads")
plt.plot(x, y, label="observe %d tosses,\n %d heads" % (N, heads))
# 填充颜色
plt.fill_between(x, 0, y, color="#348ABD", alpha=0.4)
plt.vlines(0.5, 0, 4, color="k", linestyles="--", lw=1)
leg = plt.legend()
leg.get_frame().set_alpha(0.4)
plt.autoscale(tight=True)

如上图,我们可以清楚的看到,在第 0 次实验时,我们没有一个特定的倾向。认为正面概率的取值可以为 0 到 1 中的任意一个值。上图的纵坐标,就表示我们对硬币被掷为的正面的概率取值的坚信程度(开始的时候,没有倾向,认为每个值都有可能)。
接下来,让我们调整N值。观察一下,进行0、1、2、3、4、5、8、15、50、500 次试验后,我们对概率取值的倾向变化。代码如下:

# 大部分代码上面已经解释,这里只是添加了一个循环。因此不做赘述
figsize(11, 9)
dist = stats.beta
n_trials = [0, 1, 2, 3, 4, 5, 8, 15, 50, 500]
data = stats.bernoulli.rvs(0.5, size=n_trials[-1])
x = np.linspace(0, 1, 100)

# For the already prepared, I'm using Binomial's conj. prior.
for k, N in enumerate(n_trials):
    sx = plt.subplot(len(n_trials)/2, 2, k+1)
    plt.xlabel("$p$, probability of heads") \
        if k in [0, len(n_trials)-1] else None
    plt.setp(sx.get_yticklabels(), visible=False)
    heads = data[:N].sum()
    y = dist.pdf(x, 1 + heads, 1 + N - heads)
    plt.plot(x, y, label="observe %d tosses,\n %d heads" % (N, heads))
    plt.fill_between(x, 0, y, color="#348ABD", alpha=0.4)
    plt.vlines(0.5, 0, 4, color="k", linestyles="--", lw=1)

    leg = plt.legend()
    leg.get_frame().set_alpha(0.4)
    plt.autoscale(tight=True)


plt.suptitle("Bayesian updating of posterior probabilities",
             y=1.02,
             fontsize=14)

plt.tight_layout()

在结果中,我们用曲线表示了我们的后验概率,曲线越宽,我们的不确定性越大。从上图中我们可以看到,开始观测时,后验概率的变化很不稳定。但是,随着观测数据(抛硬币的次数)越来越多,这个概率就会越来越接近它的真实值p=0.5(图中用虚线标出)。
事实上,当我们的观察是十分极端时,比如说,抛了8次只有一次结果为正面的话,我们的分布会偏离 0.5 很多。但是随着数据的累计,我们必定可以观察到(虽然因为随机性,也不是每次都能观察到),概率值为 p=0.5 可能性会最高。

贝叶斯框架

通过贝叶斯的思想,我们可以把对某件事情发生的信念做为概率。让我们以之前的“判断程序是否存在bug”为例。在对代码进行测试之前,我们对代码发生漏洞的概率会有一个先验估计。然后,我们的代码通过了X 个测试后,我们就会相应的调整我们心里的估计,这个调整过后的新估计,就叫做后验概率。
实例:图书管理员还是农民
在《思考,快与慢》一书中有这样一个问题。史蒂文是一个害羞的人,他乐于助人,但又对其他人不太关注。他愿意将每件事情安排的合理有序,并且对工作非常细心。那么问题来了,你认为史蒂文是一个图书管理员还是一个农民呢?我想很多人都会认为史蒂文看起来更像一个图书管理员。但是这里却忽略了一个事实:男性图书管理员的人数只有男性农民的1/20 。所以从统计学的角度来说,史蒂文,更有可能是一个农民。
为什么他看起来更可能是一个农民呢?让我们把问题简化,假设世上只有两种职业:图书管理员和农民,并且农民的数量确实是图书管理员的20倍。

image.png

现在假设我们从史蒂文的邻居那里获得了史蒂文的一些评价信息,我们称之为X。那么,我们想要求的就是史蒂文为图书管理员的后验概率P(A∣X)。由贝叶斯定理可得:
image.png

其中P(X∣A)表示,史蒂文真的是图书管理员的情况下,史蒂文的邻居们所给出的某种描述的概率。换句话说,如果史蒂文真的是图书馆管理员,那么他是上面描述的那样的概率(这个概率可以通过统计得到)。这个值很可能接近于1,这里我们假设是0.95 。
P(X) 表示,任何人对史蒂文的描述和上面的描述一致的概率。
接下来,我们利用 Python 将画出先验概率和后验概率的图像,并进行比较。
首先,让我们先把我们算出来的概率,进行定义。

prior = [1/21, 20/21]  # 分别设置史蒂文为图书管理员和农民的先验概率
posterior = [0.087, 1-0.087]  # 分别设置史蒂文为图书管理员后农民的后验概率
prior, posterior

接下来,利用 Matplotlib 库,进行条形统计图的绘制。

figsize(12.5, 4)  # 设置大小,以及条形统计图条数
colours = ["#348ABD", "#A60628"]  # 设置颜色

# 画条形统计图,并且设置相应参数,如横纵坐标,标签,颜色等
plt.bar([0, .7], prior, alpha=0.70, width=0.25,
        color=colours[0], label="prior distribution",
        lw="3", edgecolor=colours[0])

plt.bar([0+0.25, .7+0.25], posterior, alpha=0.7,
        width=0.25, color=colours[1],
        label="posterior distribution",
        lw="3", edgecolor=colours[1])

plt.xticks([0.20, 0.95], ["Librarian", "Farmer"])
plt.title("Prior and posterior probabilities of Steve’s occupation")
plt.ylabel("Probability")
plt.legend(loc="upper left")

由图可以看到,无论是图书管理员还是农民,在得到条件X后,概率都发生了变化。尽管史蒂文为图书馆管理员的概率还是很小,但,确实因为听到了邻居的描述,史蒂文为图书管理员的概率才会增加的。

你可能感兴趣的:(100贝叶斯方法数据分析实战--贝叶斯理论)