读书笔记|《数据压缩入门》—— 柯尔特·麦克安利斯 亚历克斯·海奇

news2025/1/12 20:50:55

前言:在接触文本隐写研究领域时了解到这本书。本书可算作《数据压缩》的入门书籍之一,这本书对熵编码、变长编码、统计编码、自适应统计编码、字典编码、上下文编码等常用编码方式的定义及来源进行介绍,对不同场景下不同格式的压缩数据有针对性地分析,笔风幽默,强烈推荐!本书中共有15个章节,本人主要阅读了前9个章节,以下是阅读本书过程中的一些笔记,供大家参考。

目录

  • ◆ 序
  • ◆ 第1章 并非无趣的一章
  • ◆ 第2章 不容错过的一章
  • ◆ 第3章 突破熵
  • ◆ 第4章 VLC
  • ◆ 第5章 统计编码
  • ◆ 第6章 自适应统计编码
  • ◆ 第7章 字典编码
  • ◆ 第8章 上下文数据转换
  • ◆ 第9章 数据建模
  • ◆ 第13章 序列化数据

◆ 序

无损方法
• 去掉重复数据(LZ算法)
• 熵压缩(哈夫曼编码、算术编码)

有损方法
• 降低精度(截断或降采样)
• 图像 / 视频压缩
• 音频压缩

◆ 第1章 并非无趣的一章

  • 数据压缩无非是用最紧凑的方式来表示数据。

  • 数据压缩算法有5类:变长编码(variable-length codes,VLC)、统计压缩(statistical compression)、字典编码(dictionary encodings)、上下文模型(context modeling)和多上下文模型(multicontext modeling)。所有这5类算法都有很多变种。

  • 1948年,香农又发表了《通信的数学理论》,在这篇论文中他详细论述了发送者怎样对要发送的信息进行编码才能达到最佳效果,由此开创了信息论(information theory)这一全新的学术领域。对消息进行编码有多种方式,“字母表”与“摩尔斯码”只是其中常见的两种。但是对每一个特定的消息来说,都有一个最佳的编码方式,这里的“最佳”指的是传递消息时用到的字母或者符号(也可以说是二进制位,即信息的单位)最少。至于这里说的“最少”到底是多少,则取决于消息所包含的信息内容。香农发明了一种度量消息所携带信息内容的方法,并称之为信息熵(information entropy)。数据压缩其实是香农的研究工作的一项实际应用,它所研究的问题是,“在保证信息能恢复的前提下,我们能将消息变得多么紧凑”。

  • 对数据进行压缩,通常有两个思路:

    • 减少数据中不同符号的数量(即让“字母表”尽可能小);
    • 用更少的位数对更常见的符号进行编码(即最常见的“字母”所用的位数最少)。

60年来的数据压缩研究都可以归结到上面两个重要思路上,数据压缩中的每一个算法都聚焦于解决这两件事情中的一件。每一个压缩算法,要么通过打乱符号或减少符号的数量,将数据转换得更便于压缩;要么利用其中一些符号比其他符号更常见的事实,通过用最少的位数编码最常见的符号,实现压缩的目的。

  • 虽然数据压缩的思路简单明了,但在实际应用中数据压缩很复杂。其原因在于,由于要压缩的数据的类型不同,针对上述两条思路中的每一条,能采用的方法都有很多。因此,进行实际的数据压缩时,需要综合考虑以下因素。

    • 不同数据的处理方法不同,比如压缩一本书中的文字和压缩浮点型的数,其对应的算法就大不相同。
    • 有些数据必须经过转换才能变得更容易压缩。
    • 数据可能是偏态的。例如,夏天的整体气温偏高,也就是说高气温出现的频率比接近零度的气温出现的频率高很多。
  • 互联网诞生的那一年,也就是1978年。

  • 在很长一段时间内,莱娜图是用来测试图像压缩算法的标准测试图。幸运的是,从此以后,很少再出现这样有争议性的图像语料库。(我们两位作者则更喜欢使用柯达公司的图像测试集。)然而即使是今天,仍然有很多图像压缩方面的论文将莱娜图用作检验算法的标准。

