熵和霍夫曼编码

编码


编码的目的是表示一系列符号 ($s_n$),其中 $s_n$ 取自有限集合 𝒳。

  • 这些符号可以是字母(文本编码)、整数(图像像素值)、音频信号的样本等。需要编码的符号类型并不重要。假设我们知道每个符号的出现概率,并且这些符号是独立生成的。每个符号由其代码表示,代码是一系列位(0或1),其长度可能可变。符号序列通过各个符号代码的串联来表示。
  • 若编码操作是单射的,则称该编码是可解码déchiffrable的。
  • 称一个编码为前缀码code préfixe,当且仅当没有一个编码是另一个编码的前缀。这是编码可解码的充分条件。
  • 记编码为 $φ$,其长度 $|φ|$ 表达如下:$|\phi|=\sum_{k=1}^K p_k\left|\phi\left(x_k\right)\right|$
    其中,$p_k$ 是符号 $x_k$ 的出现概率,$|φ(x_k)|$ 是与符号相关的代码字长度。

现存的编码


布莱叶编码(Code Braille)

为了让盲人能够阅读,布莱叶编码用 6 个点(6 位)来表示字母。

莫尔斯电码(Code Morse)

莫尔斯电码通过点和划的序列以及空格来表示字母。可以通过编码将其转换为二进制,点用 1 表示,划用 111 表示(遵循莫尔斯电码的定义),点与划之间用 0 表示,字母之间用 00 表示,单词之间用 000 表示。

ASCII 编码(Code ASCII)

在 ASCII 编码中,字符通过 7 位的序列表示,这足以涵盖大写字母、小写字母、符号和控制字符。

为了编码英语以外的语言所需的字符(如重音符等),存在扩展至 8 位的版本,例如 ISO 8859-15,可用于法语。

UTF-8

Unicode 标准(截至 2023 年)包含 149813 个字符,允许编码大量的字母、特殊字符、表情符号等。UTF-8 编码能够表示这些字符。

编码一个字符所需的位数是可变的,范围为 8 到 32 位。ASCII 编码的字符(西方最常用的)使用 8 位编码,而更罕见的字符则使用更多的位数。

整数的二进制表示(Écriture binaire des entiers)

将 1 到 7 的整数通过其二进制表示编码如图 1 所示。这是一个非前缀码。例如,位序列 101 可以同时表示 (5) 或 (2, 1)。图 2 所示的编码是前缀码(所有等长的编码都是前缀码)。可以通过编码 1 为 00 来简化该编码。整数的编码不一定对应于其二进制表示。

最优编码


在这一节,我们的目的是构建一个最优编码,即最小化编码长度的编码,其定义为:

即我们要在编码为前缀码的约束下,找到一个长度集合$l_k = \left|\phi\left(x_k\right)\right|$,满足:

处理此问题的第一步是将前缀码的约束替换为对其长度的约束。


克拉夫特-麦克米伦定理 Théorème de Kraft-McMillan

定理:对于一组长度为($l_k$)编码为前缀码,当且仅当以下条件成立时,前缀码满足:

证明:

正向:通过向下延展每个节点的叶子到最大编码长度 $L$ 来补全树。每个节点编码的叶子数为 $2^{L-l_k}$ 。由于是前缀码,不同节点的叶子集合互不相交,因此最多有 $2^L$ 叶子。于是有:

两边除以 $2^L$ ,得:

结论成立。

反向:从一个长度为 $L$ 的完全二叉树出发,假设长度按降序排列。对于每个长度 $l_k$ ,移除 $2^{l_k}$ 个叶子,并将这些叶子分配给对应长度的父节点(长度按降序,每组叶子属于同一子树)。当叶子数量足够时,即满足:

这种构造是可能的。


根据克拉夫特-麦克米伦定理,原本的问题转化为:

这是一个型如:

的问题。局部最优解$x^*$满足以下条件:

  • $\nabla f\left(x^{\star}\right)+\lambda \nabla g\left(x^{\star}\right)=0$
  • $g\left(x^{\star}\right) \leq 0$
  • $\lambda \geq 0$
  • $\lambda g\left(x^{\star}\right)=0$

根据这些条件,可得对于任意的$k$:

解得:

于是有:

$H$是离散概率分布$(p_k)_k$的熵。

若符号集合均匀分布,$p_k = 1/K$,则有 $H = log_2K$

长度 $l_k$ 可以取实数,因此比原问题中的整数约束更宽松。最优编码长度 $L^{\star}$ 满足以下关系:

反过来,存在一个前缀码(Shannon 编码) $\phi^{\dagger}$ 的长度为 $l_k^{\dagger}=\left\lceil l_k\right\rceil$ ,满足:

