您可以使用.tobytes()
函数将numpy数组转换为字节数组。
如何将它从这个字节数组解码回numpy数组呢? 我尝试了像下面这样的代码,其中i是形状为(28,28)的数组:
>> k=i.tobytes()
>> np.frombuffer(k)==i
False
也尝试过uint8。
您可以使用.tobytes()
函数将numpy数组转换为字节数组。
如何将它从这个字节数组解码回numpy数组呢? 我尝试了像下面这样的代码,其中i是形状为(28,28)的数组:
>> k=i.tobytes()
>> np.frombuffer(k)==i
False
也尝试过uint8。
frombuffer
总是将输入解释为一维数组。这是文档的第一行。因此,你需要重新调整形状为(28, 28)
。
默认的 dtype
是float
。所以如果你没序列化出浮点数,那么你就需要手动指定dtype
(没有人能事先知道字节流代表什么:你必须说明它们代表什么)。
如果你想确保数组相等,那么你必须使用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
祝好运。
np.frombuffer()
返回的对象是只读的。 - Brad Solomon虽然您可以使用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
为了方便起见,这里提供了一个序列化/反序列化函数,实现了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()
np.tobytes
方法,您可以使用pickle.dumps
和pickle.loads
。import pickle
A = np.random.randint(0, 10, [2,2])
A_bytes=pickle.dumps(A, protocol=0)
A_restore=pickle.loads(A_bytes)
# test byte type and restored np mat
np.testing.assert_array_equal(A_restore, A)
assert type(A_bytes)==bytes