MATLAB/General CS:从多个集合中进行无需替换的采样(+跟踪未采样案例)

MATLAB/General CS:从多个集合中进行无需替换的采样(+跟踪未采样案例),matlab,computer-science,set,sampling,Matlab,Computer Science,Set,Sampling,我目前正在实现一个优化算法,它要求我在不替换多个集合的情况下进行采样。虽然我是用MATLAB编写代码的,但这本质上是一个CS问题 情况如下: 我有有限数量的集合a,B,C,每个集合都有有限但可能不同数量的元素a1,a2…a8,b1,b2…b10,c1,c2…c25。对于每个集合,我还有一个概率向量,它列出了集合中每个元素的概率,也就是说,对于集合a,P_a=[P_a1 P_a2…P_a8],其中P_a=1。我通常使用这些函数为每个集合创建一个概率母函数,给定一个0到1之间的统一数,可以从该集合中

我目前正在实现一个优化算法,它要求我在不替换多个集合的情况下进行采样。虽然我是用MATLAB编写代码的,但这本质上是一个CS问题

情况如下:

我有有限数量的集合a,B,C,每个集合都有有限但可能不同数量的元素a1,a2…a8,b1,b2…b10,c1,c2…c25。对于每个集合,我还有一个概率向量,它列出了集合中每个元素的概率,也就是说,对于集合a,P_a=[P_a1 P_a2…P_a8],其中P_a=1。我通常使用这些函数为每个集合创建一个概率母函数,给定一个0到1之间的统一数,可以从该集合中吐出一个元素,即一个函数P_Au,给定u=0.25,将选择a2

我希望在不替换集合A、B和C的情况下进行采样。每个完整样本是来自不同集合(即a1、b3、c2)的元素序列。请注意,完整样本空间是A、B和C中元素的所有排列的集合。在上面的示例中,该空间是a1、a2…a8 x b1、b2…b10 x c1、c2…c25,并且在我的空间中有8*10*25=2000个唯一的完整样本

如果我的第一个样本是a1,b3,c2,那么这并不意味着我不能再次对元素a1进行采样,这只是意味着我不能再次对整个序列a1,b3,c2进行采样。另一个恼人的部分是,我正在使用的算法要求我对我没有采样的元素的所有排列进行函数求值

我现在掌握的最好方法是跟踪抽样的病例。这是一个有点低效,因为我的采样器是被迫拒绝任何情况下,已经取样,因为我取样没有更换。然后,我对未采样的情况进行函数求值,通过使用嵌套for循环遍历每个置换ax,by,cz,并且仅在采样的情况中不包括ax,by,cz的组合时进行函数求值。同样,这有点低效,因为我必须检查每个置换ax,by,cz是否已经取样


对于这个问题,如有任何建议,我将不胜感激。特别是,我正在寻找一种无需替换的采样方法,并跟踪未采样的情况,这些情况不会明确列出完整的样本空间。我通常使用10个集合,每个集合有10个元素,因此列出完整的样本空间需要一个10^10 x 10的矩阵。我意识到这可能是不可能的,尽管找到有效的方法可以让我证明算法的真正局限性。

查看matlab文档中的函数;您只需要将其与length函数结合使用,从每个向量中选择随机条目。跟踪每个采样向量应该像将其连接到矩阵一样简单

current_values = [5 89 45];  % lets say this is your current sample set
used_values = [used_values; current_values];
% wash, rinse, repeat
你真的需要跟踪所有未取样的案例吗?即使你有一个1×1010的向量,它存储了一个真或假的值,指示排列是否被采样,这仍然需要大约10GB的存储空间,如果你试图创建一个这样大小的变量,MATLAB很可能会抛出一个错误,或者使你的整台机器突然停止

一个可供选择的方法是为已经采样的排列存储一个指示符。让我们考虑一下你的小例子:

A = 1:8;
B = 1:10;
C = 1:25;
nA = numel(A);
nB = numel(B);
nC = numel(C);
beenSampled = sparse(1,nA*nB*nC);
1×2000稀疏矩阵beenSampled开始时为空,即它包含所有零,我们将在给定索引处为每个采样排列添加一个1。我们可以使用函数获得一个新的样本排列,为我们提供新值集的a、B和C索引:

indexA = randi(nA);
indexB = randi(nB);
indexC = randi(nC);
然后,我们可以将这三个索引转换为一个唯一的线性索引,并使用以下函数进行采样:

现在我们可以测试beenSampled中的索引元素,看看它的值是1,即我们已经对它进行了采样,还是0,即它是一个新样本。如果已经对其进行了抽样,我们将重复上述寻找一组新指数的过程。一旦我们有了一个尚未取样的排列,我们就可以处理它:

while beenSampled(index)
  indexA = randi(nA);
  indexB = randi(nB);
  indexC = randi(nC);
  index = sub2ind([nA nB nC],indexA,indexB,indexC);
end
beenSampled(index) = 1;
newSample = [A(indexA) B(indexB) C(indexC)];
%# ...do your subsequent processing...
如果只对所有可能的排列中的一小部分进行采样,那么使用稀疏数组将节省大量空间。对于较小的置换总数,如上面的示例中,我可能只使用逻辑向量而不是稀疏向量

while beenSampled(index)
  indexA = randi(nA);
  indexB = randi(nB);
  indexC = randi(nC);
  index = sub2ind([nA nB nC],indexA,indexB,indexC);
end
beenSampled(index) = 1;
newSample = [A(indexA) B(indexB) C(indexC)];
%# ...do your subsequent processing...