2012-09-20 64 views
4

我有一个应用程序正在从netcdf文件中读取32位浮点数据,其中使用了默认的netcdf填充值,即9.96920996839e + 36。在应用中的一个特定点处的基本缩放(乘)操作从输入数据产生的FLOAT32型掩蔽阵列上执行,因此:在numpy的屏蔽阵列上执行乘法运算时出现溢出警告

x = marr * scale # or, equivalently, x = ma.multiply(marr,scale) 

此操作抛出警告“在乘法遇到溢出”,推测是因为填充值和比例的乘积超过了32位浮点数的最大值。已知掩模阵列中的其他值很小。接下来的问题是,为什么numpy甚至在输入数组中计算被掩盖的元素的产品?当然,这些应该被忽略,对吗?

碰巧,警告可以被忽略,因为输出数组中的相应值仍被标记为被屏蔽。但是知道这是否是一个numpy错误或“按设计工作”的错误会很有趣。

下面的代码段说明了这种行为。

import numpy as np 
import numpy.ma as ma 
arr = [9.96920996839e+36, 1.123, 2.345, 9.96920996839e+36] 
marr = ma.masked_values(np.array(arr, dtype='float32'), 9.96920996839e+36) 
x = marr * 128.0 

正如所料,溢流警告不一样,如果蒙面阵列的类型float64(尽管可能会,如果比例因子是足够大)出现。类似地,如果较小的填充值例如在float32的情况下使用-1.0e20。

从表面上看,当使用较大的填充值(非常接近32位f.p.值的最大值)时,numpy似乎无法识别掩码值。

TIA,
菲尔

回答

1

可能是一个错误。前一行有:

np.seterr(divide='ignore', invalid='ignore') 

它表明它被设计为处理掩码0或NaN,但不是很大的值。它应该是

np.seterr(divide='ignore', invalid='ignore', over='ignore') 

也可以处理较大的掩码值。

请注意,numpy.ma操作通常对阵列中的所有值进行操作,包括掩码值;这大概是因为效率和广播问题。

+0

感谢您的及时响应。是的,我发现了seterr函数提供的选项,尽管大概只是确定遇到数字错误时要采取的行动。正如你所建议的,可能是一个错误。 – Phil

2

接下来的问题是,为什么numpy甚至在输入数组中计算掩盖元素的产品?当然,这些应该被忽略,对吗?

唉,没有。在当前的实现中,对整个阵列应用任何操作,然后重新应用掩码。

我知道这听起来适得其反,但它是其他方法更强大和更低效的替代方案。最初,只有在适当的域上应用该操作才会很好,但是该域的计算可能会非常棘手(有一些与pow有关的巨大问题)。而且,额外的测试会让已经可怜的表演失败。

最近引入了一种新方法,其中numpy函数接受可选参数where,这可以帮助解决这个问题......但也有一些关于在C级直接引入对缺失/忽略值的支持的讨论是要走的路。

+0

非常感谢您对'引擎盖下'发生的事情的深入了解。知道这将允许我应用一些适当的防御性编码。 – Phil

+0

@Phil相信我,'np.ma'非常笨重,速度慢,需要改进,请在numpy邮件列表上发送想法和/或请求(或者通过聊天放下邮件)。但它的工作。均田。 –