Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 人口蒙特卡罗实现_Python_Montecarlo_Approximation_Mcmc - Fatal编程技术网

Python 人口蒙特卡罗实现

Python 人口蒙特卡罗实现,python,montecarlo,approximation,mcmc,Python,Montecarlo,Approximation,Mcmc,我正试图使用Python为一个简单的模型(参见函数model())实现本文(参见第78页图3)中描述的人口蒙特卡罗算法,该模型只有一个参数。不幸的是,这个算法不起作用,我也不知道出了什么问题。请参阅下面我的实现。实际函数称为abc()。所有其他函数都可以视为辅助函数,并且似乎工作良好 为了检查算法是否有效,我首先生成观测数据,将模型的唯一参数设置为param=8。因此,ABC算法产生的后验值应以8为中心。事实并非如此,我想知道为什么 如有任何帮助或意见,我将不胜感激 # imports fro

我正试图使用Python为一个简单的模型(参见函数
model()
)实现本文(参见第78页图3)中描述的人口蒙特卡罗算法,该模型只有一个参数。不幸的是,这个算法不起作用,我也不知道出了什么问题。请参阅下面我的实现。实际函数称为
abc()
。所有其他函数都可以视为辅助函数,并且似乎工作良好

为了检查算法是否有效,我首先生成观测数据,将模型的唯一参数设置为param=8。因此,ABC算法产生的后验值应以8为中心。事实并非如此,我想知道为什么

如有任何帮助或意见,我将不胜感激

# imports

from math import exp
from math import log
from math import sqrt
import numpy as np
import random
from scipy.stats import norm


# globals
N = 300              # sample size
N_PARTICLE = 300      # number of particles
ITERS = 5            # number of decreasing thresholds
M = 10               # number of words to remember
MEAN = 7             # prior mean of parameter
SD = 2               # prior sd of parameter


def model(param):
  recall_prob_all = 1/(1 + np.exp(M - param))
  recall_prob_one_item = np.exp(np.log(recall_prob_all) / float(M))
  return sum([1 if random.random() < recall_prob_one_item else 0 for item in range(M)])

## example
print "Output of model function: \n" + str(model(10)) + "\n"

# generate data from model
def generate(param):
  out = np.empty(N)
  for i in range(N):
    out[i] = model(param)
  return out

## example

print "Output of generate function: \n" + str(generate(10)) + "\n"


# distance function (sum of squared error)
def distance(obsData,simData):
  out = 0.0
  for i in range(len(obsData)):
    out += (obsData[i] - simData[i]) * (obsData[i] - simData[i])
  return out

## example

print "Output of distance function: \n" + str(distance([1,2,3],[4,5,6])) + "\n"


# sample new particles based on weights
def sample(particles, weights):
  return np.random.choice(particles, 1, p=weights)

## example

print "Output of sample function: \n" + str(sample([1,2,3],[0.1,0.1,0.8])) + "\n"


# perturbance function
def perturb(variance):
  return np.random.normal(0,sqrt(variance),1)[0]

## example 

print "Output of perturb function: \n" + str(perturb(1)) + "\n"

# compute new weight
def computeWeight(prevWeights,prevParticles,prevVariance,currentParticle):
  denom = 0.0
  proposal = norm(currentParticle, sqrt(prevVariance))
  prior = norm(MEAN,SD)
  for i in range(len(prevParticles)):
    denom += prevWeights[i] * proposal.pdf(prevParticles[i])
  return prior.pdf(currentParticle)/denom


## example 

prevWeights = [0.2,0.3,0.5]
prevParticles = [1,2,3]
prevVariance = 1
currentParticle = 2.5
print "Output of computeWeight function: \n" + str(computeWeight(prevWeights,prevParticles,prevVariance,currentParticle)) + "\n"


# normalize weights
def normalize(weights):
  return weights/np.sum(weights)


## example 

print "Output of normalize function: \n" + str(normalize([3.,5.,9.])) + "\n"


# sampling from prior distribution
def rprior():
  return np.random.normal(MEAN,SD,1)[0]

