实现自定义距离函数

Implementing a custom distance function

AB是由二进制元素组成的矩阵。 A 表示为基础数据矩阵,B 是查询矩阵。 A由75个数据点组成,每个长度为10,B由50个数据点组成,每个长度为10。我想计算A中所有数据点与每个查询数据之间的距离指向 B 以应用最近邻搜索。因此,我没有使用欧几里德距离或汉明距离,而是使用了另一个度量标准:

N = 2k = length of data sampless = A(1,:)t = B(1,:)。 该代码适用于 A 中的一个数据样本和 B 中的另一个数据样本。我如何缩放以使其适用于所有基础数​​据点和所有查询数据点?

代码适用的示例

A(1,:) = [1,0,1,1,0,0,0,1,1,0]为A矩阵中的第一个样本。令B(1,:) = [1,1,0,0,1,1,1,1,0,0]为第一个查询点。

如果从A和B中抽取的样本中的元素相同,则为每个相似元素记录0,否则记录1。最终距离是1的总和。所以程序检查两个序列是否相同,设置 b 为 1 如果 所以,否则为零。有人可以展示我如何将其应用于矩阵吗?

代码

l = length(A);

D=zeros(1,l);
for i=1:l,
    if A(1,i)==B(1,i),
        D(1,i)=0;
    else 
        D(1,i)=1;
    end
end

sum=0;
for j=1:l,
    sum=sum+D(1,j);
end

if sum==0, 
    b = 1;
else 
    b = 0;
end

一行解决

这个计算可以在一行代码中完成:

D = A*B'+(1-A)*(1-B)' < size(A,2)

说明

考虑到 A 和 B 是二元的,A 处的每个样本与 B 处的每个样本之间的距离函数基本上检查每个坐标匹配的数量是否等于样本的长度。 您可以使用矩阵乘法来实现此目的。

更多描述性代码示例

将 A 和 B 定义为您在回答中提到的两个二进制矩阵:

%initializes A and B randomly
A = double(rand(75,10) > 0.5);
B = double(rand(50,10) > 0.5);
[m,n] = size(A);

A中每个样本与B中每个样本之间的距离可以计算如下:

首先,定义一个大小为75x50的矩阵D,s.t D(i,j)包含A中样本i与B中样本j的匹配数。

可以这样计算:

D = A*B' + (1-A)*(1-B)';

如果它们的匹配数量小于 n(n 是每个样本的长度),则可以通过测试每对 (i,j) 来完成最终的距离测量。如果较小,则样本不同,结果应为 1。否则应为零。这可以按如下方式完成:

finalDist = D < n ;

这就是我从你的描述中了解到的(如果我错了请纠正我) 设 A 为矩阵

A =

     0     1     0     0     1     0     0     1     0     1
     1     1     0     0     1     1     1     0     0     1
     0     1     1     0     0     1     1     0     1     1
     0     1     1     1     1     1     1     0     0     0
     1     1     0     0     0     1     0     0     1     1
     0     0     0     0     0     1     0     0     1     0
     1     0     1     0     1     0     0     1     1     0
     1     1     0     0     1     0     1     0     0     0
     1     0     1     0     0     1     0     0     1     0
     0     0     1     0     1     0     1     1     0     0

B 是

B =

     0     1     1     1     0     1     0     0     1     0
     0     1     0     1     0     0     1     1     1     1
     1     0     0     1     1     0     0     0     1     1
     0     1     0     1     1     0     0     0     1     0
     1     1     0     0     0     0     0     0     0     1
     1     1     0     1     1     1     1     1     1     0
     1     1     0     0     1     0     0     1     0     1
     0     0     1     1     0     1     1     1     0     1
     0     0     0     1     1     0     0     0     1     0
     0     1     1     0     0     0     1     1     0     1
>> C = A.*B

会给你他们之间的共同点,如果 A 有更多的行数,那么你可以做的是 A(1:size(B,1),:).*B 而不是

C =

     0     1     0     0     0     0     0     0     0     0
     0     1     0     0     0     0     1     0     0     1
     0     0     0     0     0     0     0     0     1     1
     0     1     0     1     1     0     0     0     0     0
     1     1     0     0     0     0     0     0     0     1
     0     0     0     0     0     1     0     0     1     0
     1     0     0     0     1     0     0     1     0     0
     0     0     0     0     0     0     1     0     0     0
     0     0     0     0     0     0     0     0     1     0
     0     0     1     0     0     0     1     1     0     0

在查找中如果没有匹配点b = 1 否则为0

b = ~find(sum(sum(C)))

更新:如果 D 应该像你说的那样是 75x50 那么 C 应该是

  C = A*(B.')

而不是

C = A.*B

因为起初我认为它是您代码中的点比较

您的距离度量实际上只是 L1 范数,即 sum(abs(x-y)) 所以 在 Octave 中您可以像这样使用 pdist2

pdist2(A,B,'L1')

在 MATLAB 中,您可以使用城市街区距离:

pdist2(A,B,'cityblock')

注意,定义您自己的距离度量(但 'cityblock' 是更好的主意):

pdist2(A,B,@(x,y)sum(abs(bsxfun(@minus,x,y)),2))

pdist2(A,B,@(x,y)sum(bsxfun(@xor,x,y),2))

pdist2(A,B,@(x,y)sum(bsxfun(@ne,x,y),2))

你的一个向量与另一个向量的距离可以这样计算:

distance = @(x,y)sum(x~=y)

但是您想要将 A 的所有行与 B 的所有行进行比较。 bsxfun 在这里会有用,我们只需要使用 permute 使其中一个矩阵进入三维:

D = squeeze(sum(bsxfun(@ne, permute(B, [3,2,1]),A),2))'

例如如果

A = [1,1,0;
     0,0,1;
     1,1,1];

B = [1,1,1;
     0,0,0;
     1,1,1;
     0,1,0]

然后

> D = squeeze(sum(bsxfun(@ne, permute(B, [3,2,1]),A),2))'

D =

   1   2   0
   2   1   3
   1   2   0
   1   2   2

所以列现在是 A 的行,他的行是 B 的行所以 D(2,3) 意味着比较 B(2,:)(即 [0,0,0]A(3,:)[1,1,1],因此由于所有元素都不相同,因此它们之间的距离为 3

如果您有统计工具箱,那么您可以使用我上面的 distance 函数和 pdist2

如果你想让你的代码像循环一样工作,只需分配 space,即 size(A,1) x size(B,1) 大,这样每个空间位置 (i,j) 都会给你 "distance"在行 ij 之间。

因此,做这样的事情。这是假设 A 是一个 M x d 矩阵,B 是一个 N x d 矩阵,其中 d 是特征点的总数,MN 是任意正数,表示每个元素有多少行。

b = zeros(size(A,1), size(B,1)); % Change
l = size(A,2); % Change - Total number of feature points

for ii = 1 : size(A,1) % Change
    for jj = 1 : size(B,1)
        D=zeros(1,l);
        for i=1:l,
            if A(ii,i)==B(jj,i) % Change
                D(i)=0;
            else 
                D(i)=1;
            end
        end

        sum=0;
        for j=1:l,
            sum=sum+D(j);
        end

        if sum==0, 
            b(ii,jj) = 1; % Change
        end
    end
end

这将遍历所有行组合。但是,请使用此处之前的任何答案对其进行矢量化。我只是想向您展示如何修改当前代码(如果这是您最满意的方式)。