◆ 第2章 不容错过的一章

  • 数据压缩所做的无非就是尽可能减少表示特定数据集时所需的二进制位数量。

  • 根据信息论的观点,一个数值所包含的信息内容等于,为了在一个集合中唯一地确定这个数值,需要做出的二选一(是/否)决定的次数。

  • 给定任意一个整数,我们都能将它转换为二进制形式。然而令人遗憾的是,给定一个整数,如果不经过二进制转换这一过程,我们很难直接知道它需要占几个二进制位。转换过程很无趣,但好在数学家已准备了下面的公式,让我们可以更轻松地处理这个问题:
    L O G 2 ( x ) = c e i l ( l o g ( x + 1 ) / l o g ( 2 ) ) LOG2(x) = ceil(log(x+1)/log(2)) LOG2(x)=ceil(log(x+1)/log(2)) : 表示一个数所需要的二进制位数

在这里插入图片描述

  • 给定任意一个十进制整数,通过计算它对应的LOG2函数的值,我们就能知道用二进制来表示这个数最少需要多少二进制位。香农将一个变量对应的LOG2函数的值定义为它的熵(entropy),也就是用二进制来表示这个数所需的最少二进制位数。

  • 数值的LOG2表示形式虽然高效,但对于制造计算机元件的方式来说并不实用。这其中的问题在于,如果用最少的二进制位数来表示一个数,在解码相应的二进制字符串时会产生混乱(因为我们并不知道该数对应的LOG2长度),会与硬件的执行性能相冲突,两者不能兼顾。现代计算机采用了折中的方案,用固定长度的二进制位数来表示大小不同的整数。最基本的存储单元是一个字节,由8个二进制位组成。在现代编程语言中,通常可用的整数的存储类型包括:短整型16个二进制位、整型32个二进制位、长整型64个二进制位。因此,对于十进制数10,虽然其对应的二进制数为1010,但在实际存储中是短整型,在计算机中的实际表示为0000000000001010。显然,这样做浪费了很多的二进制位。

◆ 第3章 突破熵

  • 香农博士将一个数对应的LOG2函数值称为该数的熵,也就是表示这个数所需要的最少二进制位数。他进一步将熵的概念(既然已经提出了这一术语了,为什么不重复利用呢……)扩展到整个数据集,也就是表示整个数据集所需要的最少二进制位数。他完成了所有这方面的数学工作,并给出了下面这个优美的公式来计算一个集合的熵: H ( S ) = − ∑ i = 1 n p i ⋅ l b ( p i ) , l b ( p i ) = l o g ( p i ) / l o g ( 2 ) ) H(S) = -\sum_{i=1}^{n}{p_{i}} · {lb(p_{i})}, lb(p_{i}) = log(p_{i})/log(2)) H(S)=i=1npilb(pi),lb(pi)=log(pi)/log(2))

在这里插入图片描述

  • https://rosettacode.org/wiki/Entropy 熵的各种语言实现。

  • 为了使表示某个数据集所需的二进制位数最少,数据集中的每个符号平均所需的最小二进制位数就是熵。

  • 从本质上来说,香农所定义的熵,是以一种倒排序的方式建立在数据流中每个符号出现概率的估算之上的。
    总的来说,一个符号出现得越频繁,它对整个数据集包含的信息内容的贡献就会越少,这看起来似乎完全违背直觉。

  • 数据集中包含的总体信息很少,因此对应的熵值也很小。

  • 突破熵的关键在于,通过利用数据集的结构信息将其转换为一种新的表示形式,而这种新表示形式的熵比源信息的熵小。

  • 需要记住的是,熵定义的只是在对数据流进行编码时,每个符号平均所需的最小二进制位数。这就意味着,有些符号需要的二进制位数比熵小,而有些符号需要的二进制位数则比熵大。

  • 柯尔莫哥洛夫复杂性(Kolmogorov complexity),度量的是确定一个对象所需要的计算资源。

