简体   繁体   English

成对L2距离计算的优化

[英]optimization of pairwise L2 distance computations

I need help optimizing this loop. 我需要帮助优化此循环。 matrix_1 is a ( n x 2) int matrix and matrix_2 is a ( m x 2), m & n very. matrix_1是一个( n x 2)int矩阵, matrix_2是一个( m x 2), mn非常。

index_j = 1;
for index_k = 1:size(Matrix_1,1)
    for index_l = 1:size(Matrix_2,1)
        M2_Index_Dist(index_j,:) = [index_l, sqrt(bsxfun(@plus,sum(Matrix_1(index_k,:).^2,2),sum(Matrix_2(index_l,:).^2,2)')-2*(Matrix_1(index_k,:)*Matrix_2(index_l,:)'))];
        index_j = index_j + 1;
    end
 end

I need M2_Index_Dist to provide a ( (n*m) x 2) matrix with the index of matrix_2 in the first column and the distance in the second column. 我需要M2_Index_Dist以提供( (n*m) ×2)与索引矩阵matrix_2在第一列和第二列之间的距离。

Output example: 输出示例:

M2_Index_Dist = [ 1, 5.465
                  2, 56.52
                  3, 6.21
                  1, 35.3
                  2, 56.52
                  3, 0
                  1, 43.5
                  2, 9.3
                  3, 236.1
                  1, 8.2
                  2, 56.52
                  3, 5.582]

If I understand correctly, this does what you want: 如果我理解正确,这可以满足您的要求:

ind = repmat((1:size(Matrix_2,1)).',size(Matrix_1,1),1); %'// first column: index
d = pdist2(Matrix_2,Matrix_1); %// compute distance between each pair of rows
d = d(:); %// second column: distance
result = [ind d]; %// build result from first column and second column

As you see, this code calls pdist2 to compute the distance between every pair of rows of your matrices. 如您所见,此代码调用pdist2来计算矩阵的每一对行之间的距离。 By default this function uses Euclidean distance. 默认情况下,此函数使用欧几里得距离。

If you don't have pdist2 (which is part of the the Statistics Toolbox), you can replace line 2 above with bsxfun : 如果没有pdist2 (这是“统计信息工具箱”的一部分),则可以将上面的第2行替换为bsxfun

d = squeeze(sqrt(sum(bsxfun(@minus,Matrix_2,permute(Matrix_1, [3 2 1])).^2,2)));

Here's how to apply bsxfun with your formula ( ||AB|| = sqrt(||A||^2 + ||B||^2 - 2*A*B) ): 这是在您的公式中应用bsxfun的方法( ||AB|| = sqrt(||A||^2 + ||B||^2 - 2*A*B) bsxfun ||AB|| = sqrt(||A||^2 + ||B||^2 - 2*A*B) ):

d = real(sqrt(bsxfun(@plus, dot(Matrix_1,Matrix_1,2), ...
    bsxfun(@minus, dot(Matrix_2,Matrix_2,2).', 2 * Matrix_1*Matrix_2.')))).';

You can avoid the final transpose if you change your interpretation of the matrix. 如果更改矩阵的解释,则可以避免最终的转置。

Note: There shouldn't be any complex values to handle with real but it's there in case of very small differences that may lead to tiny negative numbers. 注意:不应该有处理任何复杂的价值real ,但它的存在在非常小的差异,可能会导致微小的负数的情况。


Edit: It may be faster without dot : 编辑:可能没有dot更快:

d = sqrt(bsxfun(@plus, sum(Matrix_1.*Matrix_1,2), ...
    bsxfun(@minus, sum(Matrix_2.*Matrix_2,2)', 2 * Matrix_1*Matrix_2.'))).';

Or with just one call to bsxfun : 或者只调用bsxfun

d = sqrt(bsxfun(@plus, sum(Matrix_1.*Matrix_1,2), sum(Matrix_2.*Matrix_2,2)') ...
    - 2 * Matrix_1*Matrix_2.').';

Note: This last order of operations gives identical results to you, rather than with an error ~1e-14 . 注意:这最后一个操作顺序将为您提供相同的结果,而不是出现~1e-14错误。


Edit 2: To replicate M2_Index_Dist : 编辑2:复制M2_Index_Dist

II = ndgrid(1:size(Matrix_2,1),1:size(Matrix_2,1));
M2_Index_Dist = [II(:) d(:)];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM