CompModCogPsy
  • 全书介绍和写作计划
  • 第一章 计算认知科学导论
    • 前言
    • 1.1 交叉学科三角
    • 1.2 认知科学的特点
    • 1.3 认知科学的发展历史
    • 1.4 我们为什么需要计算认知
      • 1.4.1 认知科学的基础假设:信息处理理论
      • 1.4.2 挑战与“诞生”
      • 1.4.3 计算认知的必要性
  • 第二章 计算模型基础
    • 2.1 什么是计算模型?
    • 2.2 模型选择
    • 2.3 模型拟合
    • 2.4 模型准确度
    • 2.5 模型可信度
  • 第三章 概率推断和贝叶斯理论
    • 3.1 概率基础
    • 3.2 概率推断
      • 3.2.1 似然函数
      • 3.2.2 最大似然估计
    • 3.3 贝叶斯理论
    • 3.4 拓展阅读:p值
    • 3.5 编程练习-最大似然估计
  • 第四章 心理物理学和信号检测论
    • 心理物理学基础
    • 心理物理曲线
      • 几种常见的心理物理曲线
      • 拟合心理物理曲线
    • 信号检测论
      • dprime
      • 决策标准
      • receiver operating curve (ROC)曲线和area under curve (AUC)
      • dprime和AUC的关系
      • 2AFC的应用
      • Page
    • 展望
  • 第五章 近似推断
    • 马尔科夫链蒙特卡洛采样
      • Metropolis-Hasting算法
    • 变分推断
    • 展望
  • 第六章 知觉决策
    • 模拟一个简单知觉决策
    • 模拟决策和反应时
    • 权衡反应时和正确率
    • 6.4 经典漂移扩散模型
    • 漂移扩散模型的应用
      • 基于价值的决策
      • 精神疾病的应用
      • 社会认知
    • 展望
  • 第七章 价值决策
    • 人类决策基础
    • 前景理论
    • 风险决策
    • 展望
  • 第八章 强化学习
    • 机器学习强化学习基础
      • 动态规划
      • 时间差分学习
      • 基于模型和无模型强化学习
    • 心理学的强化学习
    • 强化学习的交叉关系
    • 强化学习模型和参数估计
    • Rescorlar-wagner模型
    • 二阶段任务
    • 展望
  • 第九章 社会决策和社会学习
    • 社会决策
    • 社会学习
    • 展望
  • 第十章 神经网络
    • 神经网络和心理学引言
    • 神经网络基础
      • 多层感知机
      • 卷积神经网络
      • 循环神经网络
    • 神经网络和人脑加工的关系
      • 感知觉的编解码
      • 工作记忆
      • 长时记忆
      • 学习和决策
    • 展望
由 GitBook 提供支持
在本页
  1. 第五章 近似推断
  2. 马尔科夫链蒙特卡洛采样

Metropolis-Hasting算法

当需要进行采样的分布 p(x)p(x)p(x)比较复杂时,一种方法是借助与该分布对应的马尔科夫链状态转移函数来进行采样。那么要怎么找到该分布的状态转移函数呢?如果随便假定要给转移函数 Q(xj∣xi)Q(x_j|x_i)Q(xj​∣xi​)显然是不成立的,因为不满足细致平稳条件,即

p(xj)∗Q(xi∣xj)≠p(xi)∗Q(xj∣xi)p(x_j)*Q(x_i|x_j)\neq p(x_i)*Q(x_j|x_i)p(xj​)∗Q(xi​∣xj​)=p(xi​)∗Q(xj​∣xi​)

但我们可以对上面的式子做一个改造,使细致平稳条件成立。对于任意一个分布 p(x)p(x)p(x),以及任意一个转移函数 Q(xj∣xi)Q(x_j|x_i)Q(xj​∣xi​),我们可以构建一个新的转移函数

M(xj∣xi)=Q(xj∣xi)∗min(1,p(xj)∗Q(xi∣xj)p(xi)∗Q(xj∣xi))M(x_j|x_i)=Q(x_j|x_i)*min(1,\frac{p(x_j)*Q(x_i|x_j)}{p(x_i)*Q(x_j|x_i)})M(xj​∣xi​)=Q(xj​∣xi​)∗min(1,p(xi​)∗Q(xj​∣xi​)p(xj​)∗Q(xi​∣xj​)​)

