【问题标题】:Convert byte array back to numpy array将字节数组转换回numpy数组
【发布时间】:2019-04-21 22:33:36
【问题描述】:

您可以使用 .tobytes() 函数将 numpy 数组转换为字节。

如何将它从这个字节数组解码回 numpy 数组? 我对形状为 (28,28) 的数组 i 尝试了这样的操作

>>k=i.tobytes()

>>np.frombuffer(k)==i

False

也尝试使用 uint8。

【问题讨论】:

  • 这样不行。我首先尝试了我的形状(28,28),我尝试了>>k=i.tobytes() >>np.frombuffer(k)==i False also tried with uint8 as well not working
  • 您在与 MNIST 合作吗? :)
  • 是的,它位于 MNIST 之上。它被用作示例数据集。

标签: python python-3.x numpy


【解决方案1】:

你正在做的几个问题:

  1. frombuffer 将始终将输入解释为一维数组。这是documentation 的第一行。所以你必须重塑为(28, 28)

  2. 默认dtypefloat。因此,如果您没有序列化浮点数,那么您将不得不手动指定dtype(先验没有人能说出字节流的含义:您必须说出它们代表什么)。

  3. 如果要确保数组相等,则必须使用np.array_equal。使用 == 将执行元素操作,并返回一个 numpy 布尔数组(这可能不是您想要的)。

如何将它从这个字节数组解码回numpy数组?

例子:

In [3]: i = np.arange(28*28).reshape(28, 28)

In [4]: k = i.tobytes()

In [5]: y = np.frombuffer(k, dtype=i.dtype)

In [6]: y.shape
Out[6]: (784,)

In [7]: np.array_equal(y.reshape(28, 28), i)
Out[7]: True

HTH。

【讨论】:

  • 重要:np.frombuffer()返回的对象是只读的
【解决方案2】:

虽然您可以使用tobytes(),但它不是理想的方法,因为它不存储 numpy 数组的形状信息。

如果您必须将其发送到没有形状信息的另一个进程,则必须明确发送形状信息。

更优雅的解决方案是使用 np.save 将其保存到 BytesIO 缓冲区并使用 np.load 进行恢复。在这种情况下,您不需要在任何地方专门存储形状信息,并且可以轻松地从字节值中恢复您的 numpy 数组。

例子:

>>> import numpy as np
>>> from io import BytesIO

>>> x = np.arange(28*28).reshape(28, 28)
>>> x.shape
(28, 28)

# save in to BytesIo buffer 
>>> np_bytes = BytesIO()
>>> np.save(np_bytes, x, allow_pickle=True)

# get bytes value
>>> np_bytes = np_bytes.getvalue()
>>> type(np_bytes)
<class 'bytes'>

# load from bytes into numpy array
>>> load_bytes = BytesIO(np_bytes)
>>> loaded_np = np.load(load_bytes, allow_pickle=True)

# shape is preserved
>>> loaded_np.shape
(28, 28)

# both arrays are equal without sending shape
>>> np.array_equal(x,loaded_np)
True

【讨论】:

【解决方案3】:

为方便起见,这里有一个实现Saket Kumar's答案的序列化/反序列化函数。

from io import BytesIO
import numpy as np

def array_to_bytes(x: np.ndarray) -> bytes:
    np_bytes = BytesIO()
    np.save(np_bytes, x, allow_pickle=True)
    return np_bytes.getvalue()


def bytes_to_array(b: bytes) -> np.ndarray:
    np_bytes = BytesIO(b)
    return np.load(np_bytes, allow_pickle=True)

# ----------
# quick test

def test():
    x = np.random.uniform(0, 155, (2, 3)).astype(np.float16)
    b = array_to_bytes(x)
    x1 = bytes_to_array(b)
    assert np.all(x == x1)


if __name__ == '__main__':
    test()

【讨论】:

    猜你喜欢
    • 2020-03-04
    • 2013-05-05
    • 1970-01-01
    • 2016-01-13
    • 2016-06-16
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多