当前位置: 首页 > 知识库问答 >
问题:

从计数向量中随机选取元素

申屠洛华
2023-03-14

我目前正试图通过改变算法来优化一些MATLAB/Octave代码,但不知道如何处理一些随机性。假设我有一个整数向量V,每个元素代表一些东西的计数,在我的例子中是光子。现在,我想随机选取一些“东西”,创建一个大小相同的新向量,但要调整计数。

以下是我目前的做法:

function W = photonfilter(V, eff)
% W = photonfilter(V, eff)
% Randomly takes photons from V according to the given efficiency.
%
% Args:
%  V: Input vector containing the number of emitted photons in each
%     timeslot (one element is one timeslot). The elements are rounded
%     to integers before processing.
%  eff: Filter efficiency. On the average, every 1/eff photon will be
%       taken. This value must be in the range 0 < eff <= 1.
%  W: Output row vector with the same length as V and containing the number
%     of received photons in each timeslot.
%
% WARNING: This function operates on a photon-by-photon basis in that it
% constructs a vector with one element per photon. The storage requirements
% therefore directly depend on sum(V), not only on the length of V.

% Round V and make it flat.
Ntot = length(V);
V = round(V);
V = V(:);

% Initialize the photon-based vector, so that each element contains
% the original index of the photon.
idxV = zeros(1, sum(V), 'uint32');
iout = 1;
for i = 1:Ntot
  N = V(i);
  idxV(iout:iout+N-1) = i;
  iout = iout + N;
end;

% Take random photons.
idxV = idxV(randperm(length(idxV)));
idxV = idxV(1:round(length(idxV)*eff));

% Generate the output vector by placing the remaining photons back
% into their timeslots.
[W, trash] = hist(idxV, 1:Ntot);

这是上面描述的一个相当简单的实现。但是它有一个明显的性能缺陷:函数创建一个向量(idxV),每个光子包含一个元素。所以如果我的V只有1000个元素,但是每个元素的平均计数是10000,内部向量将有1000万元素,使得函数缓慢而沉重。

我现在想要实现的不是直接优化这个代码,而是使用其他类型的算法,可以立即计算新的计数,而不给每个光子某种“身份”。这一定是有可能的,但我就是不知道怎么做。

要求:

  • 输出向量W的元素数必须与输入向量V的元素数相同。
  • W(i)必须是一个整数,且以0为界

有没有办法实现这样的东西?理想的解决方案是只使用一个随机向量,然后使用一些概率和舍入的技巧,但到目前为止,我还没有在这方面取得任何成功。

谢谢向你问好,菲利普

共有2个答案

隗星驰
2023-03-14

根据Alexander Solovets的回答,代码现在是这样的:

function W = photonfilter(V, eff, impl=1)

Ntot = length(V);
V = V(:);

if impl == 0
  % Original "straightforward" solution.
  V = round(V);
  idxV = zeros(1, sum(V), 'uint32');
  iout = 1;
  for i = 1:Ntot
    N = V(i);
    idxV(iout:iout+N-1) = i;
    iout = iout + N;
  end;
  idxV = idxV(randperm(length(idxV)));
  idxV = idxV(1:round(length(idxV)*eff));
  [W, trash] = hist(idxV, 1:Ntot);

else
  % Monte Carlo approach.
  Nphot = sum(V);
  P = cumsum(V / Nphot);
  W = hist(lookup(P, rand(1, round(Nphot * eff))), 0:Ntot-1);

end;

只要eff不太接近1(eff=1,原始解产生W=V,而蒙特卡罗方法仍具有一定的随机性,从而违反了上限约束),结果就相当具有可比性。

在交互式倍频程外壳中测试:

octave:1> T=linspace(0,10*pi,10000);
octave:2> V=100*(1+sin(T));
octave:3> W1=photonfilter(V, 0.1, 0);
octave:4> W2=photonfilter(V, 0.1, 1);
octave:5> plot(T,V,T,W1,T,W2);
octave:6> legend('V','Random picking','Monte Carlo')
octave:7> sum(W1)
ans =  100000
octave:8> sum(W2)
ans =  100000
谭晓博
2023-03-14

