为什么霍夫曼编码可以消除Lempel-Ziv不能消除的熵?


13

流行的DEFLATE算法在Lempel-Ziv的顶部使用霍夫曼编码。

通常,如果我们有一个随机的数据源(= 1位熵/位),那么包括霍夫曼在内的任何编码都不可能平均地对其进行压缩。如果Lempel-Ziv是“完美的”(随着长度的增长,它对于大多数类型的信号源都接近无穷大),那么用霍夫曼进行后期编码将无济于事。当然,Lempel-Ziv 并不完美,至少长度有限,因此仍然存在一些冗余。

霍夫曼编码部分地消除了这种剩余的冗余,从而改善了压缩。

我的问题是:为什么通过Huffman编码而不是LZ成功消除了剩余的冗余?霍夫曼与LZ的哪些属性使这种情况发生?再次运行LZ(即第二次使用LZ编码LZ压缩数据)是否会实现类似的效果?如果没有,为什么不呢?同样,首先使用Huffman进行压缩,然后使用LZ进行压缩,如果不能,为什么?

更新: 很明显,即使在LZ之后,也会保留一些冗余。有几个人指出了这一点。尚不清楚的是:为什么霍夫曼要比LZ更好地解决剩余冗余问题?与原始的源冗余(LZ比Huffman更好)相比,它有什么独特之处?

Answers:


13

这最初是评论,但时间太长。

如果看一下DEFLATE,霍夫曼压缩的就是LZ77的输出。LZ77的工作原理是(当此方法所花费的位数少于原始数据时)将一个指针更早地发送到要压缩的字符串中,以及一个匹配长度,该长度告诉指针之后要取多少符号。理论表明,即使没有附加压缩,该技术最终也会收敛到源熵。但是,在数据压缩中,只要您的分布不是完全随机的,就可以对其进行压缩。没有理由相信LZ77的输出(指针和匹配长度)是完全随机的。由于LZ77是渐近最优的,因此它们必须收敛以在渐近极限内完全随机,但是实际上,您仅使用有限字典,因此它们可能与完全随机性相距足够远,您可以通过对它们进行进一步压缩来获胜。自然,您将一个霍夫曼代码用于指针,将另一个霍夫曼代码用于匹配长度,因为这两个过程具有不同的统计信息。

为什么在第二轮压缩中使用霍夫曼而不是LZ?与Huffman相比,LZ的最大优势在于可以处理符号之间的依赖关系。在英语中,如果一个字母是“ q”,则下一个字母极有可能是“ u”,依此类推。如果符号是独立的事件,则霍夫曼会更简单,并且对于短字符串同样适用或更好。对于LZ77的输出,我的直觉是这些符号应该是相当独立的,因此霍夫曼应该更好地工作。


我在第一段与您在一起:LZ仍然留有一些冗余以便进一步压缩。但是,即使没有挥手,您的第二段似乎仍在跳跃。有两个断言:1. LZ之后剩余的冗余为零阶(即,p(X_n)大约独立于x_n-1;我在零阶模型中使用术语零阶,例如data-compression.com/theory.shtml)和2。在零阶冗余方面,霍夫曼的表现优于LZ;在高阶冗余上,LZ可以更好地工作。也许这些主张都是正确的,但您也没有道理
SRobertJames

2
@Robert:高阶相关对霍夫曼编码没有任何影响。LZ渐近最优地工作以实现高阶冗余,但是所需的额外开销意味着它在有限长度的零阶源上表现不佳。这一定是在某处的文献中经过实验研究的;也许其他人可以提供指向参考的指针。对于第1点,我的直觉是LZ之后剩余的任何高阶冗余都太复杂了,无法在任何简单的编码方案中使用,但是我没有很好的方法来证明这一点。
彼得·索尔

10

数据压缩实际上涉及两件事:建模和编码。LZ族的算法将文本建模为精确重复的串联,这对于许多随机源而言是渐近最优的,而对于许多真实文本而言则相当好。但是,对于某些输入,此模型可能会很糟糕。例如,即使后缀数组与原始文本一样可压缩,也不能使用LZ直接压缩后缀数组。

LZ77将输入编码为元组序列,每个重复一个,其中是指向较早出现的指针,是重复的长度,而是下一个字符。通常,此序列不包含许多(相当长的)精确重复,因此我们不能使用其他基于LZ的算法对其进行压缩。相反,我们必须寻找其他模型。p Ç(p,,c)pc

