2014-01-14 53 views
4

我有一行數據,說A = [0 1 1 1 0 0]在一行和1和0的矩陣之間採用xor的更快方法?

矩陣B包含許多行。對於一個虛擬的例子,假設它只是B = [1 1 1 0 1 0; 1 0 0 1 0 1]

我想找出A和B的一行不同的列數,然後用差異向量找出B的哪一行與A最相似。所以對於上面的例子,A​​不同於B(1,:)在第1,第4,第5列= 3總差異。 A在第1,2,3,6中與B(2,:)不同,所以我想返回索引1來表示A與B(1,:)最相似。

實際上B有〜50000行,A和B都有大約800列。我現在的代碼找到最相似的行如下:

min(sum(xor(repmat(A,B_rows,1),B),2)); 

這樣的工作,但它很慢。對於哪個功能需要這麼長時間以及如何改進它的任何見解?

回答

3

有6種或多或少類似的方法與bsxfun,很難說哪一個是最快的。

%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.
    0.0102 
    0.0087 
    0.0111 
1

聽起來就像是bsxfun命令是你需要什麼

min(sum(bsxfun(@xor, A, B),2)) 
3

使用pdist2'hamming'距離

[D I] = pdist2(A, B, 'hamming', 'Smallest', 1); 
+0

萬一它不快,至少要更容易理解。 – Jonas

+0

嗯好的,這對我來說是一個新功能。感謝所有人的回答,這非常有幫助。 – user1956609

+0

@Shai:你能解釋一下你的解決方案嗎?與其他人相比,哪個更好? (at)user1956609你選擇了最慢的,任何理由?我只是好奇:) – thewaywewalk

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) 
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矩陣B

0.0068s %thewaywewalk 
0.0092s %Matt J 
0.0077s %Luis Mendo 
0.0399s %Shai 

結果爲100次試驗和40320x8矩陣B

0.0889s %thewaywewalk 
0.1512s %Matt J 
0.4571s %Luis Mendo 
0.4578s %Shai 

bsxfun方法似乎使用匿名函數@eq是最快的,而對於這一點。

+1

您不考慮我的解決方案給出最近鄰居的輸出:距離和索引。它等於另一個電話'[D I] = min(Z);'在所有其他候選人之後。我認爲這不會從根本上改變計時結果,但可能會產生影響。此外,您可能需要考慮輸入類型的影響:設置「a – Shai

+0

+1」進行基準測試 –