增强分析是指以机器学习为基础的数据分析和BI功能,包含智能数据发现、增强数据准备、增强数据分析等模块。目前增强分析已经在BI中广泛使用,Gartner 认为,到2020年,增强分析将成为新用户购买BI产品、数据科学和机器学习平台,以及嵌入式分析的主要驱动力。
通过增强分析功能,能够极大地降低用户的数据分析门槛,使一个非专业人员也能够轻松完成数据预处理和数据分析的整个分析流程。
智能问答功能是增强分析中非常重要的一个子任务,其目的是让用户能够通过一句自然语言就能自动生成对应的图表。比如,提问“2015年各地区的销售额?”系统自动就会展示出如下的结果:
在学术界,这个任务叫做 NL2SQL,目前已经有很多研究。英语环境通常采用的是WikiSQL和 Spider,而中文目前还没有统一的数据集。在 WikiSQL 数据集上,Leaderboard 中的方法都是把这个任务转化为槽值填充,然后利用深度学习的方法训练多个不同的子模型对每个槽位进行填充,比如作为SOTA模型的X-SQL。
虽然在WikiSQL 数据集上,模型的效果已经超越了人类,但是在产品化的过程中, WikiSQL过于简单,比如它只支持1个查询目标,1个聚合函数和最多4个过滤条件,不支持分组。而在实际使用中,有多个查询目标以及包含分组字段的问题比比皆是,比如“各省份的人口”,“每年的人口”,所以只是采用 X-SQL 的方法无法满足工业的需要;Spider 数据集中不仅支持对分组进行提问,而且支持跨表join,但是 SOTA 模型的测试准确率只有55%,还无法满足产品化的效果。
此外,在实际提问时,时间是一个很特殊并且重要的因素,比如用户可能会问“近七天的总销售额”,“2019/2018年的销售额”,“今年前三个季度的总销售额”等等,这些内容在数据集中都没有覆盖。
基于以上这些数据集的局限性,百分点智能问答的任务既需要让模型能够准确地提取问题中的槽位信息,又需要无监督的语义分析方法,只有这样才能满足实际使用的需要。
所以我们以 X-SQL 的思路,采用槽位匹配的方法提取出问题中的select、where 内容,然后利用这些信息辅助依存句法树的解析,最终得到完整的 select、where、group、order 等内容。
值得注意的是,问题中的“时间”需要采用模板的方法,这样更易于扩展。
将自然语言转化成 SQL ,本身可以认为是一个 Seq2seq 的任务,所以在 WikiSQL 中很多早期模型也确实是这么做的,比如 Corse2fine。它会对问题和字段名进行编码,然后利用中间的预解码层将向量解码为 SQL 的框架,这个过程就能相当于自动生成了槽位模板,再把槽位模板也进行编码,结合原始的向量,最后能够解码出最终的 SQL。但是这样生成的结果不一定符合 SQL 的语法规则,所以后面改进的生成方法都是事先写好SQL 的模板槽,然后再用多个模型逐个预测槽位,X-SQL 就是其中一种。
下面详细介绍 X-SQL 的大体流程,如下图所示,先通过 MT-DNN 对原始问题及字段名称进行编码,再在问题前面人为地添加一个 [CXT] 用于提取全局信息。中间的 Context Reinforcing Laryer 层是这个模型的核心部分,它的目的是把 MT-DNN 得到的预训练编码在 NL2SQL 任务上进行增强和重组。这个中间层不仅能体现上下文信息,还能通过 Attention机制对字段名称的编码进行强化(紫色部分)。这一层输出的结果包括问题的编码,以及强化后的字段编码,后面的输出层都会在这个基础上进行。输出层包括6个子模型:S-COL和S-AGG 用于预测 select 的字段,只依赖于强化后的字段名称编码,通过 softmax 对每个字段打分就行了;W-NUM 只依赖全局信息,用于预测 where 条件个数;W-COL、W-OP和W-VAL 用于预测过滤条件的具体内容,通过组合字段编码,当前的 where 条件编号及问题编码,通过softmax 评分就能得到需要的结果。
这个架构已经十分完善了,但是由于数据的局限,模型无法预测多个 select 及 group 的内容。而且模型完全依赖字段名称去提取过滤条件和select的内容,在中文字段名称特征不够明显或者领域数据与训练数据偏差较大时,容易出错。
另一种方式是语法分析,一般依赖于依存句法分析的结果,能够把问题的语法依赖关系体现出来,在此基础上结合 POS,NER 的结果,可以使依存语法树上的每个节点都具有词性、实体标签等属性。然后通过后序遍历,每次遍历到父节点的时候,都将孩子节点及当前父节点的内容进行整理合并,最终遍历到根节点的时候,就得到了select、group 等要素。这种方法的好处是,它完全依赖于问题的语法规则,不需要训练数据,并且对于领域不敏感,迁移性强;缺点是只能处理相对规范的问题,对非常灵活的问题效果不佳。
那么如果能够结合两种方法,就能把语法和语义结合起来,得到能力更为强大的分析模型。也就是说, X-SQL 从深层语义的角度提取要素,而语法分析从问题的语法组成结构上进行提取。具体实现时,X-SQL 的方法能够解析出 1 个 select、1 个聚合函数、最多 4 个过滤条件。通过 pyltp 库可以得到问题的分词、依存句法树、词性标注、命名实体,加上 X-SQL 解析得到的结果,就可以得到一颗包含了每个词的词性、实体类别、结果标签(select、聚合函数、还是过滤条件中的字段名、操作符或字段值)、依存关系的树。
看一下具体的流程:
问题1:各地区的总新增订单量
步骤1:分词后的结果(需要考虑字段名,X-SQL 的结果):各 地区 的总新增订单量
步骤2:得到的聚合了所有信息的树:
其中 HED、ATT 等表示依存关系,HED表示核心关系,ATT 表示定中关系,RAD 表示附加关系。
步骤3:通过词库以及后序遍历解析依存树
步骤4:最终得到解析结果
问题2:销售额最高的3个地区
步骤1:分词后的结果(需要考虑字段名,X-SQL 的结果):销售额 最高 的 3个地区
步骤2:得到的聚合了所有信息的树:
其中 SBV 表示主谓关系。
步骤3:
1. 遍历到“3个”。由词性及规则得知这个是 limit。(不是 where 中的内容,否则会被 X-SQL 标记出来)
2. 遍历到“销售额”。得知这是一个字段名。
3. 遍历到“的”。得到这是一个无意义的词。
4. 遍历到“最高”。由依存关系,以及孩子回溯上来的信息,得知这个是一个降序排序信息。
5. 遍历到“地区”。由 X-SQL 得知这是查询词。并且整合孩子节点的所有信息,得知limit 3, 按销售额降序排序。
6. 遍历到root,得到最终结果:select内容为地区,limit 3, 按销售额降序排序。
步骤4:得到最终结果。
此外,在具体使用的过程中,经常会出现比较复杂的时间问法。比如“上个月”、“近7天”、“一二季度“、“2018/2019年”、“去年3月份”等等。对于这些问法相对固定,但是解析时需要利用大量知识的内容,我们采用了模板的方法进行处理。
模板定义:
一个模板包括问法模板和解析结果两部分。
1. 问法模板定义了问法的句式,由槽位、普通字符和正则语法构成,其中槽位暂时只用 ${num} 就够用了。例如“${num1}${num2}季[度]”,“${num1}/${num2}年”。
2. 解析结果是问法模板对应的解析结果。由“value”, “start”,“end”三个字段构成。“value”是列表,每个值定义了某个具体时间,存在多个时相互间取并集。“start”和“end”表示一个时间段的开始时间和结束时间,只有当 “value”不存在时才会有“start” 和“end”。在解析结果中需要 NOW_YEAR、NOW_MONTH、NOW_DAY 常量表示当前的年、月、日。
3. 下面是一个具体的模板实例:
其中 template表示问法模板,result 表示解析结果。这个模板可以匹配类似“近7天”模式的时间表达。
有了模板之后,只需要解析模板就行了。将 template 转化成对应的正则表达式后,把问题中的词替换成对应的槽位,再用正则表达式进行匹配和提取,匹配完成之后,将得到的槽位信息对应填入 result 中就得到了最终的解析结果。需要注意的是,匹配时间是先置步骤,需要在X-SQL 和语法树解析之前进行,为了避免时间对下面的解析造成影响,在模板匹配提取之后,需要将问题中的时间词语删除。
X-SQL 采用通过对WikiSQL翻译得到的50000条有标注数据进行训练,取其中 5000条作为测试数据,准确率达到了80% 以上。
实际测试环境中,由于中文NL2SQL领域还没有统一的数据集,所以通过收集用户实际在平台上的使用数据,最终得到了 266条中文测试数据(问题中可能包含了分组、过滤条件、复杂的时间表达、查询内容和排序等),在这个基础上进行测试,得到的结果如下:
在学术界一般都会以 WikiSQL 和 Spider 作为训练集和测试集,且都是英文数据集。由于WikiSQL 不支持复杂时间及分组,不具备可比较性,而在Spider上目前最优效果为测试准确率 55%。
目前学术界对Nl2SQL已经做了很多的研究,从最早的模板匹配方法,到后来语法解析,以及最近的深度学习方法。特别是在 BERT等预训练模型出现之后,深度学习的方法在 WikiSQL 数据集上取得了非常好的效果,出现了 SqlNet、Corse2fine、X-SQL 等一系列模型。虽然在工业界的使用中,WikiSQL 和国内一些企业的数据集还是过于简单,但是它们的思想是可以借鉴的。另一方面,基于依存句法树之类的语法分析方法也有其可取之处,通过结合语法分析和语义分析能得到更好的效果。而对于“时间”的处理,由于它的表达比较规范,但是处理时需要大量的知识,这种情况下或许模板才是最适合的方法。所以在工业界使用的过程中,还需要具体情况具体分析。