在Matlab中从多元定制累积分布函数中进行抽样

3
考虑一种五元累积分布函数(cdf),我称之为 F。
我希望在 Matlab 中从该 cdf 中随机抽取 5x1 向量。F 不是已经在 Matlab 中实现的 cdf (例如正态、t-student等)。具体而言,它被定义为:

enter image description here

我已经阅读了这个和其他论坛上关于如何在Matlab中从自定义概率分布函数中进行采样的多个问题/答案。然而,
1)大部分是针对单变量cdf的,例如here。想法是应用反转换采样。我的问题有点更复杂,因为我需要“反转”一个五元函数。
2)另一个选择可能是使用slicesample,如here所建议,但我不知道如何在我这种情况下编写概率密度函数的解析表达式。
3)Here还提出了另一个想法,但只适用于双变量情况。

能否请您帮我了解如何继续进行?


我不确定我是否理解了你的问题, 你说你有一个CDF,它是F(r, sigma_a, sigma_b), 然后你想从这个函数中随机采样!所以你的问题是如何制作一个随机的5x1向量r并将其提交给F?或者你的问题是如何将这个CDF转换为适当的PDF以用于自定义值的r? - Hadi
@user3285148:我发布的代码仅适用于独立概率。它正确选择了 r1、r2 和 r4,但是 r3 依赖于 r2,r5 依赖于 r4,因此这些并没有显示正确的分布。我已经修复了代码,现在变得有点复杂了,但似乎正确。 - Cris Luengo
1个回答

5

您在#3下的链接提供了解决方案的线索。它解释了当您拥有PDF时的双变量情况。在这里,我们将扩展到任意维度的情况,当您拥有CDF时。

因此,该过程如下:

  1. 计算r1的边缘CDF。
  2. 使用此边缘CDF进行随机抽样(您发布的另一个链接解释了如何执行此操作)。
  3. 计算在给定r1的情况下r2的边缘CDF。
  4. 使用此边缘CDF进行随机抽样。
  5. 计算在给定r1r2的情况下r3的边缘CDF。
  6. 等等。您看到这会导致什么结果。
请注意,如果您有一个PDF文件,则计算边际分布需要对其余变量进行积分。因此,对于r1的边缘分布需要对r2..r5进行积分,给定r1r2的边缘分布需要对r3..r5进行积分,以此类推。
当你有一个CDF时,计算边缘分布是微不足道的,因为它已经集成了PDF: r1的边缘分布是F(x,∞,∞,∞,∞)。然而,给定一个或多个变量的边缘分布需要不同的方法:给定r1r2的边缘分布需要沿着r1进行微分,给定r1r2r3的边缘分布需要沿着r1r2进行微分,等等。
可能可以通过解析法获得这些导数(这将是更有效的解决方案)。在这里,我们使用有限差分导数逼近(这使得插入任何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个变量r1..r5组成的函数F。我发现PDF的定义域在所有维度上都相同,我找到了一个比实际需要稍微大一点的区域(lims)。接下来,我通过调用sample_random从分布F中获取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的值,最大值会减小;当ii==1时,最大值为1),并使用这个随机值插值到反向采样的边缘CDF中(反向简单地意味着交换x和y)。我需要从marginal中删除重复的值,因为它成为interp1中的x,而这个函数要求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”对CDF进行采样,在点“x”处给出固定值“r(1:ii-1)”。
计算偏导数会带来一些复杂性。如果我们要计算任何一个维度的边际分布,而没有选择任何固定值,我们只需简单地执行以下操作:
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


我已经发布了一个问题,并附上了答案(但可能是我错误地实现了您的过程)。如果您有时间,请给予建议。谢谢。 - TEX
为了进行比较,我使用了预先构建的函数evrnd - TEX
@CrisLuengo:evrnd 实现了从这个分布中抽取样本 https://en.wikipedia.org/wiki/Gumbel_distribution(请参见右侧的 PDF 和 CDF 公式)。当 sigma=1 时,F = 3 个 i.i.d. Gumbel 分布的联合 CDF,其尺度为 0,位置为 1。因此,当我将 F 的每个边际分别绘制在 evrnd(0,1,N,1) 的经验 CDF 上时,应该得到相同的结果。 - TEX
我需要再想一想,抱歉。我没有预料到这个问题。我会在这个翻转的符号上发布一个问题。 - TEX
你能帮我解决这个相关问题吗?https://stackoverflow.com/questions/69290732/drawing-from-gev-cumulative-distribution-function-in-matlab - TEX
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接