你用来计算W的方法叫做蒙特卡罗方法。而且确实可以进行一些优化。一旦这样做不是计算光子指数,让我们想象一组箱子。每个箱子都有一定的概率,所有箱子的概率之和加起来等于1。我们将段[0,1]分成若干部分,其长度与料仓的概率成正比。现在,对于我们生成的[0,1]中的每个随机数,我们可以快速找到它所属的箱子。最后,我们计算箱子中的数字以获得最终结果。下面的代码说明了这个想法。

% Population size (number of photons).
N = 1000000;
% Sample size, size of V and W as well.
% For convenience of plotting, V and W are of the same size, but
% the algorithm doesn't enforce this constraint.
M = 10000;
% Number of Monte Carlo iterations, greater numbers give better quality.
K = 100000;

% Generate population of counts, use gaussian distribution to test the method.
% If implemented correctly histograms should have the same shape eventually.
V = hist(randn(1, N), M);
P = cumsum(V / sum(V));
% For every generated random value find its bin and then count the bins.
% Finally we normalize counts by the ration of N / K.
W = hist(lookup(P, rand(1, K)), M) * N / K;
% Compare distribution plots, they should be the same.
hold on;
plot(W, '+r');
plot(V, '*b');
pause
 类似资料:
  • 本文向大家介绍如何从R向量中选择随机元素?,包括了如何从R向量中选择随机元素?的使用技巧和注意事项,需要的朋友参考一下 从R向量中随机选择元素可确保无偏选择,因为在进行随机选择时,向量中的每个元素都具有由随机选择过程(特别是简单的随机采样选择过程)选择的相等概率。要从R向量中随机选择一个或多个元素,我们可以使用样本函数。 示例 在这里,由于向量x1的大小不大于样本大小500而导致错误。如果要创建一

  • 问题内容: 假设我有一个数组,我想随机选择一个元素。 最简单的方法是什么? 明显的方法是。但是也许有红宝石之类的东西?或者如果不能通过扩展创建这种方法? 问题答案: Swift 4.2及更高版本 推荐的新方法是Collection协议的内置方法:。它返回一个可选参数以避免我以前假设的空情况。 如果不创建数组并且不能保证count> 0,则应执行以下操作: Swift 4.1及以下 只是为了回答您的

  • 假设我有一个数组,我想随机选择一个元素。 最简单的方法是什么? 最明显的方法是数组[随机索引]。但可能有类似ruby的数组。示例 ?或者,如果不是,那么可以使用扩展创建这样的方法吗?

  • 问题内容: 我有一个像这样的数组: 我想从该数组中获取3个随机元素。我来自C#,但是我不确定该从哪里开始。我想我应该先对数组进行随机排序,然后再从中选择前3个项目? 我尝试使用以下扩展名将其改组: 但随后在“ shuffle()”的位置说“’()’不可转换为’[Int]’”。 为了挑选一些元素,我使用: 到目前为止看起来还不错。 如何洗牌?还是有人对此有更好/更优雅的解决方案? 问题答案: Xco

  • 我有一个数组,它只包含值1、0.5和0。 使用功能可以轻松地将0.5的值全部四舍五入,或者使用功能将值全部四舍五入。但是,我想随机决定向量中每个值是向上舍入到1还是向下舍入到0,同时保持所有和元素不变。 有没有一种方法可以做到这一点,而不会循环通过向量的每个元素?

  • 第一步是生成大量的随机数并存储它们在一个向量中。“大量”我指的是20个。在开始应该使用一个可控范围的数值,这将有益于调试,之后在增加它的规模。 接下来的函数将会使用一个参数,用来表示向量的长度。它用于申请分配一个新的向量用作存储int型数据,并且用0至upperBound-1之间的随机数填充。 apvector randomVector (int n, int upperBound) { apve