在元组的三个组成部分中,可以将指针视为一个大的随机整数,因此将其编码为位整数(对于长度为的输入)是一个不错的选择。另一方面,重复长度通常很小,因此我们应该使用优先于小数字而不是大数字的代码对其进行编码。霍夫曼是一种合适的编码方案,还有其他方案。重复后的字符可能分布不均匀,因此我们可以使用Huffman等零阶压缩器来挤出最明显的冗余。nlognn

简而言之,霍夫曼在压缩元组方面胜过LZ,因为它的模型(固定分布与精确重复)更适合数据。


谢谢你朱妮 听起来好像剩下的主要冗余是:rep长度通常较小而不是较大(不在[0,2 ^ n]上均匀分布)。霍夫曼在零阶不对称方面做得很好,而LZ确实需要更大的功能才能正常工作。那是对的吗?为什么不使用霍夫曼作为起点-为什么还要烦LZ?
SRobertJames 2011年

3
如果我们直接使用霍夫曼压缩文本,则压缩效果将不如零阶熵更好。但是,大多数真实文本具有大量的冗余资源,无法使用零阶熵对其进行充分建模。在许多情况下,在霍夫曼之前使用LZ可以压缩这种冗余。
朱尼·西伦(JouniSirén)2011年

2

我相信答案就在于查询字典的大小。

数据具有局部性(也就是说,如果使用了一条数据,则很可能很快会再次使用它),LZ算法在查找字典的构造中利用了这一点。它生成带有有限数量可能节点的特里树,以保持快速查找。当达到大小限制时,它将进行另一个尝试,“忘记”先前的尝试。因此,它必须再次为更简单的字符构建查找表,但是如果不再使用某些单词,它们将不再保存在内存中,因此可以使用较小的编码。

因此,可以通过霍夫曼编码进一步减少LZ输出,因为可以通过统计分析检测查找尝试的创建过程中的这种冗余。


我接受第一段:您解释LZ为什么留下冗余。但是第二段似乎是一个飞跃:为什么霍夫曼抓住了这种冗余?为什么不再次使用LZ?而且,如果霍夫曼更全面,为什么不从头开始呢?
SRobertJames 2011年

2

也许我不在这里,但是Huffman编码会查看整个输入以构建其编码表(树),而Lempel-Ziv会随其进行编码。对于霍夫曼来说,这既是优点也是缺点。缺点很明显,即我们必须在开始之前先查看整个输入。优点是霍夫曼将考虑输入中任何地方发生的统计信息,而Lempel-Ziv必须逐步建立起来。或者换一种说法,Lempel-Ziv有一个“方向”,霍夫曼没有。

但这只是我天真地想象事物状态的方式。我们在这里需要一个真实的证明,以了解霍夫曼到底比伦佩尔·齐夫(Lempel-Ziv)表现如何。


2
人们已经定义了自适应霍夫曼编码,该编码仅查看输入一次。出于讨论的目的,自适应和非自适应霍夫曼编码的行为将非常相似。
彼得·索尔

2

简短的答案是,LZ是一种“通用”算法,因为它不需要知道源的确切分布(只需要假设源是固定的和遍历的即可)。但是霍夫曼不是。它需要知道从中采样源的确切分布(用于制作霍夫曼树)。这些附加信息使霍夫曼获得了严格的压缩保证。但是,对于实际的文件压缩算法,霍夫曼可能不太理想,因为它首先需要收集文件的经验统计信息,然后在下半年进行实际压缩,而LZ可以在线实施。

在标准信息理论课本中可以找到更多详细信息,例如Cover和Thomas撰写的“信息论要素”。


我认为固定遍历源只是使LZ易于分析的一种假设。毕竟,压缩是基于输入的组合属性,在许多情况下,恰好恰好与统计属性相吻合。例如,考虑纯文本格式的英语文本的集合,然后是HTML格式的相同文本。LZ很好地压缩了此集合,即使它看起来不像是固定的遍历源生成的东西。
朱尼·西伦(JouniSirén)2011年

@Jouni:我不同意这个评论。我认为从某种意义上说,纯文本英语看起来很像固定的遍历语言,而这种相似正是LZ所利用的。
彼得·索尔

@Peter:但是在这种情况下,源代码首先生成一些纯文本格式的文本,然后生成与HTML格式完全相同的文本。从纯文本到HTML的任意更改似乎打破了遍历固定属性。另一方面,压缩结果比分别压缩纯文本和HTML文本时要好得多,因为纯文本格式的文本和HTML格式的相同文本之间存在许多相互信息。
朱尼·西伦(JouniSirén)2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.