我正在玩欧几里德距离度量的不同实现,我注意到我得到了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);
}
sample
和training_vector
都是长度为784的1-D数组,取自MNIST数据集。我尝试了使用相同sample
和training_vector
的所有三种方法。问题是三种不同的方法导致三种显着不同的距离(即,选项1约为1936,选项2约为1914,选项3为1382)。有趣的是,当我在选项1和2中使用sample
和training_vector
的相同参数顺序时(即将参数翻转到选项1周围),我得到了这两个选项的相同结果。但距离指标应该是对称的,对吧......?
还有什么有趣的:我将这些指标用于MNIST数据集的k-NN分类器。对于100个测试样本和2700个训练样本,我的Java实现产生了大约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)]))
这具有以下效果:
因此,这只会留下以下问题:使用SciPy时为什么结果不同(即错误?)?
答案 0 :(得分:1)
好的,我找到了解决方案:我使用pandas dtype=np.uint8
导入了训练和测试数据集。因此,sample
和training_vector
都是类型为uint8
的numpy数组。我将数据类型更改为np.float32
,现在我的所有三个选项都会给出相同的结果。我也尝试了np.uint32
,它也可以。
我不太清楚为什么,但显然,SciPy并没有给出&#34;预期&#34;使用uint8
时的结果。也许SciPy有一些内部溢出?不太确定,但至少它现在有效。感谢所有帮助过的人!