比较阵列之间的距离?

时间:2011-06-17 07:13:38

标签: c# algorithm similarity

如何比较两个数组之间的相似性?说我有:

Base Array: [.5,0,0,0,.25,0,0,.25,0,0,0,0]

Array 1: [1,0,0,0,1,0,0,1,0,0,0,0]
Array 2: [0,0,1,0,0,0,1,0,0,1,0,0]
Array 3: [1,0,0,0,0,0,0,0,0,0,0,0]

关于上面的数组,答案应该是数组1.答案是数组1,因为数组元素在结构上“更接近”基数组的数组元素。与数组3不同,.25更接近1而不是0.另一个例子:

Base Array: [.75,0,0,0,0,0,0,0,.25,0,0,0]

Array 1: [1,0,0,0,1,0,0,1,0,0,0,0]
Array 2: [0,0,1,0,0,0,1,0,0,1,0,0]
Array 3: [1,0,0,0,0,0,0,0,0,0,0,0]

在这种情况下,阵列3应该是答案。

然而,使用我当前的算法(我稍后会给出),答案就变成了阵列3.这就是我正在使用的:

for (int i = 0; i < basearray.Length; i++)
{
  temp = (basearray[i] - arrayX[i]);
  dist += temp * temp;
}

所以,我认为我的算法出了问题?或许,我需要使用'不同'的算法而不是距离(因为基本上,.25 IS接近0比1,但我想要的是其他)。

谢谢!

更新:

我找到了答案!感谢所有人的帮助。这是:

float[] pbaseArrX = new float[3];
float[] pcompArrX = new float[3];

float dist1 = 0, dist2 = 0;

for (int i = 0; i < baseArrX.Count; i++)
{
  pbaseArrX[i] = baseArrX[i] / (baseArrX[0] + baseArrX[1] + baseArrX[2]);
}

//Do the following for both compArr1 and compArr2;
for (int i = 0; i < compArrX.Count; i++)
{
  pcompArrX[i] = pcompArrX[i] / (pcompArrX[0] + pcompArrX[1] + pcompArr[2]);
}

//Get distance for both
for (int i = 0; i < pcompArrX.Count; i++)
{
  distX = distX + ((pcompArrX[i] - pbaseArrX[i])^2);
}

//Then just use conditional to determine which is 'closer'

4 个答案:

答案 0 :(得分:5)

似乎你想将数组比作光线(只是方向),但你将它们作为矢量(方向和幅度)进行比较。我建议将数组与cosine similarity进行比较,{{3}}只是矢量之间角度的余弦,因此只比较它们的方向。对于所呈现的阵列,基本阵列和阵列1之间的余弦相似度为0.94,而阵列2的余弦相似度为0.82,符合您的预期。

答案 1 :(得分:4)

数组3是正确的答案。您正在使用的算法为您提供了正确的结果。

基本上,对我来说,阵列3与基本阵列比Array1更相似。您正在寻找的模式是什么?你说Array1应该是结果......为什么?

距离只是通过任意数学假设来比较两个数组的一种方法,它背后没有真正的“逻辑”,但我们将它赋予它。

如果您希望结果为Array1,则:

  • 定义为什么Array1应该是逻辑术语的结果。
  • 翻译为什么Array1应该是数学公式的结果
  • 实施该配方

答案 2 :(得分:4)

这里的问题是你的“相似性”概念没有明确定义。根据数据的用例,定义相似性的方法有很多种。把你的阵列放在一边有一个简单的例子:

  • 眼镜和双筒望远镜是相似的,因为你用它们来看东西。
  • 眼镜和自行车是相似的,因为两者都由两个相互连接的圆圈组成
  • 眼镜和草是相似的,因为两者都以“G”开头,以“S”结尾

正如你所看到的,除非你确切地定义了你需要什么,否则任何东西都可以类似。人类善于在正确的任务中使用正确的相似性,但计算机无法做到这一点,除非你明确告诉它你想要什么。

暂且不说这一点,有一个常见的相似性案例,通常用于数据挖掘中的序列数据。这称为余弦距离,与您使用的距离没有什么不同。它被称为余弦距离。这是算法:

for (int i = 0; i < basearray.Length; i++)
{
  temp += (basearray[i] * arrayX[i]);
  f_base += (basearray[i] * basearray[i]);
  f_array += (array[i] * array[i]);
}
dist = 1 - (temp / sqrt( f_base * f_array ));

这基本上只是计算两个数组之间的“角度”,描述为n维空间中的点。在大多数情况下工作得很好,可以很容易地用于其他需求(当需要其他类型的相似性时)。

答案 3 :(得分:2)

在数学上,每个数组都是一个点the distance measure is called a norm。您正在使用欧几里德范数的一个版本,这是我们在三维空间距离的标准度量。它只是缺少平方根,因为所有你感兴趣的是哪一个最接近而不是测量实际距离所以它仍然适合你。

在你的例子中,第三个数组在欧几里德距离中绝对是最接近的,因为你的基本数组比第一个数组更接近零数组。它们可能具有“相似的结构”,但你却以错误的方式看待它。您的距离测量对数字距离感兴趣,0(在数组3中)更接近0.25而不是1(在数组1中)。

如果您正在查看“结构”,则表示您认为0比任何其他数字更重要。即你想要奖励一个匹配的数组,以便在同一个地方有非零值,而不是在数字上接近0。

我不确定你想要什么样的规范,说实话,这给我的印象是我们错过了你在一天结束时需要达到的目标 - 这有点困难就目前为止我们所知道的事情提出建议。