我从scipy / numpy得到一些奇怪的行为,我怀疑这是一个bug,但有人可能知道更好?我有一对长数组,我打破了长度为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])
为了它的价值,我尝试了numpy.linalg.norm
,scipy.linalg.norm
,并定义了一个函数来返回点积的平方根。
有什么想法吗?
更新: 谢谢你的建议!我尝试将dtype切换到float128,我很遗憾地得到类似的行为。我实际上倾向于认为它是 Python 中的一个错误,而不是此时的numpy:
我尝试自己动手:
def norm(v):
return ( sum(numpy.array(v)*numpy.array(v)))**(0.5)
这只使用numpy来表示数组。我仍然遇到相同的问题,但在数据集中以后(并且没有运行时警告)。它正在进行大约37000次这些计算。
放在一起,我认为在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中的一个bug(Gentoo Linux上的1.9.0)。
答案 0 :(得分:4)
看起来这是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)
答案 1 :(得分:1)
按照Warren的一个链接,我收到了这个警告:
In [1016]: np.linalg.norm(100000*np.ones(2).astype('int16'))
/usr/local/lib/python2.7/site-packages/numpy/linalg/linalg.py:2051: RuntimeWarning: invalid value encountered in sqrt
return sqrt(add.reduce((x.conj() * x).real, axis=None))
对于这个x2
,内部表达式是负数 - 小dtype中溢出的结果。
In [1040]: x2=100000*np.ones(2).astype('int16')
In [1041]: np.add.reduce((x2.conj()*x2).real,axis=None)
Out[1041]: -1474836480
类似于x1
:
In [1042]: x1
Out[1042]: array([ -9100, -11900, -13700, -13200], dtype=int16)
In [1043]: np.add.reduce((x1.conj()*x1).real,axis=None)
Out[1043]: -66128
如果“点”的总和对于dtype
来说太大,则可能是负数,在通过nan
时产生sqrt
。
(我在linux下使用1.8.2和1.9.0)。