彼节者有间,而刀刃者无厚;以无厚入有间,恢恢乎其于游刃必有余地矣 ----- 庖丁解牛
前言:随着移动互联网、IoT、5G等的应用和普及,一步一步地我们走进了数字经济时代。随之而来的海量数据将是一种客观的存在,并发挥出越来越重要的作用。时序数据是海量数据中的一个重要组成部分,除了挖掘分析预测等,如何高效的压缩存储是一个基础且重要的课题。同时,我们也正处在人工智能时代,深度学习已经有了很多很好的应用,如何在更多更广的层面发挥作用?深度学习的本质是做决策,用它解决具体的问题时很重要的是找到契合点,合理建模,然后整理数据优化loss等最终较好地解决问题。在过去的一段时间,我们在用深度强化学习进行数据压缩上做了一些研究探索并取得了一些成绩,已经在ICDE 2020 research track发表(Two-level Data Compression using Machine Learning in Time Series Database)并做了口头汇报。在这里做一个整体粗略介绍,希望对其它的场景,至少是其它数据的压缩等,带来一点借鉴作用。
1. 背景描述
1.1 时序数据
时序数据顾名思义指的是和时间序列相关的数据,是日常随处可见的一种数据形式。下图罗列了三个示例 a)心电图,b)股票指数,c)具体股票交易数据。
关于时序数据库的工作内容,简略地,在用户的使用层面它需要响应海量的查询,分析,预测等;而在底层它则需要处理海量的读写,压缩解压缩,采用聚合等操作,而这些的基本操作单元就是时序数据
可以想象,任何电子设备每天都在产生各种各样海量的时序数据,需要海量的存储空间等,对它进行压缩存储及处理是一个自然而然的方法。而这里的着重点就是如何进行更高效的压缩。
1.2 强化学习
机器学习按照样本是否有groundTruth可分为有监督学习,无监督学习,以及强化学习等。强化学习顾名思义是不停得努力得去学习,不需要groundTruth,真实世界很多时候也没有groundTruth,譬如人的认知很多时间就是不断迭代学习的过程。从这个意义上来说,强化学习是更符合或更全面普遍的一直处理现实世界问题的过程和方法,所以有个说法是:如果深度学习慢慢地会像C/Python/Java那样成为解决具体问题的一个基础工具的话,那么强化学习是深度学习的一个基础工具。
强化学习的经典示意图如下,基本要素为State,Action,和Environment。基本过程为:Environment给出State,Agent根据state做Action决策,Action作用在Environment上产生新的State及reward,其中reward用来指导Agent做出更好的Action决策,循环往复….
而常见的有监督学习则简单很多,可以认为是强化学习的一种特殊情况,目标很清晰就是groudTruth,因此对应的reward也比较清晰。
强化学习按照个人理解可以归纳为以下三大类:
- DQN:Deep Q network,比较符合人的直观感受逻辑的一种类型,它会训练一个评估Q-value的网络,对任一state能给出各个Action的reward,然后最终选择reward最大的那个action进行操作即可。训练过程通过评估"估计的Q-value“”和“真正得到的Q-value”的结果进行反向传递,最终让网络估计Q-value越来越准。
- Policy Gradient:是更加端到端的一种类型,训练一个网络,对任一state直接给出最终的action。DQN的适用范围需要连续state的Q-value也比较连续(下围棋等不适用这种情况),而Policy Gradient由于忽略内部过程直接给出action,具有更大的普适性。但它的缺点是更难以评价及收敛。一般的训练过程是:对某一state,同时随机的采取多种action,评价各种action的结果进行反向传递,最终让网络输出效果更好的action。
- Actor-Critic:试着糅合前面两种网络,取长补短,一方面用policy Gradient网络进行任一state的action输出,另外一方面用DQN网络对policy gradient的action输出进行较好的量化评价并以之来指导policy gradient的更新。如名字所示,就像表演者和评论家的关系。训练过程需要同时训练actor(policy Graident)和critic(DQN)网络,但actor的训练只需要follow critic的指引就好。它有很多的变种,也是当前DRL理论研究上不停发展的主要方向。
2. 时序数据的压缩
对海量的时序数据进行压缩是显而易见的一个事情,因此在学术界和工业界也有很多的研究和探索,一些方法有:
- Snappy:对整数或字符串进行压缩,主要用了长距离预测和游程编码(RLE),广泛的应用包括Infuxdb;
- Simple8b:先对数据进行前后delta处理,如果相同用RLE编码;否则根据一张有16个entry的码表把1到240个数(每个数的bits根据码表)pack到8B为单位的数据中,有广泛的应用包括Infuxdb;
- Compression planner:引入了一些general的压缩tool如scale, delta, dictionary, huffman, run length和patched constant等,然后提出了用静态的或动态办法组合尝试这些工具来进行压缩;想法挺新颖但实际性能会是个问题;
- ModelarDB:侧重在有损压缩,基于用户给定的可容忍损失进行压缩。基本思想是把维护一个小buff,探测单前数据是否符合某种模式(斜率的直线拟合),如果不成功,切换模式重新开始buff等;对支持有损的IoT领域比较合适;
- Sprintz:也是在IoT领域效果会比较好,侧重在8/16 bit的整数处理;主要用了scale进行预测然后用RLC进行差值编码并做bit-level的packing;
- Gorilla:应用在Facebook高吞吐实时系统中的当时sofa的压缩算法,进行无损压缩,广泛适用于IoT和云端服务等各个领域。它引入delta-of-delta对时间戳进行处理,用xor对数据进行变换然后用Huffman编码及bit-packing。示例图如下。
- MO:类似Gorilla,但去掉了bit-packing,所有的数据操作基本都是字节对齐,降低了压缩率但提供了处理性能;
- …
还有很多相关的压缩算法,总的来说:
- 它们基本都是支持单模式,或者有限的偏static的模式进行数据的压缩;
- 很多为了提高压缩率,都用了bit-packing (甚至有损压缩),但对越来越广泛使用的并行计算不太友好;
3. 两阶段的基于深度学习的压缩算法
3.1 时序数据压缩的特性
时序数据来源于IoT、金融、互联网、业务管理监控等方方面面,形态特性相差很多,然后对数据精确度等的要求也不尽相同。如果只能有一种统一的压缩算法进行无差别对待地处理,那应该是基于无损的、用8B数据进行数据描述的算法。
下图是阿里云业务中一些时序数据的示例,无损是从宏观还是微观层面,数据的pattern都是五花八门的,不仅仅是形状曲线,也包括数据精度等。所以压缩算法很有必要支持尽量多的一些压缩模式,然后又可以既有效又经济地选择其中一种进行压缩。
对于一个大型的商用的时序数据压缩算法,需要重点关注三个重要的特性:
- Time correlation:时序数据有很强的时间相关性,然后对应的数据基本上是连续的。采样间隔通常是1s,100ms等;
- Pattern diversity:如上图,pattern及特性差距会很大;
- Data massiveness:每天、每小时、每秒需要处理的数据量都是海量的,总体处理数据至少是在每天10P的level,对应的压缩算法需要高效且有高吞吐率。
3.2 新算法核心理念
追本溯源,数据压缩的本质可分为两阶段:首先Transform阶段把数据从一个空间转化到另外一个更规则的空间,然后在差值编码阶段用各种各样的办法较好的标识变换后的差值。
根据时序数据的特点,可以定义以下6个基本的transform primitives(可扩展)。
然后定义以下3中基本的differential coding primitives(可扩展)。
接下来把上面的两种tools排列组合进行压缩?这样可行但效果肯定是不太好,因为模式选择和相关参数的cost比重太高了,需要2B(primitive choice + primitive parameter)的控制信息,占了8B需要表达数据的25%。
更好的应该是对数据的特性进行抽象化分层表达,示意图如下。创建一个控制参数集较好的表达所有的情况,然后在全局(一个timeline)层面选择合适的参数来确定一个搜索空间(只包含少量的压缩模式,譬如4种);然后在具体进行每个点的压缩时,遍历从中选择出最好的那一种压缩模式进行压缩。控制信息的比重在~3%。
3.3 两阶段压缩框架AMMMO
AMMMO(adatpive multiple mode middle-out)整体过程分为两个阶段,第一阶段确定当前这条时间线的总体特性(确定9个控制参数的具体值);然后在第二阶段在少量的压缩模式中遍历并查找最后的一种进行压缩,具体框图如下。
第二阶段的模式选择没有难度,逻辑简单适合高效率执行;第一阶段确定各参数值(9个这里)得到合适的压缩空间有比较大的挑战,需要从理论上的300K多个排列组合选择里找出合适的那一个。
3.4 基于规则的模式空间选择算法
可以设计一种算法,譬如创建各个压缩模式的效果记录牌(scoreboard),然后遍历一个timeline里的所有点并进行分析记录,然后再经过统计分析比较等选择最好的模式。一些显而易见的问题有:
- 选择的评估指标是否理想?
- 需要人工去思考并编写程序,有较多的实现,debug和maintain的工作量;
- 如果算法中的primitive,压缩模式等做了改变,整个代码都需要重构,基于上面的选择不是理论选择,需要一种自动且较智能的方法支撑不停的演化等。
4. 深度强化学习
4.1 问题建模
简化上面的整个模式空间选择算法如下图,我们可以把这个问题等同于多目标的分类问题,每个参数就是一个目标,每个参数空间的取值范围就是可选择的类目数。深度学习在图像分类,语义理解等方面证明了它的高可用性。类似地,咱们也可以把这里的模式空间的选择问题用深度学习来实现,把它当做一个multi-label的classification问题。
用什么样的网络?考虑到识别的主要关系是delta/xor, shift,bitmask等为主,cnn不恰当,full-connect的mlp比较合适。相应地,把一条时间线上的所有点,如果1小时就是3600个共3600*8B,有些太多,考虑到同一timeline内部一段一段的相似性,把32个点作为一个最基本的处理单元。
接下来,怎么去创建训练样本?怎么给样本寻找label呢?
在这里我们引入了强化学习,而不是有监督的学习去训练,因为:
- 去创建有label的样本很难:32个样本256B,理论上sample有256^256中可能性,对每个这种样本,需要遍历300K的可能性才能找出最好的那一个。创建及选择sample,create label的工作量都非常大;
- 这不是普通的one-class-label问题:给定一个样本,并不是有唯一的最好的一个结果,很有可能很多的选择都能取得相同的压缩效果;N class(N基本不可知)的训练又增加了很多难度;
- 需要一种自动化的方法:压缩的tool等参数选择很有可能是需要扩展的,如果发生整个训练样本的创建等都需要重新再来。需要一种自动化的办法。
用什么样的强化学习呢?DQN,policy gradient, 还是actor-critic? 如前面分析,DQN是不太适合reward/action不连续的的情况,这里的参数,譬如majorMode 0和1是完全不同的两种结果,所以DQN不合适。此外,压缩问题一方面不容易评价另外网络也没有那么复杂,不需要actor-critic。最终我们选择了policy gradient。
Policy gradient常见的loss是用一个慢慢提高的baseline作为衡量标准来反馈当前的action是否合适,但这里并不太合适(效果尝试了也不太好),因为这里sample的理论block(256^256) state太多了一些。为此,我们专门设计了一个loss。
得到了每个block的参数后,考虑到block的相关性等。可以用统计的办法,聚合得到整个timeline的最终参数设置。
4.2 深度强化学习网络框架
整体的网络框架示意图如下:
在训练端:随机选择M个block,每个block复制N份,然后输入到有3个隐含层的全连接网络中,用region softmax得到各参数各种choice的概率,然后按照概率去sample每个参数的值,得到参数后输入到底层的压缩算法进行实际压缩并得到压缩值。复制的N个block相互比较计算loss然后做反向传播。loss的整体设计为:
fn(copi)描述了压缩效果,比N个block的均值高就正反馈,Hcs(copi)是交叉熵,希望得分高的概率越大越确定越好;反之亦然。后面的H(cop)是交叉熵作为正则化因子来尽量避免网络固化且收敛到局部最优。
在推理端,可以把一个timeline的全部或局部block输入到网络中,得到参数,做统计聚合然后得到整个timeline的参数。
5. 结果数据
5.1 实验设计
测试数据部分一方面随机选取了阿里云业务IoT和server两个大场景下共28个大的timeline;另外也选取了时序数据分析挖掘领域最通用的数据集UCR。基本信息如下:
对比算法选取了比较有对比性的Gorilla,MO和Snappy。因为AMMMO是两阶段的压缩算法框架,第一阶段的参数选择可以有各种各样的算法,这里选用了Lazy(简单粗暴的设置一些普世参数),rnd1000Avg(随机1000次取效果平均值),Analyze(用人工代码的算法)和 ML(深度强化学习的办法)等。
5.2 压缩效果对比
首先从整体压缩率来看,AMMMO两阶段自适应多模式的压缩比起Gorila/MO等有明显的效果提升,平均压缩率提升在50%左右。
然后ML的效果怎么样呢?下图在ML的视野对比了测试集B上的压缩效果,总的来说,ML相比人工精心设计的算法略好,比随机平均等明显好很多。
5.3 运行效率
AMMMO借鉴了MO的设计思想,移除了bit-packing,不仅仅在CPU上能高速运行,也特别适合于并行计算平台如GPU。此外AMMMO分两阶段,其中第一阶段的性能会差一些,但很多时候,譬如对一个特定的设备过去2天的数据,全局压缩参数是可以复用的。下图描述了整体的性能对比,实验环境为“Intel CPU 8163 + Nvidia GPU P100",其中AMMMO的代码使用了P100。
从上图中看出,AMMMO在压缩端和解压缩端都能达到GB/s的处理性能,性能指标还是很不错的。
5.4 算法学到的效果
深度强化学习训练的网络从最终效果上看着不错,那它是不是真的有学到有意义的内容呢?下标对比了3中算法在几个测试集上的表现,可以看出,ML版本的参数选择和分析算法/最优效果选择是差不多的,特别是在byte offset和majorMode的选择上。
这种压缩的全连接网络参数表象会是怎么样的?对第一层进行了参数heatmap可视化(正的参数为红色,负的为蓝色,值越大颜色越亮),如下:
可以明显看到32个点在相同的byte上有很多规则的操作,竖线(如果跨越byte则混淆情况),可以认为是在对应的位置上做delta或xor运算等。然后数字变动最大的Byte0的参数也比较活跃。
综上,深度学习学到的东西还是挺有解释性的。
6. 相关人员和致谢
在整个过程中,Yanqing peng,飞刀,汪晟,乐予,麦君和Yue Xie等一起付出了很多的努力,特别感谢飞刀老师的方向指引和总体判断;
此外,特别感谢矽厉等在工作中给予的支持,感谢德施等在业务上给予的帮助和支持。