21

任何人都推荐一种适用于双精度浮点值的良好压缩算法?我们发现浮点值的二进制表示会导致普通压缩程序(例如 Zip、RAR、7-Zip 等)的压缩率非常低。

我们需要压缩的数据是一个按单调递增顺序排序的 8 字节值的一维数组。这些值代表开尔文温度,跨度通常低于 100 度。值的数量范围从几百到最多 64K。

澄清

  • 数组中的所有值都是不同的,尽管由于浮点值的表示方式,在字节级别确实存在重复。

  • 由于这是科学数据,因此需要无损算法。如果存储效率有显着提高,转换为具有足够精度(约 5 个小数)的定点表示可能是可以接受的。

更新

发现了一篇关于这个主题的有趣文章。不确定该方法对我的要求有多适用。

http://users.ices.utexas.edu/~burtscher/papers/dcc06.pdf

4

6 回答 6

5

首先要考虑:在将数据转换为双精度之前尝试压缩数据。回复您对 David Thornley 的评论,除非您的 IR 成像 ADC 具有 24 个有效位,否则 32 位浮点数应该具有足够的精度;只有您要求准确保留后续处理产生的噪声才是一个问题。如果做不到这一点,可以想象通过确定它生成的值表并将索引存储到该表来对您的处理进行逆向工程。

第二:如果你的压缩算法知道你的数据是 8 字节的块,它会更有效;这是因为它不会将最重要的字节与最不重要的字节一起放入。作为一种粗略的预处理方法,您可以尝试在通过 gzip 之类的基于字节的压缩器进行管道传输之前,为每个双精度添加一个独特的字节(也许是 ASCII 逗号?);即使中间流大 12%,这应该会导致更好的总压缩。不那么粗糙但更多的努力是编写适合此任务的自己的压缩 - 可能使用 8 级树来表示双精度中每个字节的预期值。

第三:由于图像数据是高度冗余的,某种形式的增量编码或其他与图像相关的压缩应该可以节省一些空间。但是,如果您需要无损压缩,它不会为您带来很大的收益,因为图像噪声本质上是不可压缩的。此外,如上所述,它不会帮助您处理双打中不太重要的位中的伪随机散列。

于 2010-02-10T19:35:15.683 回答
4

您列出的所有编码器都是面向字节的,并且被一些双精度属性所抛弃。一方面是 12 位指数/符号在字节边界上不能很好地发挥作用的布局,另一方面是输入的噪音。第一部分很容易以多种方式处理,第二部分将限制您对其进行的任何无损压缩的有效性。我认为即使是最好的结果也不会令人惊讶,我不知道您的数据,但我怀疑您可以指望仅节省 25%,或多或少。

从我的脑海中,也许没用,因为你已经想到了这个列表上的所有内容......

  1. 将流视为 64 位整数并对相邻值进行增量编码。如果您有一系列具有相同指数的值,它将有效地将其归零,并且可能还有一些高尾数位。会有溢出,但数据仍然只需要 64 位,操作可以反转。

  2. 在这个阶段,您可以选择尝试一些粗略的整数预测,并保存差异。

  3. 如果您之前遵循了该建议,您将有几乎一半的值以 000 开头...而几乎一半的值以 FFF... 为消除这种情况,将值向左 (ROL) 旋转 1 位并将其与所有 F 进行异或如果当前 LSB 为 1。如果 LSB 为 0,则反向是与 Fs 的 XOR。

再想一想,简单地将预测与真实值进行异或比差异更好,因为那时您不必执行第 3 步。

  1. 您可以尝试重新排序字节以将具有相同重要性的字节组合在一起。比如,首先是所有最重要的字节,依此类推。最起码你应该得到类似大量零的东西,首先最多只有几位噪音。

  2. 运行一个通用压缩器,甚至是第一个零运行的 RLE,然后是一个熵编码器,比如霍夫曼,或者更好的,来自 7zip/LZMA 的范围编码器。

您的数据有一个好处,那就是单调。您的数据有一个不好的地方:它的集合太小了。你想节省多少,仅仅是千字节?做什么的?如果相邻值之间经常存在指数差异,则压缩效果将受到很大影响。

如果您正在处理大量这些数据集,您应该考虑使用它们的相似性来更好地将它们压缩在一起——也许在某个阶段将它们交错。如果您可以忍受一些损失,那么将一些最不重要的字节归零可能是一个好主意-也许在源数据和预测方面都如此,这样您就不会在那里重新引入噪音。

于 2010-03-28T22:51:14.373 回答
2

如果您需要高压缩存档存储,Burtscher & Patanaworabhan 的“双精度浮点数据的高吞吐量压缩”或 Lindstrom 和 Isenberg 的“浮点数据的快速高效压缩”可能对您有所帮助。

如果您希望以较低的压缩率为代价实现更快的动态访问,那么一维提升小波可能是合适的。您可以通过指定要保留的位数将数据量化为更小的整数。然后使用带有预测模型的 delta 编码,然后使用 Haar 变换或更昂贵的小波变换和大于指定值的系数的算术编码。

希望能帮助到你

您可以在这里获得 Lindstrom 的 ZFP 算法:https ://github.com/LLNL/zfp

于 2013-12-31T08:39:20.707 回答
1

你能在相邻值之间做一个增量吗?
测量之间的值可以改变多少有限制吗?将这种变化限制在某个最大速率值是否可以接受(以引入一些平滑为代价?)

热传感器的值的实际精度显然存在限制,您需要存储 64 位精度还是更好地存储整数,例如 0.01-开尔文单位?

如果您可以忍受更多的错误并且增加相对平滑,那么您最好将函数拟合到数据并仅存储函数的几个项。

编辑:
看看一个典型的数据集,看看相邻值之间的差异范围。然后看看你需要什么准确度来表示这个。

例如。如果读数之间的最大差异为 1 度,则可以将 1/256 的变化存储在一个字节中。如果您需要存储更大的范围或更准确的数据,请使用短除以某个因子。
所以下一个读数是 = last_reading + (float)increment/256.0

于 2010-02-10T17:15:33.147 回答
1

压缩算法依赖于重复和规律,而浮点数在这方面做得不好。

第一个问题是您是否可以使用单精度浮点值,这将立即为您提供 50% 的压缩。很少有温度计能精确到七位数,而指数代表的温度远低于我被告知您实际可以得到的任何温度。

如果没有,你能过滤你的温度,将它们四舍五入到相当于 N 位(更可能是 N/.301 位)吗?这可能会引入足够有用的规律性。

如果您确实必须为每个温度读数存储 64 位信息,并且所有位都很重要并且无法从其他位预测,那么您实际上无法压缩它。

于 2010-02-10T17:34:54.667 回答
0

您可以考虑使用熵编码器(Huffman、Shannon-Fano、算术编码)重新编码您的数据。但这只有在您有很多重复数据点并且您知道哪些符号将以何种概率出现时才能提供良好的结果。

于 2010-02-10T17:22:56.907 回答