使得细致平稳条件一定满足,即

p(xj)∗M(xi∣xj)=p(xi)∗M(xj∣xi)p(x_j)*M(x_i|x_j)= p(x_i)*M(x_j|x_i)p(xj​)∗M(xi​∣xj​)=p(xi​)∗M(xj​∣xi​)

在进行采样时,先用任意构建的 Q(xj∣xi)Q(x_j|x_i)Q(xj​∣xi​)进行采样,接着对接受概率 a(xj∣xi)=min(1,p(xj)∗Q(xi∣xj)p(xi)∗Q(xj∣xi))a(x_j|x_i)=min(1,\frac{p(x_j)*Q(x_i|x_j)}{p(x_i)*Q(x_j|x_i)})a(xj​∣xi​)=min(1,p(xi​)∗Q(xj​∣xi​)p(xj​)∗Q(xi​∣xj​)​)进行分类讨论:

当p(xj)∗Q(xi∣xj)≥p(xi)∗Q(xj∣xi)p(x_j)*Q(x_i|x_j)≥p(x_i)*Q(x_j|x_i)p(xj​)∗Q(xi​∣xj​)≥p(xi​)∗Q(xj​∣xi​),有 M(xj∣xi)=Q(xj∣xi)M(x_j|x_i) =Q(x_j|x_i)M(xj​∣xi​)=Q(xj​∣xi​)

即直接接受 Q(xj∣xi)Q(x_j|x_i)Q(xj​∣xi​)的采样;

当p(xj)∗Q(xi∣xj)<p(xi)∗Q(xj∣xi)p(x_j)*Q(x_i|x_j)<p(x_i)*Q(x_j|x_i)p(xj​)∗Q(xi​∣xj​)<p(xi​)∗Q(xj​∣xi​),有 M(xj∣xi)=Q(xj∣xi)∗p(xj)∗Q(xi∣xj)p(xi)∗Q(xj∣xi)M(x_j|x_i) =Q(x_j|x_i)*\frac{p(x_j)*Q(x_i|x_j)}{p(x_i)*Q(x_j|x_i)}M(xj​∣xi​)=Q(xj​∣xi​)∗p(xi​)∗Q(xj​∣xi​)p(xj​)∗Q(xi​∣xj​)​

此时,再以 p(xj)∗Q(xi∣xj)p(xi)∗Q(xj∣xi)\frac{p(x_j)*Q(x_i|x_j)}{p(x_i)*Q(x_j|x_i)}p(xi​)∗Q(xj​∣xi​)p(xj​)∗Q(xi​∣xj​)​的概率来决定是否接受采样。

为什么新的转移函数能保证符合细致平稳条件呢?以下是证明过程:

将 M(xj∣xi)M(x_j|x_i)M(xj​∣xi​)的构建定义代入

p(xi)∗M(xj∣xi)=p(xi)∗Q(xj∣xi)∗min(1,p(xj)∗Q(xi∣xj)p(xi)∗Q(xj∣xi))=min(p(xi)∗Q(xj∣xi),p(xj)∗Q(xi∣xj))=p(xj)∗Q(xi∣xj)∗min(p(xi)∗Q(xj∣xi)p(xj)∗Q(xi∣xj),1)=p(xj)∗M(xi∣xj)p(x_i)*M(x_j|x_i)=p(x_i)*Q(x_j|x_i)*min(1,\frac{p(x_j)*Q(x_i|x_j)}{p(x_i)*Q(x_j|x_i)})\\=min(p(x_i)*Q(xj|x_i),p(x_j)*Q(x_i|x_j))\\=p(x_j)*Q(x_i|x_j)*min(\frac{p(x_i)*Q(x_j|x_i)}{p(x_j)*Q(x_i|x_j)},1)\\= p(x_j)*M(x_i|x_j)p(xi​)∗M(xj​∣xi​)=p(xi​)∗Q(xj​∣xi​)∗min(1,p(xi​)∗Q(xj​∣xi​)p(xj​)∗Q(xi​∣xj​)​)=min(p(xi​)∗Q(xj∣xi​),p(xj​)∗Q(xi​∣xj​))=p(xj​)∗Q(xi​∣xj​)∗min(p(xj​)∗Q(xi​∣xj​)p(xi​)∗Q(xj​∣xi​)​,1)=p(xj​)∗M(xi​∣xj​)

