Numpy Linalg规范表现奇怪(错误地)

时间:2017-03-12 10:24:57

标签: python numpy

我有一个带有几百万个条目的大型向量F,它在采用规范时会产生这种不一致的行为。

np.linalg.norm(F,2.000001)=3225.96..
np.linalg.norm(F,2)=inf
np.linalg.norm(F,1.999999)=3226.01..
np.linalg.norm(F,1)=inf
---------
np.linalg.norm(F)=inf
np.linalg.norm(F/12)=inf
np.linalg.norm(F/13)=246.25
---------
np.sum(F*F)=inf
np.sum(F*F/169)=60639
np.sum(F*F/144)=inf
---------
np.all(np.isfinite(F))=True
np.max(np.abs(F))=11
---------
F.dtype=dtype('float16')

除了某种hacky解决方案之外,有没有人知道发生了什么?

2 个答案:

答案 0 :(得分:3)

正如评论中所述,您的问题是float16太小而无法代表中间结果 - 其最大值为65504.更简单的测试用例是:

np.linalg.norm(np.float16([1000]))

为避免溢出,您可以除以最大值,然后重新乘以:

def safe_norm(x):
    xmax = np.max(x)
    return np.linalg.norm(x / xmax) * xmax

可能存在np.linalg.norm默认情况下应该为float16执行此操作的论据

答案 1 :(得分:0)

Numpy似乎还没有修复。所以,为了完整性,我的另一个(非常明显的)解决方案是计算规范

def calcNorm(vector):
    if (vector.dtype == np.float16):
        vector = vector.astype(np.float32)
    return np.linalg.norm(vector)

或者,正如我需要的那样,在规范化向量的用例中:

def normalize(vector):
    prevType = vector.dtype
    if (vector.dtype == np.float16):
        vector = vector.astype(np.float32)
    norm = np.linalg.norm(vector)
    if (norm != 0 and np.isfinite(norm)):
        vector /= norm
    return vector.astype(prevType)