◆ 第4章 VLC

  • 摩尔斯码根据各个符号在英语中出现的概率来为其分配点和划。一个符号出现得越频繁,其对应的编码就越短。即使是追溯到19世纪,这也是对符号分配变长编码(variable-length codes,VLC)的最初实现之一,其目的则在于减少传输信息过程中所需要的总工作量。

  • 为了进行数据压缩,我们的目的很简单:给定一个数据集中的符号,将最短的编码分配给最可能出现的符号。

  • 设计VLC集的码字时,必须考虑两个原则:一是越频繁出现的符号,其对应的码字越短;二是码字需满足前缀性质。

◆ 第5章 统计编码

  • 统计编码算法通过数据集中符号出现的概率来进行编码使结果尽可能与熵接近。

  • 哈夫曼编码:在这里插入图片描述

  • 算术编码:
    在这里插入图片描述

  • 主流的统计编码方法有哈夫曼编码和算术编码,但ANS(非对称数字系统编码)改变了一切。虽然它在数据压缩领域里出现的时间还不长,但是已开始取代过去20多年里占据主流地位的哈夫曼编码和算术编码。例如,ZHuff、LZTurbo、LZA、Oodle和LZNA这些压缩工具已开始使用ANS。鉴于其速度和性能,ANS成为主要的编码方法似乎只是时间问题。实际上,在2013年,这一算法又出现了一个被称为有限状态熵(Finite State Entropy,FSE)的更注重性能的版本,它只使用加法、掩码和移位运算,使ANS对开发人员更具吸引力。它的性能是如此强大,以至于2015年推出了一款名为LZFSE的GZIP变种,作为苹果下一代iOS版本的核心API。

◆ 第6章 自适应统计编码

  • 数据中总会存在某种类型的局部偏态(locality-dependent skewing),将某些符号、想法或者单词集中在数据集的某个子区间里。

◆ 第7章 字典编码

  • 虽然信息论的创立是在20世纪40年代,哈夫曼编码的提出是在20世纪50年代,而互联网的出现在20世纪70年代,但是直到20世纪80年代,数据压缩才真正引起了人们的兴趣。随着互联网的快速发展,人们分享的内容已不再局限于文字,而是开始分享比文本大得多的照片以及其他格式的数据。同时这种分享又发生在网络带宽有限、存储昂贵的时期,数据压缩因此成了缓解这些瓶颈的关键。虽然VLC一直都在发挥作用,但它与熵绑定的事实也限制了数据压缩未来的发展。因此,当大多数研究人员在尝试寻找更有效的VLC技术时,也有少数研究人员选择了不同的路,他们找到了使统计压缩可以更有效地预处理数据的新方法。这种新方法通常被称为“字典转换”(dictionary transforms),它完全改变了人们对数据压缩的认知。突然间,压缩变成了一种对各种类型的数据都有用的算法。它的应用范围非常广泛,事实上今天所有的主流压缩算法(比如GZIP或者7-Zip)都会在核心转换步骤中使用字典转换。

在这里插入图片描述

  • 字典编码的关键是要找到那些能生成最小熵的词。1977年,两位研究人员Abraham Lempel和Jacob Ziv提出了几种解决“理想分词”问题的方法。这些算法根据提出的年份分别被命名为LZ77 和LZ78,它们在找出最佳分词方面非常高效,30多年来还没有其他算法可以取代它们。
    LZ算法的变体们

◆ 第8章 上下文数据转换

  • 给定一组相邻的符号集,对它们进行某种方式的变换使其更容易压缩。我们通常称这样的变换为“上下文变换”(contextual transform),因为在思考数据的理想编码方式时,这些方法考虑到了邻近符号的影响。
    这些变换的目标是一致的,即通过对这些信息进行某种方式的变换,使统计编码算法对其进行压缩时更高效。

  • 变换数据的方法有很多种,但其中有3种对现代的数据压缩来说最为重要,即行程编码(run-length encoding,RLE)、增量编码(delta coding)和伯罗斯–惠勒变换(Burrows-Wheeler transform,BWT)

  • 增量编码的目的就是缩小数据集的变化范围。更确切地说,是为了减少表示数据集中的每个值所需要的二进制位数。

