预压缩背后有科学吗?

时间:2016-07-03 19:33:18

标签: numpy struct compression lzma

这是我的问题 - 我有一个程序需要写一些输出,压缩后的输出需要尽可能小。

在这种情况下,人们可能会发现自己要问的第一个问题是“我应该为数据使用什么数据结构?”。 XML? JSON? SQLITE?文本? STRUCT?

我认为说一个类似C的结构会在压缩之前为你提供最小的文件而不是其他任何格式都是毫无争议的,但我正在努力弄清楚的是设计该结构的“规则”在压缩后尽可能小。所谓“预压缩”的工作。

举例来说,我最近不得不尽可能地保存一些DNA。有5个字母的DNA,'A','C','G','T'和'N'。 N代表'不知道'。这意味着每个字符使用的最小二进制数量是3位。

000 = A
001 = C
010 = G
011 = T
100 = N

所以我做了我认为正确的事情,并编写了一些代码,这些代码采用了一长串DNA,比如像'AACA'这样的四个字母,并将其转换为二进制,如'000 000 001 000',然后返回两个字节'xxxx0000','00001000',其中x是填充(也是0)。

实际程序需要76个字母的DNA并返回29个字节,但它的想法相同。然后我将这29个字节写入一个结构(29 uint8字节),其中7211405个DNA片段导致了一个209130745字节或209Mb的文件。在LZMA压缩之后,此文件缩小到74.3Mb。

然后我决定重新运行相同的编码/压缩,但这次用4位编码每个DNA字母。基本上,前一个文件的每个第4位现在是0. 001变为0001等。结果文件大小为274Mb,因此大65Mb,但压缩到70.2Mb,或者说小4.1Mb - 占最终的很大比例文件大小。

我用gzip,bzip2等看到同样的事情。添加零以获得每个字节两个DNA字母有助于压缩器输出。那么现在怎么办?我还能做些什么来帮助压缩机出来?我还能做些什么来获得更小的文件大小(无损)。

我想到的一个技巧是对DNA序列进行排序以保存,并且有一个单独的密钥可用于重新创建订单。在numpy中,这是用

完成的
my_array,key = numpy.unique(original_array, return_inverse=True)

使my_array成为original_array中唯一项的排序列表,key是my_array的索引列表,可用于重新创建original_array。理想情况下,my_array会很好地压缩,关键也是如此,但这两个文件的总和大致是未开始的结构的开头。在某些情况下,小一点,在另一些情况下略大一点 - 但没有什么可写回家的。

另一个想法是完全使用不同的数据结构,如图形/ trei(仍然编码为结构,但每行是节点而不是条目),但我担心我正在考虑以错误的方式压缩。我知道我不能减少超出熵限制的文件大小,但也许预压缩的秘诀就是将数据与字节对齐比创建更小的未压缩文件更好的路径 - 但是压缩文件更大。

我不是在问'你怎么做预压缩',我问'预压缩是我可以学到更多的东西,如果有的话,什么是流行语/搜索词我正在寻找'

1 个答案:

答案 0 :(得分:0)

  

我知道我不能减少超出熵限制的文件大小

但你可以!很多压缩机经常这样做。问题是(香农)熵取决于pdf,给定符号的概率分布。符号可以是“0”或“1”;或A,C,T,G& N;或高频等位基因。每组符号将为您提供不同的熵测量。找到正确的符号集,你就是金色的。

像LZC这样的压缩器使用各种方法动态调整pdf而非二进制字符串,并且有点难以击败。但是,如果您对数据有所了解,那么您可以对其进行改进。

祝你好运!