## example 

print "Output of rprior function: \n" + str(rprior()) + "\n"


# ABC using Population Monte Carlo sampling
def abc(obsData,eps):
  draw = 0
  Distance = 1e9
  variance = np.empty(ITERS)
  simData = np.empty(N)
  particles = np.empty([ITERS,N_PARTICLE])
  weights = np.empty([ITERS,N_PARTICLE])

  for t in range(ITERS):
    if t == 0:
      for i in range(N_PARTICLE):
        while(Distance > eps[t]):
          draw = rprior()
          simData = generate(draw)
          Distance = distance(obsData,simData)

        Distance = 1e9
        particles[t][i] = draw
        weights[t][i] = 1./N_PARTICLE

      variance[t] = 2 * np.var(particles[t])
      continue


    for i in range(N_PARTICLE):
      while(Distance > eps[t]):
        draw = sample(particles[t-1],weights[t-1])
        draw += perturb(variance[t-1])
        simData = generate(draw)
        Distance = distance(obsData,simData)

      Distance = 1e9
      particles[t][i] = draw
      weights[t][i] = computeWeight(weights[t-1],particles[t-1],variance[t-1],particles[t][i])


    weights[t] = normalize(weights[t])  
    variance[t] = 2 * np.var(particles[t])

  return particles[ITERS-1]



true_param = 9
obsData = generate(true_param)
eps = [15000,10000,8000,6000,3000]
posterior = abc(obsData,eps)
#print posterior
#导入
从数学导入exp
从数学导入日志
从数学导入sqrt
将numpy作为np导入
随机输入
从scipy.stats导入norm
#全球的
N=300#样本量
N_粒子=300#粒子数
ITERS=5#递减阈值数
M=10#要记住的单词数
平均值=7#参数的先验平均值
SD=2#参数的优先SD
def型号(参数):
回忆所有问题=1/(1+np.exp(M-param))
召回一个项目=np.exp(np.log(召回所有问题)/float(M))
返回和([1 if random.random()eps[t]):
draw=rprior()
simData=生成(绘制)
距离=距离(obsData、simData)
距离=1e9
粒子[t][i]=牵引
权重[t][i]=1./N_粒子
方差[t]=2*np.var(粒子[t])
持续
对于范围内的i(N_粒子):
而(距离>eps[t]):
抽取=样品(颗粒[t-1],重量[t-1])
绘制+=扰动(方差[t-1])
simData=生成(绘制)
距离=距离(obsData、simData)
距离=1e9
粒子[t][i]=牵引
权重[t][i]=计算权重(权重[t-1],粒子[t-1],方差[t-1],粒子[t][i])
权重[t]=标准化(权重[t])
方差[t]=2*np.var(粒子[t])
返回粒子[ITERS-1]
真参数=9
obsData=生成(真参数)
每股收益=[1500010000800060003000]
后部=abc(obsData,eps)
#印后

我在寻找PMC算法的pythonic实现时偶然发现了这个问题,因为,非常巧合的是,我目前正在将本文中的技术应用到我自己的研究中

你能公布你得到的结果吗?我的猜测是1)你使用的距离函数(和/或相似性阈值)选择不当,或者2)你没有使用足够的粒子。这里我可能错了(我不太熟悉样本统计),但你的距离函数暗示我随机抽取的顺序很重要。我需要更多地考虑这一点,以确定它是否真的对收敛性有任何影响(可能没有),但为什么不简单地使用平均值或中值作为样本统计

我使用1000个粒子和8的真实参数值运行代码,同时使用样本平均值之间的绝对差值作为我的距离函数,以[0.5,0.3,0.1]的ε进行三次迭代;我估计的后验分布的峰值似乎接近8,就像每次迭代时应该达到的那样,同时总体方差也在减小。请注意,仍然存在明显的向右偏移,但这是因为模型的不对称性(8或更小的参数值永远不会导致超过8次观察到的成功,而所有大于8的参数值都可能导致分布向右倾斜)

下面是我的结果图:

I