◆ 第9章 数据建模

  • LZ、RLE、增量编码以及BWT这些算法都是基于这样的假设:数据的相邻性与它的最佳编码方式有关。

(其中,游程编码(Run-Length Encoding)比较适合针对数据中冗余部分比较多的情况)

◆ 第13章 序列化数据

  • 序列化是将高级数据对象转化为二进制字符串的过程(与之相反的过程则称为反序列化)

相关资料

  1. [笔记] 数据压缩入门(Understanding Compression) | Fu Zhe’s Blog (fuzhe1989.github.io)
  2. LZW压缩算法原理解析 - 个人文章 - SegmentFault 思否

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1058220.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023-10-03 LeetCode每日一题(买卖股票的最佳时机 III)

2023-10-03每日一题 一、题目编号 123. 买卖股票的最佳时机 III二、题目链接 点击跳转到题目位置 三、题目描述 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 **注意…

【考研英语】2011 年英语(一)排序题思路复盘(费曼学习法)

文章目录 引言一、找语段特征词二、确定位置写在最后 引言 英语一中的新题型之一 —— 排序题,我是看的刘琦老师的方法课,她用的 2011 年的真题来讲解方法。讲完让我们回去用“费曼学习法”复盘以下,我个人感觉是一个不错的方法,…

leetCode 45.跳跃游戏 II 贪心算法

45. 跳跃游戏 II - 力扣(LeetCode) 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i j] 处: 0 &…

踩坑笔记 MySQL分页排序查询(Order by limit)导致数据丢失和重复

文章目录 背景现象原因解决方案 背景 分页查询排序后的数据,是一个非常常见的业务场景;但当使用不唯一的字段排序时,分两页查询的数据可能出现数据重复和丢失的错觉。 在执行查询时,MySQL会根据查询优化器的决策来确定数据的检索…

RabbitMQ安装与简单使用

安装 下载资源 可以访问官网查看下载信息rabbitmq官网 选择合适的版本,注意:rabbitmq需要下载一个Erlang才能使用 我自己是在一下两个连接中下载的 rabbitmq 3.8.8 erlang 21.3.8.15 需要下载其他版本的同学注意erlang版本是否匹配,可以访…

axb_2019_brop64

