Python-Numpy:如何减少这种成对距离代码中的舍入错误?

Python-Numpy:如何减少这种成对距离代码中的舍入错误?,python,numpy,matrix,rounding,Python,Numpy,Matrix,Rounding,我必须计算大量向量的成对加权距离。设A为m向量/n矩阵,W为1xn权向量 我的第一个函数以简单的方式计算成对距离: def weightedDistance(A,W): aff = np.zeros((len(A),len(A))) for i in range(len(A)): for j in range(len(A)): aff[i][j] = np.sum(((A[i] - A[j])**2)*W) return aff

我必须计算大量向量的成对加权距离。设A为m向量/n矩阵,W为1xn权向量

我的第一个函数以简单的方式计算成对距离:

def weightedDistance(A,W):
    aff = np.zeros((len(A),len(A)))
    for i in range(len(A)):
        for j in range(len(A)):
            aff[i][j] = np.sum(((A[i] - A[j])**2)*W)
    return aff
对于1000x2矩阵,这需要20秒以上的时间

然后我尝试了一个更快的版本,使用矩阵乘法:

这是同一1000x2矩阵的“瞬间”。然而,它在e-17级引入了一系列错误

>>> dist = desc.weightedDistanceFast(attr,(1,1))
>>> dist2 = desc.weightedDistance(attr,(1,1))
>>> np.sum(dist-dist2)
6.9155863612166586e-11
>>> len(np.where((dist-dist2 > 0))[0])
380824
在这里查看其他答案时,我还尝试使用sklearn.distance包中的wminkowski距离,但根据W的值,它从上述两个函数中产生了不同的结果

def weightedDistanceMinkowski(A,W):
    aff = sp.squareform(sp.pdist(A,metric='wminkowski',p=2,w=W))
    return aff**2
无论如何,我知道a,但是因为我要对这个距离矩阵做进一步的计算,我想知道是否有一种方法可以减少这个误差(或者,一种不太容易出错的方法可以使函数1更快)


谢谢大家!

真正的问题是你真的需要这样的精确度吗?如果没有(可能!),那就加快速度吧!如果您确实需要它,那么您可能需要更多地担心数据中的噪声而不是数字错误……如果需要,您可以通过更改数组的来提高精度,例如,
A=A.astype(np.float64)
或类似的。是什么让您如此自信地认为第一个答案是“正确”的?两者都会有舍入误差,但如果我不得不猜测的话,我希望第二个答案更接近真实的距离值
np.dot
通常调用BLAS例程,它可以利用诸如融合乘加运算之类的方法来减少所需浮点运算的总数,从而减少舍入误差。感谢大家的评论——Julien提到如果我关心这一级别的误差,我可能会遇到更大的问题,这是非常正确的。所以我想我的第0个问题应该是这些错误是否真的重要,对此我说“我还不确定”。是时候考虑一下了。至于正确性,即使在非常小的矩阵上也会出现错误,我用手检查过。这让我相信这是numpy引入的错误,但感谢您的评论!出于好奇,我仍然对答案感兴趣。我想知道雷蒂所说的是否就是它的全部。真正的问题是你真的需要那样的精确度吗?如果没有(可能!),那就加快速度吧!如果您确实需要它,那么您可能需要更多地担心数据中的噪声而不是数字错误……如果需要,您可以通过更改数组的来提高精度,例如,
A=A.astype(np.float64)
或类似的。是什么让您如此自信地认为第一个答案是“正确”的?两者都会有舍入误差,但如果我不得不猜测的话,我希望第二个答案更接近真实的距离值
np.dot
通常调用BLAS例程,它可以利用诸如融合乘加运算之类的方法来减少所需浮点运算的总数,从而减少舍入误差。感谢大家的评论——Julien提到如果我关心这一级别的误差,我可能会遇到更大的问题,这是非常正确的。所以我想我的第0个问题应该是这些错误是否真的重要,对此我说“我还不确定”。是时候考虑一下了。至于正确性,即使在非常小的矩阵上也会出现错误,我用手检查过。这让我相信这是numpy引入的错误,但感谢您的评论!出于好奇,我仍然对答案感兴趣。我不知道雷蒂所说的是否就是全部。
def weightedDistanceMinkowski(A,W):
    aff = sp.squareform(sp.pdist(A,metric='wminkowski',p=2,w=W))
    return aff**2