虽然这不一定是最优编码,但保证了最优编码长度 $L^{\star}$ 满足如下界限:

霍夫曼编码:构建最优编码


前一部分确认了存在一个长度不超过$H+1$的最优编码,但未提供其构造方法。霍夫曼算法能够保证构造出一个最优编码。

霍夫曼算法


霍夫曼算法以递归方式构建编码 $\phi$ 。它接收符号列表 $\left(x_1, \ldots, x_K\right)$ 及其对应的概率 $\left(p_1, \ldots, p_K\right)$ 作为输入。

  • 当 $K=2$ 时,给两个符号 $\left(a_1, a_2\right)$ 分配编码:

  • 当 $K>2$ 时,假设符号 $\left(a1, \ldots, a_K\right)$ 按概率降序排列 $\left(p_1, \ldots, p{K-1}, pK\right)$ 。将符号 $\left(a{K-1}, aK\right)$ 合并为一个新符号 $z$ ,其概率为 $p{K-1}+pK$ 。对于新符号集合 $\left(a_1, \ldots, a{K-2}, z\right)$ 构建霍夫曼编码 $\phi^{\star}$ 。然后设置:


例如

最优性证明


引理:对于一组给定的符号及其概率,总可以找到一个最优编码,使得概率最小的两个符号是兄弟节点。

证明:

  • 假设 $x$ 和 $y$ 是概率最小的两个符号,但它们不是兄弟节点。如果它们位于同一深度的不同分支,可以交换分支,使其成为兄弟节点,而不改变编码长度。于是存在一个满足条件的最优编码。
  • 假设 $l_x>l_y$ 。如果 $x$ 没有兄弟节点,可以将其上移一层,此时编码不是最优的。如果 $x$ 有兄弟节点(符号或子树),则可以将其与 $y$ 交换,从而减少编码长度。唯一的可能是 $x$ 和 $y$ 作为兄弟节点,并具有相同的长度,从而保留最优性。

通过递归证明。当 $K=2$ 时,结论显然成立。
假设对于 $K-1$ 个符号结论成立。霍夫曼算法为 $K$ 个符号生成了编码 $\phiK$ 。同时,存在一个满足最优条件的编码 $\psi_K$ 。在这两种情况下,符号 $x$ 和 $y$ 是兄弟节点(即它们的编码长度相同)。通过将这两个符号在 $\phi_K$ 中合并为一个符号 $z$ ,可以得到 $K-1$ 个符号的霍夫曼编码 $\phi{K-1}$ 。同样,在最优编码 $\psiK$ 中进行合并,也可以得到 $K-1$ 个符号的编码 $\psi{K-1}$ 。对于这两种情况,有以下等式成立:

由此可得:

实际上, $K$ 个符号的编码是通过向 $z$ 的编码添加一个比特来重新找到 $x$ 和 $y$ 的编码,这在平均意义上增加了 $p_x+p_y$ 的长度。

由于对于 $K-1$ 个符号的霍夫曼编码是最优的,得出:

从而可以推导出:

这证明了霍夫曼算法对 $K$ 个符号的最优性。

基于块的霍夫曼编码


为了更接近熵,可以对符号块进行编码,而不是单独对每个符号编码。此时,每个符号的平均长度上限为:

$N$是块的长度

局限性


霍夫曼编码的局限性包括以下需求:

  • 必须知道符号的概率。
  • 必须传递编码信息。
  • 或者必须传递概率信息。
  • 或者必须预先固定编码(例如,在某些压缩标准中)。

其他编码方法:

  • 算术编码(Code arithmétique)

    这种方法可以在不需要构造块(因此避免代码复杂性随块大小增长而增加)的情况下达到理论压缩界限。

  • Lempel-Ziv 编码

    一种基于字典的编码方法,将符号流分割为由先前观察到的序列和符号组成的片段。它还可以达到压缩界限,并能考虑符号间的相关性。

PNG 格式


PNG 格式是一种无损压缩的图像存储格式。像素通常通过 8 位或 16 位表示,支持 1 至 4 个通道(灰度、RGB、透明度)。

算法的两个步骤包括:

  • 预测步骤:用于降低熵。
  • DEFALTE 编码:结合 Lempel-Ziv 和霍夫曼编码的方法。

不同的预测方法

可以使用以下几种预测方法:

  • 0:无过滤,直接编码原始像素强度值。
  • 1:编码当前像素与像素 A 的差值。
  • 2:编码当前像素与像素 B 的差值。
  • 3:编码当前像素与像素 A 和 B 平均值(向下取整)的差值。
  • 4:编码当前像素与 A、B 或 C 中最接近 $A+B−C$ 值的像素的差值。

其中,预测方法对每一行是固定的。