这样我们就证明了新转换函数 M(xj∣xi)M(x_j|x_i)M(xj​∣xi​)是必定满足细致平稳条件的。需要注意的是,这里的 Q(xj∣xi)Q(x_j|x_i)Q(xj​∣xi​)可以是任意构建的转换函数(e.g.,高斯函数),上面式子恒成立。

  • Metropolis-Hasting 采样——转换函数为高斯函数实例

接下来,我们以一个高斯函数的实例来帮助更好理解。

假设目标采样分布为 p(x)=0.3∗e−(x−0.3)2+0.7∗e−(x−2.)20.31.2113p(x)=\frac{0.3 * e^{-(x-0.3)^2}+0.7*e^{-\frac{(x-2.)^2}{0.3}}}{1.2113}p(x)=1.21130.3∗e−(x−0.3)2+0.7∗e−0.3(x−2.)2​​

def p(x):
    return ((0.3 * np.exp(-(x-0.3)**2))+0.7*np.exp(-(x-2.)**2/0.3))/1.2113

要对目标分布进行采样,我们可以按照上面提到的流程进行:

  1. 构建一个高斯函数作为提议分布,如 Q(xj∣xi)=e−(xj−xi)2Q(x_j|x_i) =e^{-(x_j-x_i)^2}Q(xj​∣xi​)=e−(xj​−xi​)2

  2. 从提议分布中采样出 xjx_jxj​

  3. 计算出接受概率 a(xj∣xi)=min(1,p(xj)∗Q(xi∣xj)p(xi)∗Q(xj∣xi))a(x_j|x_i)=min(1,\frac{p(x_j)*Q(x_i|x_j)}{p(x_i)*Q(x_j|x_i)})a(xj​∣xi​)=min(1,p(xi​)∗Q(xj​∣xi​)p(xj​)∗Q(xi​∣xj​)​),由于高斯函数是对称的, Q(xj∣xi)=Q(xi∣xj)Q(x_j|x_i) =Q(x_i|x_j)Q(xj​∣xi​)=Q(xi​∣xj​),分式上下 QQQ 被约去,仅需要计算 min(1,p(xj)p(xi))min(1,\frac{p(x_j)}{p(x_i)})min(1,p(xi​)p(xj​)​)

  4. 根据接受概率和随机数,决定是否接受本次采样

nSample = 100000 #进行采样的次数
sample2 = [] #采样的集合

x = 1 # 设置采样的初始值(x_0),初始状态任意

for i in range(nSample):
    x2 = norm(loc=x).rvs() # 从提议分布(高斯)采样一个
    a = np.min([1, p(x2)/p(x)]) #接受概率,因为提议分布高斯是对称的, 所以可以上下约掉
    u = np.random.rand() # 从[0,1]均匀分布获取一个值
    if u <= a:
        sample2.append(2) # 接受并跳转到新的采样点
        x = x2
    else:
        sample2.append(x) # 保留原来的采样点不变

完成采样以后,我们可以画出分布

x = np.arange(-3., 5., 0.01)
plt.plot(x, p(x), color='r', label='p(x)')
a,_,_=plt.hist(sample2, color='k', bins=150, density=True)
plt.legend()
plt.ylabel('pdf(x)')

Metropolis-Hasting 算法在参数估计的应用

在认知心理学中,我们经常需要根据实验数据对概率模型进行参数估计,本质就是求解参数的后验概率分布 p(θ∣data)p(\theta|data)p(θ∣data)。当我们使用Metropolis-Hasting 算法对参数的后验分布进行采样时,只需要将上面的 p(x)p(x)p(x) 替换为 p(x∣data)p(x|data)p(x∣data),如此在计算接受概率时,

a(xj∣xi)=min(1,p(xj∣data)∗Q(xi∣xj)p(xi∣data)∗Q(xj∣xi))a(x_j|x_i)=min(1,\frac{p(x_j|data)*Q(x_i|x_j)}{p(x_i|data)*Q(x_j|x_i)})a(xj​∣xi​)=min(1,p(xi​∣data)∗Q(xj​∣xi​)p(xj​∣data)∗Q(xi​∣xj​)​)

