Skip to main content
 首页 » 编程设计

python之规范化向量在 Numpy 中产生 nan

2025年05月04日38sxdcgaq8080

我从 scipy/numpy 得到一些奇怪的行为,我怀疑这是一个错误,但有人可能知道得更多?我有一对长数组,为了调试目的,我将它们分成长度为 2-4 的帧。我想标准化每对帧并取点积。执行此操作的代码(带有一些调试输出)是:

   tf = numpy.copy(t_frame) / norm(t_frame) 
   pf = numpy.copy(p_frame) / norm(p_frame) 
   print "OPF:" 
   print p_frame 
   print "PF: " 
   print pf 
   print "TF norm is: " + str(norm(tf)) 
   print "PF norm is: " + str(norm(pf)) 
   print numpy.dot(tf, pf) 
   return numpy.dot(tf, pf) 

这确实符合我一段时间的预期(特别是为 tf 和 pf 指定了 1 的范数)但随后我开始看到这样的行:

OPF:

[ -91 -119 -137 -132]

PF:

[ nan nan nan nan]

什么?这可以在新的 Python 窗口中正常化:

>>> p = [ -91, -119, -137, -132]  
>>> p / norm(p) 
array([-0.37580532, -0.49143773, -0.56577285, -0.54512421]) 

对于它的值(value),我尝试了 numpy.linalg.norm、scipy.linalg.norm,并定义了一个函数来返回点的平方根产品。

有什么想法吗?

更新: 感谢您的建议!我尝试将 dtype 切换为 float128 并且很遗憾地得到了类似的行为。我实际上倾向于相信这是 Python 中的错误,而不是 numpy 在这一点上:

  1. 如果这是一个简单的溢出问题,我似乎会按照给定的列表得到它。但是,如果我在新的 Python session 中执行此操作,则规范计算得很好。
  2. 我尝试自己滚动:

    def norm(v): 
       return (  sum(numpy.array(v)*numpy.array(v)))**(0.5) 
    

    这仅使用 numpy 来表示数组。我仍然遇到同样的问题,但是 稍后 在数据集中(并且没有运行时警告)。它正在执行大约 37000 次这样的计算。

  3. 我实际上是在计算两个帧的范数,一个 t_frame 和一个 p_frame。当且仅当另一个计算阻塞时,一个计算阻塞。

放在一起,我认为在 Python (2.7.9) 的内部某处存在一些奇怪的缓冲区溢出???我最终也需要这些计算速度快;所以我正在考虑切换到 Cython 进行计算。

更新 2: 我试着自己动手:

def norm(v): 
  sum = float(0) 
  for i in range(len(v)): 
    sum += v[i]**2 
  return sum**(0.5) 

然后问题就消失了。所以我猜测它是 numpy(Gentoo Linux 上的 1.9.0)中的错误。

请您参考如下方法:

看起来这是 numpy 中的一个错误。如果数组的数据类型是 np.int16,我可以重现问题:

In [1]: np.__version__ 
Out[1]: '1.9.2' 
 
In [2]: x = np.array([ -91, -119, -137, -132], dtype=np.int16) 
 
In [3]: x 
Out[3]: array([ -91, -119, -137, -132], dtype=int16) 
 
In [4]: np.linalg.norm(x) 
/Users/warren/anaconda/lib/python2.7/site-packages/numpy/linalg/linalg.py:2061: RuntimeWarning: invalid value encountered in sqrt 
  return sqrt(sqnorm) 
Out[4]: nan 

问题也出现在numpy开发版的master分支。我在这里创建了一个问题:https://github.com/numpy/numpy/issues/6128

如果 p_frame 实际上是一个 16 位整数数组,一个简单的解决方法如下:

x = np.asarray(p_frame, dtype=np.float64) 
pf = x / norm(x)