MATLAB矢量化:计算邻域矩阵

时间:2015-02-25 11:01:54

标签: performance matlab matrix vector vectorization

给定长度为X的两个向量Yn,表示平面上的点和邻域半径rad,是否存在计算邻域的向量化方式点的矩阵?

换句话说,可以对以下内容(对于大n)循环缓慢进行矢量化:

neighborhood_mat = zeros(n, n);
for i = 1 : n
    for j = 1 : i - 1
        dist = norm([X(j) - X(i), Y(j) - Y(i)]);
        if (dist < radius)
            neighborhood_mat(i, j) = 1;
            neighborhood_mat(j, i) = 1;
        end
    end
end

2 个答案:

答案 0 :(得分:5)

方法#1

基于{p> bsxfun的方法 -

out = bsxfun(@minus,X,X').^2 + bsxfun(@minus,Y,Y').^2 < radius^2
out(1:n+1:end)= 0

方法#2

基于{p> Distance matrix calculation using matrix-multiplication的方法(可能更快) -

A = [X(:) Y(:)]
A_t = A.';  %//'
out = [-2*A A.^2 ones(n,3)]*[A_t ; ones(3,n) ; A_t.^2] < radius^2
out(1:n+1:end)= 0

方法#3

使用pdistsquareform -

A = [X(:) Y(:)]
out = squareform(pdist(A))<radius
out(1:n+1:end)= 0

方法#4

您可以像上一种方法一样使用pdist,但要避免squareform使用一些逻辑索引来获取邻域矩阵的最终输出,如下所示 -

A = [X(:) Y(:)]
dists = pdist(A)< radius

mask_lower = bsxfun(@gt,[1:n]',1:n)  %//'
%// OR tril(true(n),-1)

mask_upper = bsxfun(@lt,[1:n]',1:n)  %//'
%// OR mask_upper = triu(true(n),1)
%// OR mask_upper = ~mask_lower; mask_upper(1:n+1:end) = false;

out = zeros(n)
out(mask_lower) = dists

out_t = out'  %//'
out(mask_upper) = out_t(mask_upper)

注意:正如我们所看到的,对于上述所有方法,我们使用预分配输出。预分配的快速方法是 out(n,n) = 0 ,并基于this wonderful blog on undocumented MATLAB。这应该真正加快这些方法!

答案 1 :(得分:1)

如果您社区中的点数很少或者您使用蛮力方法在内存上运行不足,则以下方法非常有用:

如果您安装了统计工具箱,则可以查看rangesearch方法。 (免费替代品包括文件交换中的k-d tree implementations of a range search。)

rangesearch的使用很简单:

P = [X,Y];
[idx,D] = rangesearch(P, P, rad);

它返回到达范围内节点索引的单元格数组idx及其距离D

根据数据的大小,这在速度和内存方面可能是有益的。 该算法不是计算所有成对距离,而是过滤掉那些大的距离,而是构建一个名为k-d tree的数据结构,以便更有效地搜索近点。

然后,您可以使用它来构建sparse矩阵:

I = cell2mat(idx.').';
J = runLengthDecode(cellfun(@numel,idx));
n = size(P,1);
S = sparse(I,J,1,n,n)-speye(n);

(这使用this answer中的runLengthDecode函数。)


如果您的数据点没有变化,并且您想多次查询数据,也可以查看KDTreeSearcher课程。