如何转换源自尴尬数组的 numpy 数组的数据类型[关闭]

问题描述 投票:0回答:1

我有一个 numpy 数组,通过 to_numpy() 函数从笨拙的数组转换而来,结果数组的数据类型为: dtype=[('phi', '

我尝试了常规的 asdtype 函数,但我得到的只是错误

python numpy tensorflow numpy-ndarray awkward-array
1个回答
2
投票

我相信你的问题与此相同:你有一些带有记录结构的尴尬数组,

>>> array = ak.Array([{"phi": 1.1, "eta": 2.2}, {"phi": 3.3, "eta": 4.4}])

当您使用 ak.to_numpy 进行转换时,它会将记录字段转换为 NumPy 结构化数组 字段:

>>> ak.to_numpy(array)
array([(1.1, 2.2), (3.3, 4.4)], dtype=[('phi', '<f8'), ('eta', '<f8')])

TensorFlow 和 PyTorch 等 ML 库希望特征向量具有带名称的字段,而是相反是二维数组,其中第二维范围涵盖所有特征。如果所有 NumPy 结构化数组数据类型都相同,因为在本例中它们都是

<f8
,您可以查看它:

>>> ak.to_numpy(array).view("<f8").reshape(len(array), -1)
array([[1.1, 2.2],
       [3.3, 4.4]])

但这不安全。例如,如果您的某些字段是 32 位而其他字段是 64 位,或者某些字段是整数而其他字段是浮点型,则 view 将重新解释内存,从而丢失数字的含义:

>>> bad = np.array([(1, 2, 3.3), (4, 5, 6.6)], dtype=[("x", "<i4"), ("y", "<i4"), ("z", "<f8")])
>>> bad.view("<f8").reshape(len(bad), -1)
array([[4.24399158e-314, 3.30000000e+000],
       [1.06099790e-313, 6.60000000e+000]])

z
的 3.3 和 6.6 被保留,但是
x
y
被合并到一个字段中,并且原始内存被解释为浮点数。)

相反,我们应该在 Awkward 中调整结构,它有工具可以完成这类事情,然后将其转换为 NumPy(并从那里转换为 TensorFlow 或 PyTorch)。

因此,我们从具有命名字段的记录数组开始:

>>> array
<Array [{phi: 1.1, eta: 2.2}, {...}] type='2 * {phi: float64, eta: float64}'>

我们希望命名字段消失并创建这些单独的数组。那是 ak.unzip.

>>> ak.unzip(array)
(<Array [1.1, 3.3] type='2 * float64'>, <Array [2.2, 4.4] type='2 * float64'>)

(元组中的第一个来自

phi
,第二个来自
eta
。)

我们希望将每个字段的值一起放入机器学习模型的相同输入向量中。也就是说,

1.1
2.2
应该在向量
[1.1, 2.2]
中,并且
3.3
4.4
应该在向量
[3.3, 4.4]
中。这是该元组中数组的串联,但不是
axis=0
的串联,从而形成
[1.1, 3.3, 2.2, 4.4]
;它必须是更高层
axis=1
中的串联。该轴尚不存在,但我们始终可以使用 np.newaxis.

制作长度为 1 的轴。
>>> ak.unzip(array[:, np.newaxis])
(<Array [[1.1], [3.3]] type='2 * 1 * float64'>, <Array [[2.2], [4.4]] type='2 * 1 * float64'>)

现在 ak.concatenate

axis=1
会将
[1.1]
[2.2]
连接成
[1.1, 2.2]

>>> ak.concatenate(ak.unzip(array[:, np.newaxis]), axis=1)
<Array [[1.1, 2.2], [3.3, 4.4]] type='2 * 2 * float64'>

最后,这里有一个单行代码,您可以将其传递给 TensorFlow,即使您的记录字段具有不同的 dtypes,它也能正常工作:

>>> ak.to_numpy(ak.concatenate(ak.unzip(array[:, np.newaxis]), axis=1))
array([[1.1, 2.2],
       [3.3, 4.4]])

或者,实际上,也许您可以跳过 ak.to_numpy 并直接进入 ak.to_tensorflow

© www.soinside.com 2019 - 2024. All rights reserved.