我在Matlab和Julia(使用tic,toc命令)之间进行简单的速度比较,运行带有拒绝采样的Gibbs采样器。对于Matlab,我运行了两个不同版本的代码。一个是使用内置的unifrnd(a,b),而另一个是通过调用以下函数在区间(a,b)中绘制均匀的随机数:
% Draw a uniform random sample in the interval (a,b)
function f = rand_uniform(a,b)
f = a + rand*(b - a);
end
我在Julia代码中使用了与上面相同的功能。
以1000000次迭代运行代码的结果如下:
案例1:使用unifrnd(a,b)的Matlab:
x_bar = 1.0944
y_bar = 1.1426
经过的时间是255.201619秒。
案例2:Matlab调用rand_uniform(a,b)(上面的函数):
x_bar = 1.0947
y_bar = 1.1429
经过的时间是38.704601秒。
案例3:Julia调用rand_uniform(a,b)(上面的函数):
x_bar = 1.0951446303536603
y_bar = 1.142634615899686
经过时间:3.563854193秒
显然使用unifrnd(a,b)可以减慢Matlab代码的速度,但问题是为什么?密度取自Introduction to Applied Bayesian Statistics and Estimation for Social Scientists中的一个示例,如果有人对理论均值感兴趣,mu_x = 1.095而mu_y = 1.143。
案例1:使用内置unifrnd(a,b)的Matlab代码是:
clear;
clc;
tic
% == Setting up matrices and preliminaries == %
d = 1000000; % No. of iterations
b = d*0.25; % Burn-in length. We discard 25% of the sample (not used here)
x = zeros(1,d);
x(1) = -1;
y = zeros(1,d);
y(1) = -1;
m = 25; % The constant multiplied on g(x)
count = 0; % Counting no. of iterations
% == The Gibbs sampler using rejection sampling == %
for i = 2:d
% Sample from x|y
z = 0;
while z == 0
u = unifrnd(0,2);
if ((2*u+3*y(i-1)+2) > unifrnd(0,2)*m) % Height is (1/(b-a))*m = 0.5*25 = 12.5
x(i) = u;
z = 1;
end
end
% Sample from y|x
z = 0;
while z == 0
u = unifrnd(0,2);
if ((2*x(i)+3*u+2) > unifrnd(0,2)*m)
y(i) = u;
z = 1;
end
end
%count = count+1 % For counting no. of total draws from m*g(x)
end
x_bar = mean(x)
y_bar = mean(y)
toc
案例2:调用rand_uniform(a,b)的matlab代码(上面的函数):
clear;
clc;
tic
% == Setting up matrices and preliminaries == %
d = 1000000; % No. of iterations
b = d*0.25; % Burn-in length. We discard 25% of the sample (not used here)
x = zeros(1,d);
x(1) = -1;
y = zeros(1,d);
y(1) = -1;
m = 25; % The constant multiplied on g(x)
count = 0; % Counting no. of iterations
% == The Gibbs sampler using rejection sampling == %
for i = 2:d
% Sample from x|y
z = 0;
while z == 0
u = rand_uniform(0,2);
if ((2*u+3*y(i-1)+2) > rand_uniform(0,2)*m) % Height is (1/(b-a))*m = 0.5*25 = 12.5
x(i) = u;
z = 1;
end
end
% Sample from y|x
z = 0;
while z == 0
u = rand_uniform(0,2);
if ((2*x(i)+3*u+2) > rand_uniform(0,2)*m)
y(i) = u;
z = 1;
end
end
%count = count+1 % For counting no. of total draws from m*g(x)
end
x_bar = mean(x)
y_bar = mean(y)
toc
案例3:调用rand_uniform(a,b)的Julia代码(上面的函数):
# Gibbs sampling with rejection sampling
tic()
# == Return a uniform random sample from the interval (a, b) == #
function rand_uniform(a, b)
a + rand()*(b - a)
end
# == Setup and preliminaries == #
d = 1000000 # No. of iterations
b = d*0.25 # Burn-in length. We discard 25% of the sample (not used here)
x = zeros(d)
x[1] = -1
y = zeros(d)
y[1] = -1
m = 25
# == The Gibbs sampler using rejection sampling == #
for i in 2:d
#Sample from y|x
z = 0
while z==0
u = rand_uniform(0,2)
if ((2*u+3*y[i-1]+2) > rand_uniform(0,2)*m) #Height is (1/(b-a))*m = 0.5*25 = 12.5
x[i] = u
z = 1
end
end
#Sample from x|y
z = 0
while z == 0
u = rand_uniform(0,2)
if ((2*x[i]+3*u+2) > rand_uniform(0,2)*m)
y[i] = u
z = 1
end
end
end
println("x_bar = ", mean(x))
println("y_bar = ", mean(y))
toc()