【问题标题】:Euclidean distance, different results between Scipy, pure Python, and Java欧几里得距离,Scipy、纯 Python 和 Java 之间的不同结果
【发布时间】:2018-08-08 08:36:22
【问题描述】:

我正在研究欧几里得距离度量的不同实现,我注意到我在 Scipy、纯 Python 和 Java 上得到了不同的结果。

这是我使用 Scipy(= 选项 1)计算距离的方法:

distance = scipy.spatial.distance.euclidean(sample, training_vector)

这是我在论坛中找到的 Python 实现(选项 2):

distance = math.sqrt(sum([(a - b) ** 2 for a, b in zip(training_vector, sample)]))

最后,这是我在 Java 中的实现(选项 3):

public double distance(int[] a, int[] b) {
    assert a.length == b.length;
    double squaredDistance = 0.0;
    for(int i=0; i<a.length; i++){
        squaredDistance += Math.pow(a[i] - b[i], 2.0);
    }
    return Math.sqrt(squaredDistance);
}

sampletraining_vector 都是长度为 784 的一维数组,取自 MNIST 数据集。我用相同的sampletraining_vector 尝试了所有三种方法。问题是这三种不同的方法会导致三个明显不同的距离(即,选项 1 大约在 1936 年,选项 2 大约在 1914 年,选项 3 大约在 1382 年)。有趣的是,当我在选项 1 和 2 中为 sampletraining_vector 使用相同的参数顺序时(即将参数翻转到选项 1),这两个选项的结果相同。但是距离度量应该是对称的,对吧...?

还有什么有趣的:我将这些指标用于 MNIST 数据集的 k-NN 分类器。我的 Java 实现对 100 个测试样本和 2700 个训练样本产生了大约 94% 的准确率。但是,使用选项 1 的 Python 实现只能产生大约 75% 的准确度...

您对我为什么会得到这些不同的结果有任何想法吗?如果您有兴趣,我可以在线发布两个数组的 CSV,并在此处发布链接。

我正在使用 Java 8、Python 2.7 和 Scipy 1.0.0。

编辑: 将选项 2 更改为

distance = math.sqrt(sum([(float(a) - float(b)) ** 2 for a, b in zip(training_vector, sample)]))

这有以下效果:

  • 它摆脱了 ubyte 溢出警告(我之前一定错过了这个警告......)
  • 更改选项 1 和 2 的参数顺序不再产生影响。
  • 选项 2(纯 Python)和 3(Java)的结果现在相等

那么,这只会留下以下问题:为什么使用 SciPy 时结果不同(即错误?)?

【问题讨论】:

  • 我读过你写的,但是打印 len(sample) 和 len(training_vector)
  • 我无法重现您的问题。
  • @MattTimmermans 它为两个向量返回 784
  • 在选项 2 中,尝试使用 float(a) - float(b) 而不是 a-b
  • @MattTimmermans 谢谢,这解决了大部分问题!现在只有 SciPy 解决方案不同(请参阅原始问题中的编辑)

标签: java python scipy knn euclidean-distance


【解决方案1】:

好的,我找到了解决方案:我已经使用带有 dtype=np.uint8 的 pandas 导入了训练和测试数据集。因此,sampletraining_vector 都是类型为uint8 的numpy 数组。我将数据类型更改为np.float32,现在我的三个选项都给出了相同的结果。我也试过np.uint32,效果也不错。

我不太清楚为什么,但显然,在使用 uint8 时,SciPy 并没有给出“预期”的结果。也许 SciPy 中有一些内部溢出?不太确定,但至少它现在有效。感谢所有帮助过的人!

【讨论】:

  • 谢谢!我遇到了同样的问题,因为我所有的公式都是正确的,所以我花了几个小时试图找出我的代码出了什么问题。只是为可能需要它的人添加:numpy,linalg.norm 有同样的问题。
猜你喜欢
  • 1970-01-01
  • 2011-01-29
  • 2020-01-20
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 2014-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多