我有一行数据,比如A = [0 1 1 1 0 0]
。
Matrix B包含许多行。对于一个虚拟的例子,我们说它只是B = [1 1 1 0 1 0; 1 0 0 1 0 1]
。
我想找到A和B行不同的列数,并使用该差异向量来查找哪一行B与A最相似。所以对于上面的示例,A与{{第1列,第4列,第5列中的1}} = 3总差异。 A与第2列,第2列,第3列,第6列= 4总差异中的B(2,:)不同,因此我希望返回索引1以指示A与B(1,:)最相似。
实际上B有 ~50,000行,而A和B都有 800列。我目前找到最相似行的代码如下:
B(1,:)
有效,但速度很慢。任何关于哪个功能花了这么长时间的见解以及改进它的方法?
答案 0 :(得分:3)
bsxfun
有6种或多或少类似的方法,很难说哪种方法最快。
%example data
A = [0 1 1 1 0 0];
B = perms(A); %720x6 matrix
计算相似之处:
Z = sum( bsxfun(@eq, A,B) , 2);
Z = sum( ~bsxfun(@ne, A,B) , 2);
Z = sum( ~bsxfun(@xor, A,B) , 2);
计算差异:
Z = sum( ~bsxfun(@eq, A,B) , 2);
Z = sum( bsxfun(@ne, A,B) , 2);
Z = sum( bsxfun(@xor, A,B) , 2);
Z
是一个向量,包含A
每行B
的相等/不等元素数。
每项100项试验的基准(与上述相同的顺序):
t100 =
0.0081
0.0098
0.0123
0.0102
0.0087
0.0111
答案 1 :(得分:3)
将pdist2
与'hamming'
距离
[D I] = pdist2( A, B, 'hamming', 'Smallest', 1 );
答案 2 :(得分:2)
(基准代码Thanks to Amro)
function [t] = bench()
A = [0 1 1 1 0 0];
B = perms(A);
% functions to compare
fcns = {
@() compare1(A,B);
@() compare2(A,B);
@() compare3(A,B);
@() compare4(A,B);
};
% timeit
t = zeros(4,1);
for ii = 1:100;
t = t + cellfun(@timeit, fcns);
end
end
function Z = compare1(A,B) %thewaywewalk
Z = sum( bsxfun(@eq, A,B) , 2);
end
function Z = compare2(A,B) %Matt J
Z = sum(bsxfun(@xor, A, B),2);
end
function Z = compare3(A,B) %Luis Mendo
A = logical(A);
Z = sum(B(:,~A),2) + sum(~B(:,A),2);
end
function Z = compare4(A,B) %Shai
Z = pdist2( A, B, 'hamming', 'Smallest', 1 );
end
100个试验的结果和720x6
的{{1}}矩阵:
B
100个试验的结果和0.0068s %thewaywewalk
0.0092s %Matt J
0.0077s %Luis Mendo
0.0399s %Shai
的{{1}}矩阵:
40320x8
B
方法似乎是最快的,并且使用匿名函数0.0889s %thewaywewalk
0.1512s %Matt J
0.4571s %Luis Mendo
0.4578s %Shai
。
答案 3 :(得分:1)
听起来像你需要的bsxfun命令
min(sum(bsxfun(@xor, A, B),2))
答案 4 :(得分:1)
另一种可能性,它通过索引取代xor
(不确定它是否比以前的答案更快):
A = logical(A);
min(sum(B(:,~A),2) + sum(~B(:,A),2))
或者,为了避免~
上的B
:
A = logical(A);
min(sum(B(:,~A),2) - sum(B(:,A),2)) + nnz(A)