Matlab 跨两种模式的交叉对距离测量
我有个问题。我试图计算向量之间的成对距离。首先让我解释一下这个问题:我有两组向量Matlab 跨两种模式的交叉对距离测量,matlab,optimization,vector,Matlab,Optimization,Vector,我有个问题。我试图计算向量之间的成对距离。首先让我解释一下这个问题:我有两组向量X和YX有三个向量x1、x2和x3Y有三个向量y1、y2和y3。注X和Y中的向量长度分别为m和n。将数据集表示为以下图像: 我试图计算一个类似矩阵,如下所示: 。现在解释了不同的颜色编码部分-不需要计算所有标有0的单元格。我有意将其设置为100(它可以是任何值)。必须计算灰色单元格。相似性得分计算为(xi xj)+L2规范的L2规范的(yi yj) 这意味着条目是 M((x_i,y_j), (x_k,y_l)) :
X
和Y
X
有三个向量x1
、x2
和x3
Y
有三个向量y1
、y2
和y3
。注X
和Y
中的向量长度分别为m
和n
。将数据集表示为以下图像:
我试图计算一个类似矩阵,如下所示:
。现在解释了不同的颜色编码部分-不需要计算所有标有0
的单元格。我有意将其设置为100
(它可以是任何值)。必须计算灰色单元格。相似性得分计算为(xi xj)
+L2
规范的L2
规范的(yi yj)
这意味着条目是
M((x_i,y_j), (x_k,y_l)) := norm(x_i-x_k,2) + norm(y_j-y_l,2)
为此,我编写了一个基本代码:
clc;clear all;close all;
%% randomly generate data
m=3; n1=4; n2=6;
train_a_mean = rand(m,n1);
train_b_mean = rand(m,n2);
p = size(train_a_mean,1)*size(train_b_mean,1);
score_mean_ab = zeros(p,p);
%% This is to store the index variables
%% This is required for futu
idx1 = score_mean_ab;
idx2 = idx1; idx3 = idx1; idx4 = idx1;
a=1; b=1;
for i=1:size(score_mean_ab,1)
c = 1; d = 1;
for j=1:size(score_mean_ab,2)
if (a==c)
score_mean_ab(i,j) = 100;
else
%% computing distances between the different modalities and
%% summing them up
score_mean_ab(i,j) = norm(train_a_mean(a,:)-train_a_mean(c,:),2) ...
+ norm(train_b_mean(b,:)-train_b_mean(d,:),2);
end
%% saving the indices
idx1(i,j)=a; idx2(i,j)=b; idx3(i,j)=c; idx4(i,j)=d;
%% updating the values of c and d
if mod(d,size(train_a_mean,1))==0
c = c + 1;
d = 1;
else
d = d+1;
end
end
%% updating the values of a and b
if mod(b,size(train_a_mean,1))==0
a = a + 1;
b = 1;
else
b = b+1;
end
end
对于矩阵的干样本运行:我得到以下结果-
score_mean_ab =
100.0000 100.0000 100.0000 0.6700 1.6548 1.5725 0.8154 1.8002 1.7179
100.0000 100.0000 100.0000 1.6548 0.6700 1.5000 1.8002 0.8154 1.6454
100.0000 100.0000 100.0000 1.5725 1.5000 0.6700 1.7179 1.6454 0.8154
0.6700 1.6548 1.5725 100.0000 100.0000 100.0000 1.3174 2.3022 2.2200
1.6548 0.6700 1.5000 100.0000 100.0000 100.0000 2.3022 1.3174 2.1475
1.5725 1.5000 0.6700 100.0000 100.0000 100.0000 2.2200 2.1475 1.3174
0.8154 1.8002 1.7179 1.3174 2.3022 2.2200 100.0000 100.0000 100.0000
1.8002 0.8154 1.6454 2.3022 1.3174 2.1475 100.0000 100.0000 100.0000
1.7179 1.6454 0.8154 2.2200 2.1475 1.3174 100.0000 100.0000 100.0000
然而,我的代码非常慢。我进行了几次样本运行,得到了以下结果:
m=3; n1=3; n2=3;
Elapsed time is 0.000363 seconds.
m=10; n1=3; n2=3;
Elapsed time is 0.042015 seconds.
m=10; n1=1800; n2=1800;
Elapsed time is 0.230046 seconds.
m=20; n1=1800; n2=1800;
Elapsed time is 4.309134 seconds.
m=30; n1=1800; n2=1800;
Elapsed time is 23.058106 seconds.
我的问题:
m~100
和n1~2000
和n2~2000
。我自己的代码在这一点上崩溃了。有什么优化的方法可以做到这一点吗注意:向量实际上是行向量的形式,
n1
和n2
的值可能不相等。您可以使用以下方法实现此目的:
m = 3; % Number of vectors in X/Y (must have same number of vectors)
XD = squareform(pdist(X)); %// == pdist2(X,X) but faster
YD = squareform(pdist(Y)); %// == pdist2(Y,Y) but faster
M = kron(XD,ones(m,m)) + repmat(YD,m,m);
请注意,为了使
pdist
工作,X
和Y
必须作为行向量给出。另外:忽略对角块。这里有一个方法。这将计算所有条目
m = 3; %// number of (row) vectors in X and in Y
n1 = 3; %// length of vectors in X
n2 = 3; %// length of vectors in Y
X = rand(m, n1); %// random data: X
Y = rand(m, n2); %// random data: Y
[ii, jj] = ndgrid(1:m);
U = reshape(sqrt(sum((X(ii,:)-X(jj,:)).^2, 2)), m, m);
V = reshape(sqrt(sum((Y(ii,:)-Y(jj,:)).^2, 2)), m, m);
result = U(ceil(1/m:1/m:m), ceil(1/m:1/m:m)) + repmat(V, m, m);
或者您可以使用bsxfun
而不是ndgrid
:
U = sqrt(sum(bsxfun(@minus, permute(X, [1 3 2]), permute(X, [3 1 2])).^2, 3));
V = sqrt(sum(bsxfun(@minus, permute(Y, [1 3 2]), permute(Y, [3 1 2])).^2, 3));
result = U(ceil(1/m:1/m:m), ceil(1/m:1/m:m)) + repmat(V, m, m);
假设
A
astrain\u-mean
和B
astrain\u-mean
易于在代码中访问,您可以在这里使用两种方法到达最终目的地,即输出得分\u-mean\u-ab
的行最小索引数组
方法#1
该方法的基础是获得范数及其总和
,以及根据问题要求将对角线块
元素设置为所有Infs
的线性指数。下面是实现-
%// Parameter
M = m^2;
%// Get pairwise norms
nm1 = sqrt(sum(bsxfun(@minus,A,permute(A,[3 2 1])).^2,2));
nm2 = sqrt(sum(bsxfun(@minus,B,permute(B,[3 2 1])).^2,2));
%// Get sum of norms and the final values
norm_sum = bsxfun(@plus,nm1,permute(nm2,[2 1 4 3]));
%// Get "diagonal block" elements and set them to all Infs
ind1 = bsxfun(@plus,[1:m:M]',[0:m-1]*(M+1)); %//'
ind2 = bsxfun(@plus,ind1(:),[0:m-1]*m^3);
norm_sum(ind2) = Inf;
[~,min_idx] = min(reshape(norm_sum,m,M,[]),[],2);
min_idx = reshape(reshape(min_idx,m,[])',[],1);
方法#2
这种方法ab(使用)用于可能更快的解决方案。下面列出了代码-
%// Parameters
nA = size(A,2);
nB = size(B,2);
M = m^2;
%// Get the pairwise norms for both A and B
A_t = A'; %//'
norm_a = sqrt([-2*A A.^2 ones(m,nA)]*[A_t ; ones(nA,m) ; A_t.^2])
norm_a(1:m+1:end) = 0;
B_t = B'; %//'
norm_b = sqrt([-2*B B.^2 ones(m,nB)]*[B_t ; ones(nB,m) ; B_t.^2])
norm_b(1:m+1:end) = 0;
%// Norm sums
norm_sum = reshape(bsxfun(@plus,norm_a(:).',norm_b(:)),m,m,[]) %//'
%// Set the "diagonal blocks" as all Infs
norm_sum(:,:,1:m+1:M) = Inf
%// Re-arrange into the desired 2D output and get the minimum indices
out = reshape(permute(reshape(permute(norm_sum,[1 3 2]),M,m,[]),[1 3 2]),M,M);
[~,min_idx] = min(out,[],2);
请详细说明相似性分数。矩阵M((x_i,y_j),(x_k,y_l))的条目是什么?
?请将此信息添加到问题中!看起来这可以通过在这些距离上使用一个pdist2(…,'euclidean')
和一个pdist2(…,'cityblock')
来实现。我还不知道细节。另外,您没有指定数据是列向量还是行向量。@roni您的意思是输出大小为m^2 X m^2
,对吗?如果您只需要索引,我们不需要计算完整矩阵,但at是对称的(使用对称块)。。。另外:Divakar已经提供了删除这些条目的代码,您可以将其用于三种解决方案中的任何一种。@roni您是否能够测试这里列出的各种方法?确定。我看到我们使用的是相同的方法,您避免了pdist2
和kron
。有一段时间我不确定我是否正确理解了这个问题。我尝试使用“更简单”(?)函数来提高速度我在bsxfun上使用了一种稍微不同的方法来获得第四个维度:)@Divakar,当我通过bsxfun
方法写作时,我想到了这一点。我放弃了它,因为它太难了。然后我想:“我知道现在谁在做这个!”-D@roni你能自己测试一下吗?您知道您的数据大小等。您熟悉timeit
功能吗?它比tic
/toc
更好,因为计时可能squareform(pdist(…)
会节省一些时间。我想知道如何从向量生成对称矩阵。什么也找不到。