Vectorize函数,用于查找最近值的数组

时间:2017-05-10 04:34:31

标签: matlab math vector octave vectorization

我仍在围绕矢量化,我正在努力解决我所做的以下功能......

for i = 1:size(X, 1)
  min_n = inf;
  for j=1:K
    val = X(i,:)' - centroids(j,:)';
    diff = val'*val;
    if (diff < min_n)
      idx(i) = j;
      min_n = diff;
    end
  end
end

X是一个(x,y)坐标数组......

2    5
5    6
...
...
此示例中的

centroids限制为3行。它也是(x,y)格式,如上所示。

对于X中的每一对,我正在计算最接近的centroids对。然后我将质心的索引存储在idx

所以idx(i) = j表示我将质心的索引j存储在索引i,其中i对应于X的索引。这意味着与X(i, :)配对的最近质心位于idx(i)

我可以通过矢量化来简化这个吗?我很难对内循环进行矢量化。

2 个答案:

答案 0 :(得分:4)

以下是三个选项。但请注意,与双循环相比,向量化的缺点是它一次存储所有差异运算结果,这意味着如果矩阵有很多行,则可能会耗尽内存。另一方面,矢量化方法可能要快得多。

选项1

如果您有权访问Statistics and Machine Learning Toolbox,则可以使用函数pdist2来获取两个矩阵之间的所有成对距离。然后,min函数为您提供结果每列的最小值。它的第一个返回值是最小值,第二个是索引,这是idx所需的值:

diff = pdist2(centroids,X);
[~,idx] = min(diff);

选项2

如果您无权访问工具箱,则可以使用bsxfun。这将允许您计算两个矩阵之间的差异运算,即使它们的尺寸不一致。您需要做的就是使用shiftdim重塑X',使其大小为[1,size(X,2),size(X,1)],然后reshapedXcentroids与其尺寸兼容(请参阅bsxfun)的文档。这使您可以获取它们的值之间的差异。结果是一个三维数组,您需要沿第二维求和,以获得行之间差异的范数。此时,您可以按照选项1进行操作。

reshapedX = shiftdim(X',-1);
diff = bsxfun(@minus,centroids,reshapedX);
diff = squeeze(sum(diff.^2,2));
[~,idx] = min(diff);

注意:从Matlab版本2016b开始,the bsxfun is used implicitly并且您不再需要调用它。因此,bsxfun行可以替换为更简单的行diff = centroids-reshapedX

选项3

使用功能dsearchn,它完全符合您的需要:

idx = dsearchn(centroids,X);

答案 1 :(得分:3)

可以使用pdist2 - 两个矩阵的行之间的成对距离来完成:

% random data
X = rand(500,2);
centroids = rand(3,2);
% pairwise distances
D = pdist2(X,centroids);
% closest centroid index for each X coordinates
[~,idx] = min(D,[],2)
% plot
scatter(centroids(:,1),centroids(:,2),300,(1:size(centroids,1))','filled');
hold on;
scatter(X(:,1),X(:,2),30,idx);
legend('Centroids','data');

enter image description here