python - 优化二维数组中所有元素的舍入

标签 python arrays optimization numpy

我有一个二维 numpy 数组,我希望每个元素都四舍五入到序列中最接近的数字。该数组的形状为 (28000, 24)

例如,序列将是 [0, 0.05, 0.2, 0.33, 0.5]

例如原始 0.27 将四舍五入为 0.330.42 将四舍五入为 0.5

这是我目前使用的,但是使用双循环当然很慢。

MWE:

arr = np.array([[0.14, 0.18], [0.20, 0.27]])
new = []
sequence = np.array([0, 0.05, 0.2, 0.33, 0.5])
for i in range(len(arr)):
    row = []
    for j in range(len(arr[0])):
        temp = (arr[i][j] - sequence)**2
        row.append(list(sequence[np.where(temp == min(temp))])[0])
    new.append(row)

结果:

[[0.2000001, 0.2000001], [0.2000001, 0.33000001]]  

动机:

在机器学习中,我正在做预测。由于结果反射(reflect)了专家的信心,因此可能有 2/3 给出了 1(即 0.66)。所以,在这个数据中,会出现比较多的0、0.1、0.2、0.33、0.66、0.75等。然而,我的预测大约是 0.1724。在这种情况下,我会通过四舍五入到 0.2 来消除很多预测误差。

如何优化所有元素的舍入?

更新:我现在预分配内存,所以不必不断追加。

 # new = [[0]*len(arr[0])] * len(arr), then unloading into new[i][j],
 # instead of appending 

时间:

Original problem: 36.62 seconds
Pre-allocated array: 15.52 seconds  
shx2 SOLUTION 1 (extra dimension): 0.47 seconds
shx2 SOLUTION 2 (better for big arrays): 4.39 seconds
Jaime's np.digitize: 0.02 seconds

最佳答案

可以围绕 np.digitize 构建另一个中间存储不大于要处理的数组的真正矢量化解决方案.

>>> def round_to_sequence(arr, seq):
...     rnd_thresholds = np.add(seq[:-1], seq[1:]) / 2
...     arr = np.asarray(arr)
...     idx = np.digitize(arr.ravel(), rnd_thresholds).reshape(arr.shape)
...     return np.take(seq, idx)
... 
>>> round_to_sequence([[0.14, 0.18], [0.20, 0.27]],
...                   [0, 0.05, 0.2, 0.33, 0.5])
array([[ 0.2 ,  0.2 ],
       [ 0.2 ,  0.33]])

更新 那么发生了什么......函数的第一行计算出序列中项目之间的中点是什么。这个值是四舍五入的阈值:低于它,你必须向下舍入,高于它,你必须向上舍入。我使用 np.add,而不是更清晰的 seq[:-1] + seq[1:],这样它就可以接受列表或元组而无需显式转换它到一个 numpy 数组。

>>> seq = [0, 0.05, 0.2, 0.33, 0.5]
>>> rnd_threshold = np.add(seq[:-1], seq[1:]) / 2
>>> rnd_threshold
array([ 0.025,  0.125,  0.265,  0.415])

接下来我们使用 np.digitize 来找出数组中的每个项目在哪个 bin 中,由这些阈值分隔。 np.digitize 只需要一维数组,所以我们必须做 .ravel.reshape 的事情来保持数组的原始形状。照原样,它使用标准约定将限制的项目四舍五入,您可以使用 right 关键字参数来反转此行为。

>>> arr = np.array([[0.14, 0.18], [0.20, 0.27]])
>>> idx = np.digitize(arr.ravel(), seq).reshape(arr.shape)
>>> idx
array([[2, 2],
       [3, 3]], dtype=int64)

现在我们需要做的就是创建一个形状为 idx 的数组,使用它的条目来索引要四舍五入的值序列。这可以通过 seq[idx] 来实现,但使用 np.take 通常(总是?)更快(参见 here)。

>>> np.take(seq, idx)
array([[ 0.2 ,  0.2 ],
       [ 0.33,  0.33]])

关于python - 优化二维数组中所有元素的舍入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19722919/

相关文章:

mysql - 强制扫描子查询结果而不是现有结果

php - 我的基本PHP Socket Server是否需要优化?

python - Pandas ,列值大于x的groupby

在c中创建按钮gtk数组

python - sort() 不适用于列表理解

c - 在 C 中从 typedef 结构设置和获取数组的值

java - Arrays.asList(T... a) 如何返回接口(interface)?

optimization - 高效的Hashmap使用

python - 无法从数据库返回数组

python - 如何选择网站的各种元素