区间编码

概念

信息熵

信息熵是用来衡量事物的信息量的,度量公式为:
H= ∑ i = 1 n p i l o g 1 p i \sum_{i=1}^{n}{p_i}log{\frac{1}{p_i}} i=1npilogpi1
n表示该事物有n中可能的情况, p i p_i pi表示每种情况发生的概率。
比如:某个人怀孕后,生的小孩是什么性别,这件事的信息熵是1.
因为生男孩,还是女孩的概率都为0.5
H = 0.5log2 + 0.5log2 = 1.
如果一件事情发生的可能性越多,每种可能的概率越分散,则信息熵越大,即信息量越多。
比如中国有14亿人,这个事件的概率是1,大叫都知道的事情,所以没啥信息量。
在等概率情况下,简单的理解就是,但需要使用多少bit来存储某个数据。

熵编码

熵编码就是根据信息论的原理,对原始数据进行编码。它可以达到数据压缩的效果。广泛应用在压缩算法中。
熵编码分三种:哈夫曼编码,区间编码(算数编码),ANS。

区间编码

区间编码就是利用区间的变化,来承载数据。

基础的区间编码过程

编码

为了简化计算过程,假设只有4个符号,分别为A,B,C,D且每个符号的概率相等,都为0.25
初始区间为[0,512],这样编码依次编码AABB,过程如下:
在这里插入图片描述
1.编码的时候,按照符号的概率划分区间大小。然后根据符号的顺序,得到对应的区间。
比如,约定A,B,C,D分别对应第1,2,3,4区间。但编码A后,就得到第一个区间,区间的大小等于原始区间*A的概率。
2.编码结束后,从区间取任意一个数都可以作为编码结果。比如,编码完后,区间变成[10,12],取11可以作为编码结果。

解码
编码区间解码出的符号新区间
11[0,512]A,因为11在第一个区间[0,128],所以解码出A[0,128]
11[0,128]A,因为11在第一个区间中[0,32][0,32]
11[0,32]B,因为11在第二个区间中[8,16][8,16]
11[8,16]B,因为11在第二个区间中[10,12]结束

区间编码的证明

原始区间编码后的区间
rangerange*p

一个区间可以容纳range个值,所以区间能够容纳的信息为log(range)
编码前后信息差量为log(range)-log(range*p)=-log(p),正好等于符号的信息量。

基础的区间编码面临的问题

  1. 区间在不断的缩小,到后面无法编码新的符号。
    区间容纳的信息有限,所以区间大小会趋于0,无法继续编码。
    解决方案:如果把数字转成二进制,可以看到,编码后,区间上下沿的部分高位相同,而且后续编码中,该部分不会再变化。因此可以输出出来,来对区间进行扩展。
    编码:
    在这里插入图片描述
    解码
    在这里插入图片描述

  2. 当区间上下沿,高位不同,但区间却比较小,比如
    [0111 1111,1000 0000],这是因为区间中存在延时数字,无法输出,导致区间无法扩展。这个也需要特殊的处理,可以将上下沿同时减去一个数后,在进行区间扩展。
    在这里插入图片描述

3.区间共享
在zstd,lzma这些算法,是先通过lz77获取三元组序列,在对三元组序列进行熵编码,三元组中的各个数据在概率上来说并没有关联性,所以分开统计概率在进行熵编码能够得到更高的压缩率。
如果各自创建一个区间,并根据概率去编码就会产生麻烦,因为区间编码每个符号时,输出的bit并不是固定的,这样各个数据通过熵编码后的输出混合在一起后,解码的时候没法区分
解决方法:
通过观察可以知道,解码时候的跟区间没关系,跟概率表有关系。不管用什么区间去编码,只要使用的是同一套概率表,解码时,就能够解码出正确的符号。所以可以各个数据共用一个区间,然后应用各自的概率表对区间进行编码并输出。
4.固定概率 or 预测概率

  1. 固定概率:
    可以先统计出三元组中各个符号的概率,然后应用熵编码进行编码。
    缺点:需要提前扫描全部的三元组,增加计算量,同时输出的数据中需要保存概率表
  2. 预测概率
    可以预设一个概率,然后编码的过程中,不断的调整概率表。如果不算固定概率方式中概率表的存储空间,这种方式的压缩率会稍微低一点,因为概率不准确。

备注:区间编码的原理比较简单,但是真正能够在压缩中使用时,就得解决上述问题,上述问题对应的解决方法,不容易理解,也不好表达,而且区间编码资料本身就很少,作者自己也是花了很大功夫,突然顿悟才想到解决方案。大家如果从事区间编码研究的,可以参考一下我的代码,看能得到灵感不。
https://github.com/sunny-shu/rangecode。
另外第三个问题的解决办法,在这个项目中,https://github.com/sunny-shu/lzrc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值