axb_2019_brop64 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)64位,只开了NX __int64 repeater() {size_t v1; // raxchar s[208]; // [rsp0h] [rbp-D0h] BYREFprintf("…

1200*C. Make It Good(二分 || 贪心)

Make It Good - 洛谷 Problem - 1385C - Codeforces 思路一&#xff1a; 二分答案&#xff0c;每次check从mid1开始&#xff0c;判断能否形成要求的序列。 #include<bits/stdc.h> using namespace std; #define int long long const int N2e55; int t,n,a[N]; bool che…

栈的应用场景(三)

最小栈 1.题目2.画图分析3.代码实现 1.题目 2.画图分析 3.代码实现 package Stack;import java.util.Stack; public class MinStack {private Stack <Integer> stack;private Stack <Integer> MinStack;public MinStack() {stack new Stack<>();MinStack …

JAVA学习(2)-全网最详细~

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

jarvisoj_level5

jarvisoj_level5 Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x3fe000)64位&#xff0c;只开了NX ssize_t vulnerable_function() {char buf[128]; // [rsp0h] [rbp-80h] BYREFwrite(1, "Input:\…

【网络通信三要素】TCP与UDP快速入门

网络通信三要素 1.什么是网络编程&#xff1f; 可以让设备中的程序&#xff0c;与网络上其他设备中的程序进行数据交互&#xff0c;从而实现网络通信的手段&#xff0c;java.net.*包下提供了网络编程的解决方案 2.基本的通信架构 基本的通信架构有2种形式&#xff1a;CS架构…

【Spring MVC】MVC如何浏览器请求(service方法)

文章目录 1. DispatcherServlet 的 service 方法1.1. processRequest 方法1.2. doService 方法 背景&#xff1a;平时我们学习 MVC 重点关注的时DispatcherServlet 的 doDispatcher 方法&#xff0c;但是在 doDispatcher 方法之前 还有请求处理的前置过程&#xff0c;这个过程…

javaWeb学生信息管理

一、引言 学生信息管理系统是基于Java Web技术开发的一个全栈应用&#xff0c;用于管理学生的基本信息。本系统采用Eclipse作为开发工具&#xff0c;Navicat用于MySQL数据库管理&#xff0c;运行在JDK1.8、Tomcat9.0、MySQL8.0环境下。前端采用JavaScript、jQuery、Bootstrap4…

大语言模型之十四-PEFT的LoRA

在《大语言模型之七- Llama-2单GPU微调SFT》和《大语言模型之十三 LLama2中文推理》中我们都提到了LoRA&#xff08;低秩分解&#xff09;方法&#xff0c;之所以用低秩分解进行参数的优化的原因是为了减少计算资源。 我们以《大语言模型之四-LlaMA-2从模型到应用》一文中的图…

14:00面试,14:06就出来了,这问的过于变态了。。。

前言 刚从小厂出来&#xff0c;没想到在另一家公司我又寄了。 在这家公司上班&#xff0c;每天都要加班&#xff0c;但看在钱给的比较多的份上&#xff0c;也就不太计较了。但万万没想到5月一纸通知&#xff0c;所有人不准加班了&#xff0c;不仅加班费没有了&#xff0c;薪资…

Linux: 进程(控制)

目录 1.进程的创建 1.1fork函数 1.2fork创建子进程,OS做了什么&#xff1f; 1.3为什么要写实拷贝&#xff1f; 2.进程的终止 2.1进程终止&#xff0c;操作系统做了什么&#xff1f; 2.2进程常见的退出方式 2.3进程常见的退出方法 3.进程的等待 3.1为什么进行进程等待…

SpringCloud Alibaba - Seata 部署 TC 服务,并集成微服务

目录 一、Seata 架构 1.1、Seata 架构重要角色 1.2、部署 TC 服务 1.2.1、前言 1.2.2、下载 seata-server 包&#xff0c;解压 1.2.3、修改配置 1.2.4、在 nacos 中添加配置 1.2.5、创建数据库表 1.2.6、启动 TC 服务 1.3、微服务集成 Seata 1.3.1、引入依赖 1.3.2、…

面试题:熟悉设计模式吗?谈谈简单工厂模式和策略模式的区别

刚刚接触设计模式的时候&#xff0c;我相信单例模式和工厂模式应该是用的最多的&#xff0c;毕竟很多的底层代码几乎都用了这些模式。自从接触了一次阿里的公众号发的一次文章关于 DDD的使用 以后&#xff0c;就逐渐接触了策略模式。现在在项目中运用最多的也是这几种设计模式了…

使用mysql的cmd窗口,运行项目中的mapper层xml里的sql语句,查看运行结果

使用mysql的cmd窗口&#xff0c;运行项目中的mapper层xml里的sql语句&#xff0c;查看运行结果 项目代码或者从控制台复制sql语句从控制台搜索方式 运行效果或者使用idea的console窗口运行查看结果点击进入&#xff0c;查看表结构与字段 其他技巧根据from 表名寻找对应的sql代码…

Linux系统编程系列之线程属性

一、什么是线程属性 线程属性就是线程的属性&#xff0c;是一个用于控制线程行为和功能的参数集合。它可以影响线程的优先级、调度、同步行为和资源管理等方面。线程有许多属性&#xff0c;如分离属性&#xff0c;继承策略&#xff0c;调度策略等。看图 二、线程属性的特性 1、…