将字节数组转换回numpy数组

Gau*_*osh 12 python numpy python-3.x

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

如何将其从此字节数组解码回numpy数组?我尝试过这样的形状数组(28,28)

>>k=i.tobytes()

>>np.frombuffer(k)==i

False

也尝试过使用uint8。

Mat*_*ith 13

您正在做的事情有两个问题:

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

  2. 默认dtype值为float。因此,如果您没有序列化浮点数,那么就必须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
Run Code Online (Sandbox Code Playgroud)

HTH。

  • 重要提示:np.frombuffer()返回的对象是只读的 (4认同)

Sak*_*ngh 10

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

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

一个更优雅的解决方案是np.save使用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
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,这种方法对于大型 numpy 数组来说非常非常慢。请参阅相关的SO帖子:/sf/ask/4364686931/?noredirect=1#comment110277408_62352670 (6认同)

Sam*_*yer 8

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

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()

Run Code Online (Sandbox Code Playgroud)