jef*_*ott 24 python arrays numpy
I am creating symmetric matrices/arrays in Python with NumPy, using a standard method:
x = rand(500,500)
x = (x+x.T)
all(x==x.T)
> True
Run Code Online (Sandbox Code Playgroud)
Now let's be clever:
x = rand(500,500)
x += x.T
all(x==x.T)
> False
Run Code Online (Sandbox Code Playgroud)
Wait, what?
x==x.T
> array([[ True, True, True, ..., False, False, False],
[ True, True, True, ..., False, False, False],
[ True, True, True, ..., False, False, False],
...,
[False, False, False, ..., True, True, True],
[False, False, False, ..., True, True, True],
[False, False, False, ..., True, True, True]], dtype=bool)
Run Code Online (Sandbox Code Playgroud)
The upper left and lower right segments are symmetrical. What if I chose a smaller array?
x = rand(50,50)
x += x.T
all(x==x.T)
> True
Run Code Online (Sandbox Code Playgroud)
OK....
x = rand(90,90)
x += x.T
all(x==x.T)
> True
x = rand(91,91)
x += x.T
all(x==x.T)
> False
Run Code Online (Sandbox Code Playgroud)
And just to be sure...
x = rand(91,91)
x = (x+x.T)
all(x==x.T)
> True
Run Code Online (Sandbox Code Playgroud)
Is this a bug, or am I about to learn something crazy about += and NumPy arrays?
jde*_*esa 24
The transpose operation returns a view of the array, which means that no new array is allocated. Which, in turn, means that you are reading and modifying the array at the same time. It's hard to tell why some sizes or some areas of the result work, but most likely it has to do with how numpy deals with array addition (maybe it makes copies of submatrices) and/or array views (maybe for small sizes it does create a new array).
The x = x + x.T operation works because there you are creating a new array and then assigning to x, of course.
Jai*_*ime 20
其他人提到的实现细节称为缓冲.您可以在有关数组迭代的文档中阅读有关它的更多信息.
如果你更详细地看一下你失败的例子:
>>> a = np.random.rand(91, 91)
>>> a += a.T
>>> a[:5, -1]
array([ 0.83818399, 1.06489316, 1.23675312, 0.00379798, 1.08967428])
>>> a[-1, :5]
array([ 0.83818399, 1.06489316, 1.75091827, 0.00416305, 1.76315071])
Run Code Online (Sandbox Code Playgroud)
所以第一个错误的价值就是90*91 + 2 = 8192,我们得到的结果不出所料:
>>> np.getbufsize()
8192
Run Code Online (Sandbox Code Playgroud)
我们也可以将它设置得更高,然后:
>>> np.setbufsize(16384) # Must be a multiple of 16
8192 # returns the previous buffer size
>>> a = np.random.rand(91, 91)
>>> a += a.T
>>> np.all(a == a.T)
True
Run Code Online (Sandbox Code Playgroud)
虽然现在:
>>> a = np.random.rand(129, 129)
>>> a += a.T
>>> np.all(a == a.T)
False
Run Code Online (Sandbox Code Playgroud)
当然,依靠正确性这是一件危险的事情,因为它确实是一个可以改变的实现细节.
| 归档时间: |
|
| 查看次数: |
854 次 |
| 最近记录: |