numpy:sqrt 到位:这是一个错误吗?

numpy: sqrt in place: is this a bug?

我正在尝试在数组的一部分上执行 sqrt,使用布尔掩码选择。

为什么这不起作用:

import numpy as np

a = np.array([[4,9],[16,25]], dtype='float64')

np.sqrt(a[[True, False], :], out=a[[True, False], :])
print(a[[True, False], :]) # prints [[4, 9]], sqrt in place failed

print('')

b = np.zeros_like(a[[True, False], :])
np.sqrt(a[[True, False], :], out=b)
print(b) # prints [[2, 3]] sqrt in b succeeded

如果我改为选择单个索引,这会起作用(但它对我没有帮助,因为我想进行稀疏更新):

import numpy as np

a = np.array([[4,9],[16,25]], dtype='float64')

np.sqrt(a[0, :], out=a[0, :])
print(a[0, :]) # prints [2, 3]

print('')

b = np.zeros_like(a[0, :])
np.abs(a[0, :], out=b) # prints [2, 3]
print(b)

一般的sqrt()不行到位。它 returns 修改后的数组。因此,您必须将 np.sqrt(a[[True, False], :], out=a[[True, False], :]) 行替换为 a = np.sqrt(a[[True, False], :], out=a[[True, False], :]) 以获得数组 a.

sqrt 函数的结果

这在indexing documentation中有解释,相关部分:

Advanced indexing always returns a copy of the data (contrast with basic slicing that returns a view).

使用布尔数组建立索引被认为是“高级”,因此您总是得到一个副本,并且修改它不会触及原始数据。实际上,在您的第一个示例中 b 已修改,但 a 未修改。仅使用索引 returns 一个“视图”,这就是修改原始数据的原因。

该问题表明在一个简单切片上可能存在就地平方根。因此,考虑到稀疏更新,可以循环遍历(稀疏)布尔掩码的 True 元素,在此类切片上进行就地平方根。

如果布尔掩码索引返回原始数组的视图,它可能不如假设的那样有效,但总比没有好。

import numpy as np

a = np.array([[4,9],[16,25]], dtype='float64')

mask = np.array([True, False])

for (i,) in np.argwhere(mask):
    slice = a[i]
    np.sqrt(slice, out=slice)

print(a)

给出:

[[  2.   3.]
 [ 16.  25.]]