Tho*_*ard 4 python arrays random precision numpy
我有一组随机浮点数,我需要将它与另一个以不同顺序具有相同值的浮点数进行比较。就此而言,我使用总和、乘积(以及其他组合,具体取决于表格的维度,因此需要等式的数量)。
尽管如此,当我根据值的顺序对数组执行总和(或乘积)时遇到了精度问题。
这是一个简单的独立示例来说明这个问题:
import numpy as np
n = 10
m = 4
tag = np.random.rand(n, m)
s1 = np.sum(tag, axis=1)
s2 = np.sum(tag[:, ::-1], axis=1)
# print the number of times s1 is not equal to s2 (should be 0)
print np.nonzero(s1 != s2)[0].shape[0]
Run Code Online (Sandbox Code Playgroud)
如果您执行此代码,它有时会告诉您s1和s2不相等,并且差异是计算机精度的数量级。
问题是我需要np.in1d在我无法真正容忍的功能中使用它们......
有没有办法避免这个问题?
对于列出的代码,您可以使用np.isclose它,也可以指定容差值。
使用提供的示例,让我们看看如何使用它 -
In [201]: n = 10
...: m = 4
...:
...: tag = np.random.rand(n, m)
...:
...: s1 = np.sum(tag, axis=1)
...: s2 = np.sum(tag[:, ::-1], axis=1)
...:
In [202]: np.nonzero(s1 != s2)[0].shape[0]
Out[202]: 4
In [203]: (~np.isclose(s1,s2)).sum() # So, all matches!
Out[203]: 0
Run Code Online (Sandbox Code Playgroud)
要在其他场景中使用容差值,我们需要逐案处理。因此,假设对于涉及元素比较的实现,例如 in np.in1d,我们可以引入broadcasting对第一个输入中的所有元素与第二个输入中的所有元素进行元素相等性检查。然后,我们使用np.abs来获得“接近度因子”,最后与输入容差进行比较以决定匹配。根据模拟的需要np.in1d,我们沿其中一个轴进行任何操作。因此,np.in1d容忍使用broadcasting可以像这样实现 -
def in1d_with_tolerance(A,B,tol=1e-05):
return (np.abs(A[:,None] - B) < tol).any(1)
Run Code Online (Sandbox Code Playgroud)
正如 OP 的评论中所建议的那样,我们还可以在放大浮点数后对它们进行舍入,这应该是内存高效的,因为这是处理大型数组所需要的。所以,修改后的版本会是这样 -
def in1d_with_tolerance_v2(A,B,tol=1e-05):
S = round(1/tol)
return np.in1d(np.around(A*S).astype(int),np.around(B*S).astype(int))
Run Code Online (Sandbox Code Playgroud)
样品运行 -
In [372]: A = np.random.rand(5)
...: B = np.random.rand(7)
...: B[3] = A[1] + 0.0000008
...: B[6] = A[4] - 0.0000007
...:
In [373]: np.in1d(A,B) # Not the result we want!
Out[373]: array([False, False, False, False, False], dtype=bool)
In [374]: in1d_with_tolerance(A,B)
Out[374]: array([False, True, False, False, True], dtype=bool)
In [375]: in1d_with_tolerance_v2(A,B)
Out[375]: array([False, True, False, False, True], dtype=bool)
Run Code Online (Sandbox Code Playgroud)
最后,关于如何使其适用于其他实现和用例 - 这将取决于实现本身。但在大多数情况下,np.isclose并broadcasting应帮助。