从Matlab中的多变量定制累积分布函数中抽样

时间:2018-06-18 11:04:41

标签: matlab random probability sampling cdf

考虑一个5变量cumulative distribution function(cdf),我称之为F.

我想在Matlab中从这个cdf中抽取随机5x1向量。 F不是已经在Matlab中实现的cdf(例如普通,t-学生等)。具体来说,它被定义为

enter image description here

我在本论坛和其他论坛上已经阅读了几个关于如何从Matlab中定制概率分布函数进行采样的问题/答案。然而,

1)它们中的大多数是用于单变量cdf,例如here。我们的想法是应用inverse transform sampling。我的问题有点复杂,因为我需要“反转”一个5变量函数。

2)另一种选择可能是建议使用slicesample here,但我不知道在我的情况下如何编写概率密度函数的解析表达式。

3)Here是另一个想法,但具体针对双变量情况。

请您帮助我了解我如何继续?

1 个答案:

答案 0 :(得分:1)

Your link under #3给出了解决方案的提示。它解释了当您拥有PDF时的双变量情况。对于CDF,在这里我们将其扩展到任意数量的尺寸。

所以过程是:

  1. 计算 r 1 的边际CDF。
  2. 使用此边际CDF抽取随机样本(another link you posted说明了如何执行此操作。)
  3. 在给定 r 1 的情况下,计算 r 2 的边际CDF。
  4. 使用此边际CDF随机抽样
  5. 在给定 r 1 r 的情况下,计算 r 3 的边际CDF 2
  6. 等等等。你知道这是怎么回事。

请注意,如果您有PDF,则计算边际分布涉及对剩余变量进行积分。因此, r 1 的边际分布需要对 r 2 进行积分。. r 5 ,给定 r 1 r 2 的边际分布需要对< em> r 3 .. r 5 等。

拥有CDF时,计算边缘分布很简单,因为它已经集成了PDF: r 1 的边缘分布为 F x ,∞,∞,∞,∞)。但是,在给定一个或多个变量的情况下获得边际分布需要区分:给定 r 1 r 2 的边际分布>需要沿 r 1 进行区分,给定 r r 3 的边际分布 1 r 2 需要区分 r 1 r < / em> 2 ,等等。

可能有可能通过分析获得这些导数(这将是更有效的解决方案)。在这里,我们改用有限差分导数近似(这使得插入任何CDF更加容易)。

让我们看一些MATLAB代码:

sigma_a = 0.5;
sigma_b = 0.3;
F = @(r1,r2,r3,r4,r5)exp(-exp(-r1) - (exp(-r2/sigma_a)+exp(-r3/sigma_a)).^sigma_a ...
                                   - (exp(-r4/sigma_b)+exp(-r5/sigma_b)).^sigma_b);

lims = [-5,10]; % This is the area along all dimensions containing 99.99% of the PDF

N = 1000;
values = zeros(N,5);
for n=1:N
   values(n,:) = sample_random(F,5,lims);
end

在这里,我为sigma_asigma_b选择了一些随机值,并使用它们来定义由5个变量F .. r1组成的函数r5。我发现PDF的范围在所有维度上都是相同的,我发现一个比实际需要的区域略大(lims)。接下来,我通过调用F从分布sample_random中获得1000个随机样本:

function r = sample_random(F,N,lims)
delta = diff(lims)/10000;
x = linspace(lims(1),lims(2),300);
r = inf(1,N);
for ii = 1:N
   marginal = get_marginal(F,r,ii,x,delta);
   p = rand * marginal(end);
   [~,I] = unique(marginal); % interp1 cannot handle duplicated points, let's remove them
   r(ii) = interp1(marginal(I),x(I),p);
end

delta是我们用于对导数进行有限差分近似的距离。 x代表F任一维度上的样本点。

我们首先将r定义为向量[inf,inf,inf,inf,inf],将其用作样本位置,并在函数结尾处包含从分布中得出的随机值。

接下来,我们遍历5个维度,在每次迭代中,给定先前维度的值(已经选取),我们对维度ii的边际分布进行采样。函数get_marginal在下面。我们在0到此边际CDF的最大值之间选择一个随机值(请注意,当r的最大值为1时,对于每个维度,我们选取​​ii==1的值时最大值会减小),我们使用该随机值可插值到反向采样的边际CDF中(反向简单意味着交换x和y)。我需要从marginal中删除重复的值,因为它变成了x中的interp1,并且此函数要求x的值是唯一的。

最后,函数get_marginal

function marginal = get_marginal(F,r,ii,x,delta)
N = length(r);
marginal = zeros(size(x));
for jj=0:2^(ii-1)-1
   rr = flip(dec2bin(jj,N)-'0');
   sign = mod(sum(rr,2),2);
   if sign == 0
      sign = 1;
   else
      sign = -1;
   end
   args = num2cell(r - delta * rr);
   args{ii} = x;
   marginal = marginal + sign * F(args{:});
end

这包含了相当多的复杂性。在给定固定值ii的情况下,它沿着给定维度x在点r(1:ii-1)采样CDF。

复杂性来自计算偏导数。如果我们要计算任意一个维度的边际分布而又未选择任何固定值,那么我们只需做

marginal = F(inf,x,inf,inf,inf);

我们选择了一个值

marginal = F(r1,x,inf,inf,inf) - F(r1-delta,x,inf,inf,inf);

(这是沿第一维的偏导数的近似值。)

get_marginal中的代码针对ii-1固定值执行此操作。这要求对这些固定值的每个以及对F移位的每个组合进行两次delta采样,总共n^2次(对于n固定值)。 dec2bin位用于获取所有这些组合。 sign确定是从运行总计中添加还是减去给定样本。 args是具有函数F的5个参数的单元格数组,元素1:ii-1是固定值,元素ii设置为x,元素ii+1:Ninf


最后,我绘制数据集values(包含从CDF随机抽取的1000个元素)的边际分布,并覆盖CDF的边际分布,以验证所有数据是否正确:

lims = [-2,5];
x = linspace(lims(1),lims(2),300);
figure
for ii=1:5
   subplot(5,1,ii)
   histogram(values(:,ii),'normalization','cdf','BinLimits',lims)
   hold on
   args = num2cell(inf(1,5));
   args{ii} = x;
   plot(x,F(args{:}))
   text(5.2,0.5,['r_',num2str(ii)])
end

marginal distributions, input and sampled