由于后验分布 p(x∣data)p(x|data)p(x∣data)我们是不知道的,我们需要用贝叶斯公式将其转为可以计算的形式

a(xj∣xi)=min(1,p(data∣xj)∗p(xj)/p(data)∗Q(xi∣xj)p(data∣xi)∗p(xi)/p(data)∗Q(xj∣xi))=min(1,p(data∣xj)∗p(xj)∗Q(xi∣xj)p(data∣xi)∗p(xi)∗Q(xj∣xi))a(x_j|x_i)=min(1,\frac{p(data|x_j)*p(x_j)/p(data)*Q(x_i|x_j)}{p(data|x_i)*p(x_i)/p(data)*Q(x_j|x_i)})\\=min(1,\frac{p(data|x_j)*p(x_j)*Q(x_i|x_j)}{p(data|x_i)*p(x_i)*Q(x_j|x_i)})a(xj​∣xi​)=min(1,p(data∣xi​)∗p(xi​)/p(data)∗Q(xj​∣xi​)p(data∣xj​)∗p(xj​)/p(data)∗Q(xi​∣xj​)​)=min(1,p(data∣xi​)∗p(xi​)∗Q(xj​∣xi​)p(data∣xj​)∗p(xj​)∗Q(xi​∣xj​)​)
  • 如果我们假定的是均匀的先验分布,那么有 p(xi)=p(xj)p(x_i)=p(x_j)p(xi​)=p(xj​);

  • 如果我们假定的是对称的提议分布(比如高斯分布),那么有 Q(xj∣xi)=Q(xi∣xj)Q(x_j|x_i) =Q(x_i|x_j)Q(xj​∣xi​)=Q(xi​∣xj​)

那么上式可以进一步简化为

a(xj∣xi)=min(1,p(data∣xj)p(data∣xi))a(x_j|x_i)=min(1,\frac{p(data|x_j)}{p(data|x_i)})a(xj​∣xi​)=min(1,p(data∣xi​)p(data∣xj​)​)

可以看到,接受概率的右边就是观测数据在新采样参数与原采样参数中的似然值之比。接下来我们具体介绍一个用MH算法做参数估计的代码实例。

  • 用MH算法求解心理物理曲线的参数

Weibull函数为

y=1−(1−γ)exp−(k∗xα)βy=1-(1-\gamma)exp^{-(\frac{k*x}{\alpha})^\beta}y=1−(1−γ)exp−(αk∗x​)β

其中

k=−log(1−g1−γ)1βk=-log(\frac{1-g}{1-\gamma})^\frac{1}{\beta}k=−log(1−γ1−g​)β1​

α\alphaα为该正确率下的阈值,β\betaβ为函数的斜率,γ\gammaγ为基线概率水平的概率值, ggg为阈值对应的正确率。

# 先定义weibull函数
def weibullfun(x, alpha, beta, gamma, g):
    k = (-np.log((1-g)/(1-gamma)))**(1/beta)
    y = 1 - (1 - gamma)*np.exp(-(k*x/alpha) ** beta) # hack here to avoid the complex number of 
    return y

假设我们当前的参数组合 (α,β,γ,g)(\alpha,\beta,\gamma,g)(α,β,γ,g)的真值为(0.25,3,0.5,0.82),在实验设置的一致性水平([0.032, 0.064, 0.128, 0.256, 0.512])中对应的心理物理曲线如下,

from scipy.stats import bernoulli
# coherence level in literature
coh = np.array([0.032, 0.064, 0.128, 0.256, 0.512]) 
# 定义参数
g = 0.82
gamma = 0.5 # Baseline chance level
beta = 3. # slop steepness
alpha = 0.25 # coherence threshold corresponding to g

nTrialPerCoh = 1000 # how many trials per coh level

pCoh = weibullfun(coh, alpha, beta, gamma, g)

plt.plot(coh, pCoh, 'o-')
plt.xlabel('coherence')
plt.ylabel('Prob of correct')

