A和B是由二进制元素组成的矩阵。 A表示为基础数据矩阵,B表示为查询矩阵。 A由长度为10的75个数据点组成,而B由长度为10的50个数据点组成。我想计算A中所有数据点与B中每个查询数据点之间的距离为了应用最近的邻居搜索。因此,我使用了另一个指标:
,而不是使用欧几里得距离或汉明距离。
N = 2,k = length of data samples,s = 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,则
因此,否则为零。有人可以告诉我如何将其应用于矩阵吗?
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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 |
- 您提到您的距离度量标准不是汉明距离,而是第一个for循环看起来很相似...您能澄清一下吗?汉明距离将相应元素之间不一致位置的总数相加。但是,您正在计算一致位置的总数,这是您的第一个for循环正在执行的操作。另外,您是说这段代码在两个查询向量之间起作用,并且您想扩展到矩阵吗?我想写一个更加向量化的方法,但是如果您热衷于使用循环,那我可以接受。请说清楚。
-
在解释中,您说的是"如果从A和B抽取的样本中的元素相同,则每个相似的元素记录为1,否则为0",但是在代码中,您做的却是相反的
-
请参阅我在公式中放置的已编辑问题。该代码在一个基本向量和一个查询向量之间工作。我问我如何修改它以适用于75个基本向量和50个查询向量。谢谢
一线解决方案
此计算可以在一行代码中完成:
1
| D = A*B'+ (1-A )* (1-B )' < size(A, 2) |
说明
对A和B是二进制的事实,A处的每个样本与B处的每个样本之间的距离函数基本上检查每个坐标的匹配量是否等于样本的长度。
您可以使用矩阵乘法来实现此目的。
更多描述性代码示例
将A和B定义为答案中提到的两个二进制矩阵:
A中的每个样本与B中的每个样本之间的距离可以计算如下:
首先,定义大小为75x50的矩阵D,s.t D(i,j)包含A中的样本i和B中的样本j之间的匹配数。
可以如下计算:
1
| D = A*B' + (1-A)*(1-B)'; |
如果每对(i,j)的匹配量小于n(n是每个样本的长度),则可以通过测试每对(i,j)来完成最终距离测量。如果较小,则样本将不同,结果应为1。否则应为零。可以按照以下步骤进行操作:
- 不应该是A. * B吗?
-
@Umar否。您必须将所有同意的元素加在一起,所以矩阵矩阵乘法非常适合。您上面编写的代码与矩阵矩阵乘法完全相同,但是您正在使用两个sum调用来执行此操作。
-
这是与OP中相同的距离度量吗?我的理解是,由于两个元素不同,[1,0,0,1]和[1,1,0,0]之间的距离为2,但是A*B'给出的距离仅为1,因为它基本上找到了两个向量均等于1的地方?
-
@drorco:我运行了您的代码,但抛出错误:使用*时出错*两个逻辑输入必须为标量。要计算元素时间,请改用TIMES(。*)。因此,基于错误,我使用了元素明智的乘法,但是错误也表明矩阵尺寸必须一致。我注意到的另一件事是,距离矩阵D必须是75 x 50(如您的回答所述)维度,而根据您的方法,我应该得到75 x 10
-
@Dan-谢谢,您是正确的,我相应地修改了答案。
-
@SKM-编写A = double(A)和B = double(B),它将起作用(矩阵的类型必须为double)。另外,如果仔细观察,D的大小为75 x 50
-
最后一个问题,只是想知道我的理解是否正确。您提到的解决方案是该语句的向量化版本:sum = sum D(1,j);我需要在问题中使用公式,然后使用您的解决方案,是否可以找到b,即有多少个相似的字符串?
-
@SKM如果您写D = AB \\'(1-A)*(1-B)\\'<size(A,2),则实际上得到最终结果-每个i,j对的b值。如果只写D = AB \\'(1-A)*(1-B)\\'-那么它将是第一部分的向量化(直到包含sum = sum D(1,j)的循环)
-
我明白了,所以当我将您的解决方案实现为一个大矩阵,其维数为A = 1,000,000×960,B = 1000×960时,我得到的错误=内存不足。这是因为使用了双重类型转换吗?如何应用您的解决方案,使其适用于大尺寸矩阵?
-
@SKM,您可以尝试使用uint8而不是double,但这是一个非常庞大的矩阵,因此您可能仍然没有内存。您的系统有多少内存?
如果要使代码按循环原样工作,只需分配size(A,1) x size(B,1)大的空间,以便每个空间位置(i,j)为您提供行i和j之间的"距离"。
因此,请执行以下操作。假定A是M x d矩阵,B是N x d矩阵,其中d是特征点的总数,并且M和N是表示正数的任意正数每行中都有元素的行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 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 |
这将遍历所有行组合。但是,在这里使用任何先前的答案可以将其向量化。我只是想向您展示如果您最满意的话如何修改当前代码。
您的距离指标实际上只是L1范数,即sum(abs(x-y)),因此在Octave中,您可以像这样使用pdist2:
在MATLAB中,您可以使用街区距离:
注意,要定义自己的距离度量标准(但最好使用'cityblock'):
1
| pdist2 (A,B,@ (x,y )sum(abs(bsxfun (@minus,x,y )), 2)) |
或
1
| pdist2 (A,B,@ (x,y )sum(bsxfun (@xor,x,y ), 2)) |
或
1
| pdist2 (A,B,@ (x,y )sum(bsxfun (@ne,x,y ), 2)) |
一个向量与另一个向量的距离可以这样找到:
1
| distance = @ (x,y )sum(x~=y ) |
但是,您想将A的所有行与B的所有行进行比较。 bsxfun在这里将很有用,我们只需要使用permute使其中一个矩阵进入第三维:
例如,如果
1 2 3 4 5 6 7 8
| A = [1,1,0;
0,0,1;
1,1,1];
B = [1,1,1;
0,0,0;
1,1,1;
0,1,0] |
然后
1 2 3 4 5 6 7 8
| > 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结合使用。
-
感谢你的回复。我尝试使用具有工具箱的pdist()进行操作,但是会引发错误:使用pdist2出错(第616行)计算距离函数\\'@(x,y)sum(abs(xy))\\'时出错。\\'但是, bsxfun可以工作,但是很难遵循,尤其是permute [3,2,1]命令。您能告诉我如何申请pdist吗?
-
@SKM我明天尝试pdist2。 permute就像转置的n维版本。因此,如果换位矩阵交换尺寸1和2,则我的permute版本交换1和3。因此bsxfun扩展为单凝胶尺寸,即尺寸为1的尺寸,所以我使用permute进行矩阵只有1行。因此,它扩展了行,还扩展了新的第三维,因为矩阵A在第三维中的"深度"为1。由于它在这两个维度上都在扩展,因此最终将A中的每一行与B中的每一行进行比较
-
那么,如果向量是n维的(n = 900),那么[3,2,1]可能不起作用?基本上,我使用bsxfun来获取维数大于(n)的向量的内存错误
-
@SKM尺寸更大...还是更大的尺寸?您当然没有900维矩阵。这是一维矩阵:大小为10的ones(10,1)。这是大小10 -by- 10:ones(10,10)的2D矩阵和大小10 -by- 10 -by- 10:ones(10,10,10)的3D矩阵,等等...什么A和B的实际尺寸是多少?因为使用75 -by- 10,我对内存不足错误感到非常惊讶
-
尺寸是指每个矢量的长度,其中矢量是某些对象的特征。我正在使用2个数据库-iris.mtx和GIST数据库。虹膜数据库包含2个文件-基本文件具有150个特征向量,每个特征向量的尺寸为4维,另一个文件是相同大小的真值文件。您的解决方案适用于Iris数据库。
-
GIST功能数据库是我收到错误的数据库。它包含N个对象的N个数据点的几个文件。每个数据点都是长度为960的特征向量。我问了一个问题stackoverflow.com/questions/37690080/…。在"问题"中,我使用汉明距离而不是自定义距离,因为自定义距离会引发内存不足错误。您能否看一下我链接的问题,也许您可??以更好地了解问题所在。感谢您一直以来的帮助。
-
@SKM我添加了MATLAB pdist2解决方案。 'cityblock'距离等于您想要的距离,但是我添加了如何使L1度量标准也起作用的方法。它需要一个bsxfun。
-
谢谢您,我将pdist2与cityblock一起使用了
这就是我从您的描述中了解的信息(如果我错了,请纠正我)
设A为矩阵
1 2 3 4 5 6 7 8 9 10 11 12
| 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为
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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而不是
1 2 3 4 5 6 7 8 9 10 11 12
| 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
更新:如果D像您说的那样是75x50,那么C应该是
而不是
因为首先我认为它与您的代码中的点比较
-
感谢你的回复。但是您的解决方案存在问题。矩阵C是最重要的,因为它是形式矩阵中的一个,我用变量和表示。 C矩阵应为75 x 75(如果A和B的大小相同)。 C确实具有此维度的原因是我想稍后对距离矩阵进行排序并选择最近的点。
-
这只是10的一个示例,您可以将其扩展为75 x 10和50 x 10 :)方法将是相同的
-
D应该是75x50还是75x75?
-
代码使用。*引发错误。矩阵尺寸必须在C = A(size(A,1),:)。* B行中一致
-
如果A和B的大小相同,则为75 * 75,否则为75 * 50
-
不好意思,我应该是A(1:size(B,1),:)。* B,我现在更新了chk