MATLAB:使用bsxfun加速离散函数



对于当前项目,我必须将准连续值离散到由某些预定义的分箱分辨率定义的分箱中。为此,我编写了一个函数,我希望它非常高效,因为它既可以处理标量输入,也可以使用bsxfun处理向量输入。然而,经过一些分析后,我发现我的大项目的几乎所有处理时间都是在这个函数中产生的,并且在函数中,主要是bsxfun部分花费时间,最小查询排在第二位。长话短说,我正在寻找关于如何在MATLAB中更快地解决此任务的建议。旁注:我通常传递大约有50k个元素的向量。

代码如下:

function sampleNo = value2sample(value,bins)
%Make sure both vectors have orientations fitting bsxfun
value = value(:);
bins = bins(:)';
%Recover bin resolution (avoids passing another parameter)
delta = median(diff(bins));
%Calculate distance matrix between all combinations
dist = abs(bsxfun(@minus,value,bins));
%What we really want to know is the minimum distance per row
[minval,ind] = min(dist,[],2);
%Make sure we don't accidentally further process NaNs as 1st bin
ind(isnan(minval))=NaN;
sampleNo = ind;
sampleNo(minval>delta) = NaN;
end

你的函数之所以慢是因为你计算valuesbins的每个元素之间的距离,并将它们全部存储在一个数组中——如果有N值和M bin,那么你将需要NM元素来存储所有的距离,这可能是一个非常大的数字(例如,如果每个输入有50,000个元素,那么你需要25亿个元素在输出数组中)。

此外,由于您的箱子是排序的(您没有说明这一点,但看起来您在代码中假设了这一点),您不需要计算从每个值到每个箱子的距离。你可以更聪明,

function ind = value2sample(value, bins)
    % Find median bin distance
    delta = median(diff(bins));
    % Bucket into 'nearest' bin by using midpoints
    bins = bins(:);
    mids = [-Inf; 0.5 * (bins(1:end-1) + bins(2:end))];
    [~, ind] = histc(value, mids);
    % Ensure that NaN values and points that aren't near any bin are returned as NaN
    ind(isnan(value)) = NaN;
    ind(abs(value - bins(ind)) > delta) = NaN;
end

在我的测试中,使用values = randn(10000, 1)bins = -50:50,运行原始函数需要大约4.5毫秒,运行上面的代码需要485微秒,因此您可以获得大约10倍的加速(并且随着输入大小的增加,加速将会更大)。

感谢@Chris Taylor,我能够非常有效地解决这个问题。代码现在的运行速度几乎是以前的400倍。我对他的版本所做的唯一更改反映在下面的代码中。主要问题是将histc(不再鼓励使用)替换为discretize

function ind = value2sample(value, bins)
% Make sure the vectors are standing
value = value(:);
bins = bins(:);
% Bucket into 'nearest' bin by using midpoints
mids = [eps; 0.5 * (bins(1:end-1) + bins(2:end))];
ind = discretize(value, mids);

唯一的问题是,在这个实现中,您的bin必须是非负的。除此之外,这段代码完全符合我的要求,包括indvalue具有相同的大小,并且在valueNaN或超出bins范围时包含NaNs

相关内容

  • 没有找到相关文章

最新更新