首页 > 解决方案 > 打包数据,Python中的极端Bitpacking

问题描述

我需要将信息尽可能紧密地打包到比特流中。

我有不同数量的不同状态的变量:

Number_of_states=[3,5,129,15,6,2]# A bit longer in reality

我目前最好的选择是创建一个位域,使用

2+3+8+4+3+1 位 ->21 位

然而,应该可以将这些状态打包成np.log2(3*5*129*15*6*2)=18.4位,节省两位。(实际上我有 298 位需要保存一些)

在我的情况下,这将节省大约 5% 以上的数据流,这将有很大帮助。

python中是否有可行的解决方案以这种方式打包数据?我试过packalgorithms了,但它们只用几个字节的数据就产生了太多的开销。字符串没问题,它是常量,会提前传输。

这是我目前正在使用的代码:

from bitstring import pack
import numpy as np

DATA_TO_BE_PACKED=np.zeros(6)

Number_of_states=[3,5,129,15,6,2]#mutch longer in reality

DATA_TO_BE_PACKED=np.random.randint(Number_of_states)

string=''

for item in Number_of_states:
    string+='uint:{}, '.format(int(np.ceil(np.log2(item))))

PACKED_DATA = pack(string,*DATA_TO_BE_PACKED)

print(len(PACKED_DATA ))

print(PACKED_DATA.unpack(string))

标签: pythonnumpycompressionbitstring

解决方案


您可以将状态解释为形状为 (3, 5, 129, 15, 6, 2) 的多维数组的索引。该索引可以编码为长度为 的扁平一维数组中的整数索引3*5*129*15*6*2 = 348300。NumPy 具有可以为您执行此操作ravel_multi_index的功能。unravel_index

例如,让num_states您的状态的每个组件的状态数:

In [86]: num_states = [3, 5, 129, 15, 6, 2]

假设state持有数据的一个实例;也就是说,它记录了每个组件的状态:

In [87]: state = [2, 3, 78, 9, 0, 1]

要编码此状态,请将其传递给ravel_multi_index. idx是编码状态:

In [88]: idx = np.ravel_multi_index(state, num_states)

In [89]: idx
Out[89]: 316009

通过构造,0 <= idx < 348300,所以它只需要 19 位。

state要从恢复idx,请使用unravel_index

In [90]: np.unravel_index(idx, num_states)
Out[90]: (2, 3, 78, 9, 0, 1)

推荐阅读