[英]Measuring efficiency of Huffman coding with Python bitstring
我有以下字符串,我想将霍夫曼编码并有效存储到位数组中:
>>> print sequence
GTCAGGACAAGAAAGACAANTCCAATTNACATTATG|
符号的频率sequence
为:
>>> print freqTuples
[(0.40540540540540543, 'A'), (0.1891891891891892, 'T'), (0.16216216216216217, 'C'), (0.16216216216216217, 'G'), (0.05405405405405406, 'N'), (0.02702702702702703, '|')]`
我把它翻译成霍夫曼代码字典:
>>> print codeDict
{'A': '1', 'C': '010', 'G': '001', 'N': '0110', 'T': '000', '|': '0111'}
然后我使用Python bitstring
包将字符串逐字符串转换为BitArray
类的实例,我称之为bitArray
,它包含用各自的Huffman代码编码的每个字符的位:
>>> print bitArray.bin
0b001000010100100110101100111100110101101100000100101100000001101010100000010000010111
这是以字节为单位的位数组:
>>> print bitArray.tobytes()
!I\254\363[^D\260^Z\240Ap
我必须使用tobytes()
而不是bytes
,因为我生成的位数组不能均匀地划分为8位段。
当我计算BitArray
表示的存储效率(位数组和输入字符串的大小的比率)时,我的性能会比未输入的输入字符串差得多:
>>> sys.getsizeof(bitArray.tobytes()) / float(len(sequence))
1.2972972973
我是否正确测量存储效率? (如果我对较长的输入字符串进行编码,这个比率会提高,但它似乎接近0.28的渐近极限。我想确认这是否是衡量事物的正确方法。)
编辑
以下两种方法产生不同的答案:
>>> print len(bitArray.tobytes()) / float(len(mergedSequence))
0.297297297297
>>> print bitArray.len / (8.*len(mergedSequence))
0.283783783784
我不确定该相信哪一个。 但是在将数据写入存储的过程中,我认为我需要字节表示,这使我倾向于选择第一个结果。
我不太确定bitarray的东西,但你不应该只能做:
>>> len(bitArray.tobytes()) / float(len(sequence))
我不是说这会解决你的问题,但可能是因为“getizeof”的事情(再次,我并不是那么熟悉的事情)会让你失望。
从你在那里写的,看起来你有点像苹果和橙子。
>>> sys.getsizeof(bitArray.tobytes()) / float(len(sequence))
1.2972972973
意味着编码版本比原始序列长 30%。
我不认为你想在这里使用getsizeof
- 如果你想最小化Python对象的大小,你应该使用getsizeof(sequence)
,而不是len
。
相反,如果你想做霍夫曼编码要做的事情,并最小化二进制表示,那么你想在两者上使用len
(假设序列表示为每个字符一个字节)。
所以,你的真实比例是11/37。
我假设您正在使用霍夫曼编码作为练习,因为这似乎不是一种有效存储仅具有终止字符的四位代码的逻辑方法。 至少最好使用算术编码,这将允许您使用base-5编码而不是base-2,这对于5个可能的字符是最佳的。
实际上,我假设在一个足够长的序列中值得压缩,有一个已知的G:A:C:T和/或固定长度2位编码的比率同样有效(比率接近1:1: 1:1)因为你真的不需要编码终止字符。
你知道答案是错误的,因为霍夫曼字典每个字符少于4位,所以真正的答案必须小于.5。 如果字典和字符频率对于较长的字符串没有变化,则压缩比不应随着字符串变长而逐渐减小到渐近限制。
从sys的文档:
"getsizeof() calls the object’s __sizeof__ method and adds
an additional garbage collector overhead if the object is
managed by the garbage collector."
你需要一个函数来返回bitstring本身的长度,而不是bitstring + overhead。 BitString文档说len
或length
属性以位为单位返回长度。 所以尝试做:
bitArray.len / 8.*len(sequence)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.