【问题标题】:Generate random samples from arbitrary discrete probability density function in Matlab从 Matlab 中的任意离散概率密度函数生成随机样本
【发布时间】:2015-07-28 00:20:51
【问题描述】:

我有一个任意概率密度函数在 Matlab 中离散为矩阵,这意味着对于每对 x,y,概率存储在矩阵中: A(x,y) = 概率

这是一个 100x100 矩阵,我希望能够从该矩阵中生成二维 (x,y) 的随机样本,并且如果可能的话,还希望能够计算PDF格式。我想这样做是因为在重新采样后,我想将样本拟合到一个近似的高斯混合模型。

我一直在寻找任何地方,但我没有找到任何像这样具体的东西。我希望你能帮助我。

谢谢。

【问题讨论】:

  • 我不能给你代码。但是,如果您在文档中找不到任何内容,则可以自己实现。您只需要能够从离散分布中采样。这个Wiki-Article 展示了一些方法,有些很容易实现!如果速度不是那么重要:选择线性搜索。如果速度很重要:选择别名方法。
  • 我认为这个问题不应该在这里问。从任意 PDF 中计算均值和其他矩总是很困难的,但是如果您可以获得条件概率:x|y 和 y|x,那么您可以使用 gibbs sampling 来获得您想要的。你可以找到一个例子here

标签: matlab function probability sampling probability-density


【解决方案1】:

如果你真的有一个由A 定义的离散概率密度函数(而不是一个由A 描述的连续概率密度函数),你可以通过将你的二维问题变成一维问题来“作弊” .

%define the possible values for the (x,y) pair
row_vals = [1:size(A,1)]'*ones(1,size(A,2));  %all x values
col_vals = ones(size(A,1),1)*[1:size(A,2)];  %all y values

%convert your 2D problem into a 1D problem
A = A(:);
row_vals = row_vals(:);
col_vals = col_vals(:);

%calculate your fake 1D CDF, assumes sum(A(:))==1
CDF = cumsum(A); %remember, first term out of of cumsum is not zero

%because of the operation we're doing below (interp1 followed by ceil)
%we need the CDF to start at zero
CDF = [0; CDF(:)];

%generate random values
N_vals = 1000;  %give me 1000 values
rand_vals = rand(N_vals,1);  %spans zero to one

%look into CDF to see which index the rand val corresponds to
out_val = interp1(CDF,[0:1/(length(CDF)-1):1],rand_vals); %spans zero to one
ind = ceil(out_val*length(A));

%using the inds, you can lookup each pair of values
xy_values = [row_vals(ind) col_vals(ind)];

我希望这会有所帮助!

芯片

【讨论】:

    【解决方案2】:

    我不相信 matlab 具有生成具有任意分布的多元随机变量的内置功能。事实上,单变量随机数也是如此。但是虽然后者可以很容易地根据累积分布函数生成,但多元分布不存在 CDF,因此生成这样的数字要麻烦得多(主要问题是 2 个或更多变量具有相关性)。所以你的这部分问题远远超出了本站的范围。

    由于有一半的答案总比没有答案好,以下是如何使用 matlab 数值计算均值和更高矩的方法:

    %generate some dummy input
    xv=linspace(-50,50,101);
    yv=linspace(-30,30,100);
    [x y]=meshgrid(xv,yv);
    
    %define a discretized two-hump Gaussian distribution
    A=floor(15*exp(-((x-10).^2+y.^2)/100)+15*exp(-((x+25).^2+y.^2)/100));
    A=A/sum(A(:)); %normalized to sum to 1
    
    %plot it if you like
    %figure;
    %surf(x,y,A)
    
    %actual half-answer starts here    
    
    %get normalized pdf
    weight=trapz(xv,trapz(yv,A));
    A=A/weight; %A normalized to 1 according to trapz^2
    
    %mean
    mean_x=trapz(xv,trapz(yv,A.*x));
    mean_y=trapz(xv,trapz(yv,A.*y));
    

    因此,关键是您可以使用对trapz 的两次连续调用对矩形网格执行二重积分。这允许您计算与网格具有相同形状的任何数量的积分,但缺点是必须独立计算矢量分量。如果您只想计算可以用xy 参数化的东西(它们的大小自然与您的网格相同),那么您无需做任何额外的思考就可以相处。

    您还可以为集成定义一个函数:

    function res=trapz2(xv,yv,A,arg)
    
    if ~isscalar(arg) && any(size(arg)~=size(A))
        error('Size of A and var must be the same!')
    end
    
    res=trapz(xv,trapz(yv,A.*arg));
    
    end
    

    这样你就可以计算出类似的东西

    weight=trapz2(xv,yv,A,1);
    mean_x=trapz2(xv,yv,A,x);
    

    注意:我在示例中使用 101x100 网格的原因是对 trapz 的双重调用应该以正确的顺序执行。如果您在调用中交换xvyv,由于与A 的定义不一致,您会得到错误的答案,但如果A 是正方形,这将不明显。我建议在开发阶段避免使用对称量。

    【讨论】:

    • 对 101x100 网格而不是 100x100 网格的调用很好。在整个代码中获得正确的尺寸和形状可能非常棘手(但非常很重要)。使数组不是正方形的是一个很好的方法!
    猜你喜欢
    • 2017-05-30
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多