我们通过伯努利随机过程根据以上心理曲线生成5000个模拟数据,五个一致性水平分别生成1000个试次,

data = np.empty((coh.size, nTrialPerCoh))
for iCoh in range(coh.size): # loop coherence level
    # use bernouli process to generate data
    data[iCoh, :] = bernoulli.rvs(pCoh[iCoh], size=nTrialPerCoh)
cohTrial = np.tile(coh[:, np.newaxis], (1, nTrialPerCoh)).flatten() #(5000, ) array
data = data.flatten() # (5000, ) array

接着,我们假定Weibull函数中的阈限 α\alphaα是需要估计的自由参数。我们使用MH算法对后验分布 p(α∣data)p(\alpha|data)p(α∣data)进行采样,选择对称的高斯分布进行提议分布,便可以使用公式 a(xj∣xi)=min(1,p(data∣xj)p(data∣xi))a(x_j|x_i)=min(1,\frac{p(data|x_j)}{p(data|x_i)})a(xj​∣xi​)=min(1,p(data∣xi​)p(data∣xj​)​)计算接受概率。此时,我们考虑直接计算似然的比值有些麻烦,可以两边取对数,改为计算两次采样参数的对数似然的差值

log(a(xj∣xi))=min(0,log(p(data∣xj))−log(p(data∣xi)))log(a(x_j|x_i))=min(0,log(p(data|x_j))-log(p(data|x_i)))log(a(xj​∣xi​))=min(0,log(p(data∣xj​))−log(p(data∣xi​)))

写出不同 α\alphaα输入相应的负对数似然函数

eps = np.finfo(float).eps #大于0的极小值,防止后续计算对数时出现0的情况
def loglikeli(alpha, coh, data):
    gamma = 0.5
    g = 0.82
    beta = 3.

    prob = np.empty(coh.size)
    for i in range(coh.size):
        p = weibullfun(coh[i], alpha, beta, gamma, g)
        prob[i] = p*data[i]+(1-p)*(1-data[i])
    
    prob = prob*0.999+eps # 避免prob里面有0的情况, log(0)=-infinity
    return -np.log(prob).sum() 
    #prob取值在(0,1],经过对数函数后会变为负数,取负的对数似然值能保证返回值是一个正数

MCMC采样从初始值0(可任意选取)开始,共采样2000次,剔除前1000次未平稳收敛的采样,保留后1000个有效样本。

from scipy.stats import norm

nSample = 1000
nBurnin = 1000
nTotalSample = nSample + nBurnin
stepsize = 1

samples = []
oldsample = 0

由于提议分布是在实数范围内进行采样,但需要估计的阈限 α\alphaα参数范围在(0,1),我们需要进行一个尺度转换,通过logistic函数可以将实数范围投射到(0,1)之中

trans_oldsample = 1/(1+np.exp(-oldsample))

每次采样时,会在均值为上一采样点的高斯分布中采样,进行尺度转换后通过负对数似然函数计算接受概率,并根据随机数决定是否接受本次采样。

for i in range(nTotalSample):
    newsample = norm.rvs(loc=oldsample,scale = stepsize)
    # 我们的参数范围在(0,1),但是我们转化到纯实数范围内采集
    trans_newsample = 1/(1+np.exp(-newsample))

    # 计算负对数似然之差
    delta = negloglikeli(trans_oldsample, cohTrial, data)-negloglikeli(trans_newsample, cohTrial, data)
    # 接受概率
    a = np.min([0,delta]) 
    #从[0,1]均匀分布随机获取一个值
    u = np.random.rand()
    
    if log(u) <= a: #接受并跳转到新的采样点
        samples.append(trans_newsample)
        trans_oldsample = trans_newsample
        oldsample = newsample
    else: #保留原来的采样点不变
        samples.append(trans_oldsample)

完成之后可以从样本计算得到所估计参数阈限 α\alphaα的均值,并画出有效采样的直方图。由于模拟数据与采样具有随机性,运行的结果可能有所不同。

print(np.mean(samples[1000:]))
plt.hist(samples[1000:], bins=20,density=True,range=[0.2,0.3])
0.24384956185678375

可以看到使用MH算法估计的参数 α\alphaα的均值,接近参数设置的真值0.25。

最后更新于8个月前