gpt4 book ai didi

python - 创建不同形状数组的对象数组时如何防止 numpy 广播

转载 作者:太空狗 更新时间:2023-10-30 01:05:40 26 4
gpt4 key购买 nike

我尝试将不同形状数组的列表存储为 dtype=object使用 np.save 的数组(我知道我可以对列表进行 pickle,但我真的很好奇该怎么做)。如果我这样做:

import numpy as np
np.save('test.npy', [np.zeros((2, 2)), np.zeros((3,3))])

它有效。但是这个:

np.save('test.npy', [np.zeros((2, 2)), np.zeros((2,3))])

给我一​​个错误:

ValueError: could not broadcast input array from shape (2,2) into shape (2)

我猜 np.save首先将列表转换为数组,所以我尝试了:

x=np.array([np.zeros((2, 2)), np.zeros((3,3))])
y=np.array([np.zeros((2, 2)), np.zeros((2,3))])

效果相同(第一个有效,第二个无效。结果 x表现如预期:

>>> x.shape
(2,)
>>> x.dtype
dtype('O')
>>> x[0].shape
(2, 2)
>>> x[0].dtype
dtype('float64')

我还尝试强制“对象”数据类型:

np.array([np.zeros((2, 2)), np.zeros((2,3))], dtype=object)

没有成功。似乎 numpy 试图将第一维相等的数组广播到新数组中,但意识到它们的形状不同时为时已晚。奇怪的是,它似乎在某一时刻起作用了 - 所以我真的很好奇有什么区别,以及如何正确地做到这一点。


编辑:我弄清楚了它之前工作的情况:唯一的区别似乎是列表中的 numpy 数组具有另一种数据类型。它适用于 dtype('<f8') , 但它不适用于 dtype('float64') , 我什至不确定有什么区别。


编辑 2:我找到了一种非常非 pythonic 的方法来解决我的问题,我在这里添加它,也许它有助于理解我想做什么:

array_list=np.array([np.zeros((2, 2)), np.zeros((2,3))])
save_array = np.empty((len(array_list),), dtype=object)
for idx, arr in enumerate(array_list):
save_array[idx] = arr
np.save('test.npy', save_array)

最佳答案

np.save 做的第一件事是

arr = np.asanyarray(arr)

是的,它正在尝试将您的列表转换为数组。

从任意大小的数组或列表构造对象数组是很棘手的。 np.array(...) 尝试创建尽可能高的维度数组,如果可能甚至尝试连接输入。最可靠的方法是做你所做的 - 使 数组并填充它。

构造对象数组的一种稍微更紧凑的方法:

In [21]: alist = [np.zeros((2, 2)), np.zeros((2,3))]
In [22]: arr = np.empty(len(alist), dtype=object)
In [23]: arr[:] = alist
In [24]: arr
Out[24]:
array([array([[ 0., 0.],
[ 0., 0.]]),
array([[ 0., 0., 0.],
[ 0., 0., 0.]])], dtype=object)

这里有 3 个场景:

形状匹配的数组,组合成一个 3d 数组:

In [27]: np.array([np.zeros((2, 2)), np.zeros((2,2))])
Out[27]:
array([[[ 0., 0.],
[ 0., 0.]],

[[ 0., 0.],
[ 0., 0.]]])
In [28]: _.shape
Out[28]: (2, 2, 2)

在第一个维度上不匹配的数组 - 创建对象数组

In [29]: np.array([np.zeros((2, 2)), np.zeros((3,2))])
Out[29]:
array([array([[ 0., 0.],
[ 0., 0.]]),
array([[ 0., 0.],
[ 0., 0.],
[ 0., 0.]])], dtype=object)
In [30]: _.shape
Out[30]: (2,)

还有尴尬的中间情况(甚至可能被描述为错误)。第一个维度匹配,但第二个维度不匹配):

In [31]: np.array([np.zeros((2, 2)), np.zeros((2,3))])
...
ValueError: could not broadcast input array from shape (2,2) into shape (2)
[ 0., 0.]])], dtype=object)

就好像初始化了一个(2,2,2)数组,然后发现(2,3)放不下。并且当前的逻辑不允许它像在前面的场景中那样备份和创建对象数组。

如果您想将两个 (2,2) 数组放入对象数组中,您必须使用创建和填充逻辑。

关于python - 创建不同形状数组的对象数组时如何防止 numpy 广播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43173540/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com