【发布时间】:2011-11-30 11:53:18
【问题描述】:
如果我有两个大小为 [m x n] 和 [p x n] 的矩阵 A 和 B,我想求出 B 的每一行在 A 中出现的次数的计数,例如:
>> A = rand(5,3)
A =
0.1419 0.6557 0.7577
0.4218 0.0357 0.7431
0.9157 0.8491 0.3922
0.7922 0.9340 0.6555
0.9595 0.6787 0.1712
>> B = [A(2,:); A(1,:); A(2,:); A(3,:); A(3,:); A(4,:); A(5,:)]
B =
0.4218 0.0357 0.7431
0.1419 0.6557 0.7577
0.4218 0.0357 0.7431
0.9157 0.8491 0.3922
0.9157 0.8491 0.3922
0.7922 0.9340 0.6555
0.9595 0.6787 0.1712
在这种情况下的答案是
ans =
1 2 2 1 1
虽然和这个例子不同,但总的来说 m >> p
如果 A 和 B 是向量,matlab 的 histc 可以完成这项工作,但如果 bin 是向量,则似乎没有等效项。
目前我是这样做的:
for i=1:length(B)
indices(i) = find(abs(A/B(i,:)-1) < 1e-15);
% division requires a tolerance due to numerical issues
end
histc(indices, 1:size(A,1))
ans =
1 2 2 1 1
但是由于我有很多这样的矩阵 B,并且 A 和 B 都很大,所以这非常慢。有什么想法可以改进吗?
编辑:
查看到目前为止的方法,我有以下数据:
A 7871139x3 188907336 double
B 902x3 21648 double
为了让事情变得更快,我将使用前 10 行 B
B = B(1:10,:);
请注意,对于完整的应用程序,我(目前)拥有 >10^4 个此类矩阵(最终将 >10^6 ....)
我的第一种方法:
tic, C = get_vector_index(A,B); toc
Elapsed time is 36.630107 seconds.
bdecaf 的方法(可以通过删除 if 语句并使用 L1 距离而不是 L2 距离缩短到 ~25 秒)
>> tic, C1 = get_vector_index(A,B); toc
Elapsed time is 28.957243 seconds.
>> isequal(C, C1)
ans =
1
oli 的 pdist2 方法
>> tic, C2 = get_vector_index(A,B); toc
Elapsed time is 7.244965 seconds.
>> isequal(C,C2)
ans =
1
oli的归一化方法
>> tic, C3 = get_vector_index(A,B); toc
Elapsed time is 3.756682 seconds.
>> isequal(C,C3)
ans =
1
最后我想出了另一种方法,我先搜索第一列,然后在第一列的命中中搜索第二列,递归直到列用完。这是迄今为止最快的....
N = size(A,2);
loc = zeros(size(B,1),1);
for i=1:size(B,1)
idx{1} = find(A(:,1)==B(i,1));
for k=2:N,
idx{k} = idx{k-1}(find(A(idx{k-1},k)==B(i,k)));
end
loc(i) = idx{end};
end
C = histc(loc, 1:size(A,1));
导致:
>> tic, C4 = get_vector_index(A,B); toc
Elapsed time is 1.314370 seconds.
>> isequal(C, C4)
ans =
1
另请注意,使用intersect 会慢得多:
>> tic, [~,IA] = intersect(A,B,'rows'); C5 = histc(IA,1:size(A,1)); toc
Elapsed time is 44.392593 seconds.
>> isequal(C,C5)
ans =
1
【问题讨论】:
-
顺便说一下,我意识到我当前方法中的矩阵除法也是错误的——它(几乎)有可能得到一个虚假的误报,但它会产生一个错误,因为只有在我拥有的所有情况下,A 中 B 的每个向量都有一个匹配项。
-
只是一个技术性问题 - 您输入的代码只有在 B 中的所有行在 A 中都有一行时才有效。此外,如果 A 中有两个几乎相同的行,则会出现问题。该行为也与 histc 不同。
histc分类到 最近的 垃圾箱 - 当它正好在垃圾箱中时,你就成功了。 -
还要小心使用长度——它总是返回最大的尺寸。所以如果
p<n会有麻烦。 -
抱歉,长度(B) 应该是 size(B,1) ......当我创建示例时,它悄悄出现了。
-
对于前一个,是的,我的描述可能缺少,因为在我的情况下,B 中的所有行在 A 中都有一行 - 只是 histc 将解决我在一维情况下的问题
标签: matlab histogram vectorization