NLP 在度小满风控中的应用
导读 近些年,AI大模型技术掀起了新的热潮,NLP在金融领域的落地应用备受关注。其中最典型的场景就是智能风控。风控领域会涉及很多文本和非文本类数据,比如征信报告、交易流水、基础属性信息等,基于这些信息的建模和优化一直是NLP在实践中的主要工作。本文重点从NLP技术在文本建模涉及到的样本、特征、模型结构等方面,从研究与实践角度,与大家分享度小满所做的一些探索。
今天的介绍会围绕下面几点展开:
- 背景介绍;
- 文本序列建模;
- 非文本序列建模与预训练;
- 多模融合;
- 样本优化。
分享嘉宾|唐东格 度小满 AI算法专家
编辑整理|橘子
出品社区|DataFun
01背景介绍
使用NLP技术对文本建模主要会涉及到样本、特征和模型结构三部分。
样本: 根据样本是否有标注,可以分为有监督和无监督;根据样本量大小,可以分为小样本/大样本;根据训练时及线上的分布是否一致,可以分为是有偏/无偏;根据样本真实性,可分为真/伪样本。
特征: 一般按照特征是否代表用户行为,或是否利用文本进行划分。行为方面,可分为是用户的行为序列特征、画像类特征、统计特征;根据特征是否是文本,可以分为文本特征、类文本特征、非文本特征。
模型结构: 此前使用比较多的是DNN类、CNN类或RNN类,现在基本都是transformer类。
02文本序列建模
首先和大家介绍下文本序列建模。
1.背景
风控领域中有很多文本数据,如征信报告中的文本内容、用户上传的文本信息、用户在客户端的浏览、搜索信息或外部数据文本信息。文本数据对金融领域的风控预测有非常大的影响:
- 文本能直接反映用户的信用情况,如征信报告;
- 文本能帮助构建用户的画像,如职业、兴趣、爱好这类信息;
- 文本能反映用户的风险变化,如用户在不同时间段从事不同的工作,他搜索或构建的文本内容也会随之变化,学习这种变化,可以有效捕捉用户的风险变化。
2.文本输入向量表达
使用文本建模首先要对文本进行向量表达。
① 文本数据处理方法:分词VS分字
对文本进行向量表达,传统的方法是对文本清洗,之后进行简单分词,构建统计词典,再基于这个词典建模。
这种建模方法的优点是总体输入比较短、模型比较小,训练和推理的速度都比较快。缺点是模型严重依赖构建的统计词典,如果词典量比较大会造成特征稀疏,过拟合比较严重;词典量比较小,信息丢失比较严重,效果比较差。
现在基于transformer的主流方法是基于分字进行。分字之后先做无监督训练,然后在下游任务上进行微调。这种方法的好处是不需要人工构建词典,词典总体相对较小,而效果方面,相比传统方法,也有质的提升。这种方法的缺点在于这种分字方法会导致模型的输入较长,如果不加中间预训练过程,效果较差,有时甚至不如传统统计方法。因此,必须依赖于预训练模型,但加预训练则会造成训练耗时增加。
② 分字+分词方法结合的业务实践
基于分字和分词的方法,我们做了一些业务上的实践。当输入的文本是“武汉市长江大桥”,如果只分字的话,输入长度是7,如果做字加词结合,有两种分法,一个是字词分离,可以把输入长度缩减到5,另一个是做字词对齐,以字为基准进行分词,让分词结果与字进行对齐,长度还是只分字,但额外引入了分词信息。
这三种方法进行对比:
- 只分字需要的特征工程量最小,可直接使用开源词典;输入长度相对较长;不加预训练效果相对较差,在预训练比较充分的情况下模型效果最好、泛化性比较好;
- 字词分离方法,在一定程度上需要构建特征工程,需要有预先构建的一个词典,输入长度相比直接分字可以减少20%-50%,建模所需资源量少,不加预训练效果一般;理论上大模型效果不如第一个效果(涉及分词准确性问题,现在所有分词工具在实际业务使用的表现基本都在90%以内);
- 字词对齐方法,需要构建特征工程;需要词典(词典准确性要求相比第二种要低);输入长度跟分字长度相同;不加预训练效果最好;模型泛化性好。
分字与分词方法相结合会有两个问题:一个是字向量和词向量怎么同时输入到模型中;第二个就是使用词向量会带来较大的内存占用,一般情况下,我们只使用字向量的话,构建一个中文字典在2万左右,但构建词典一般情况下都在5万以上,甚至到15万左右。
针对字向量和词向量同时输入的问题,我们以字为单位进行对齐,将词向量复制与字向量依次对齐之后两者相加输入到文本中。
内存占用方面,字需要学习复杂的上下文依赖关系才能得到相应的表征,相较于字,词本身就是一个相对精确的表征单元,它需要的向量空间也就较小。在实际使用过程中,字向量的维度一般要超过768,而词向量只需要32维度。在做字词向量对齐时,可以通过32x768的矩阵映射与字向量进行对齐(矩阵分解),将两者相加。
这种字词对齐的优点是字词的信息可以相互补充(模型学习以字为基础的上下文依赖关系需要较大的数据量和资源消耗,在资源有限的情况下学习效果相对一般,使用词信息可以起到较好的辅助学习作用,降低训练难度);有利于模型迁移和扩展,有很多分析任务或小任务是基于词的,通过这种方法得到的词向量,可以直接迁移到其他需要词向量建模分析的任务中;有利于模型解释性,如果只是基于分字方法,计算出来的重要性权重可能会落在不连续的字上,语义上不连贯。
在实际金融领域的对比实验中可以发现,在机器资源相对有限的情况下(在3亿规模参数量情况下做对比)字加词(字词分离)方式能够提升0.5%,字词对齐能够提升2%以上。
③ 文本与其他有效特征结合
在实际业务中除了一些纯文本数据之外,往往会带有一些其他属性特征如渠道来源、内容分类、时间地点,这些特征对于加强文本理解或是目标任务预测都是比较有用的,比如渠道可以用来区分文本的置信度;内容分类可以帮助我们更好地理解文本内容(同一个文本在不同场景下的语义表征也可能是不同的);时间和地域信息可以帮助我们更好地梳理文本的序列信息或与文本信息进行交叉增强风控判断。
一般情况下,我们可以将这些文本及其属性特征直接拼接输入到大模型中,使用一个固定权重或者让模型自己学习映射权重,但这样学习到的权重大小都是固定的。我们期望对于不同段落、不同属性,模型能够依据段落重要性去自适应学习权重大小。因此在业务构建时除了使用DNN模型做特征拼接之后的映射,模型还会根据段落和属性信息构建门单元结构,自动控制底层段落属性输入到下游建模任务中的权重,做到动态调权。
3.超长文本建模
在文本建模中涉及超长文本建模问题。
① 文本窗口与风控
在金融风控领域文本建模涉及超长文本问题。风控场景与搜广推最大的区别在于需要对用户很长时间之后的信用情况做判断(金融场景的还款期限可能有6/12/24个月,甚至更久),我们需要关注用户更多+更久的信息。比如一个用户在三个月前有赌博信息,最近三个月没有这种信息,如果建模窗口是2个月,就会发现这个用户偏向于低风险用户,但建模时间窗口拉长,可能就会发现这个用户是高风险用户。因此建模窗口对用户风险预测有很大影响。
② 文本窗口与长度
在实际业务中测试,使用用户文本数据的窗口从最近一个月拉长到半年、一年、一年半、甚至两年,相对的都会有效果增益。在相关指标上半年相比一个月能提升2%;1年相比半年能够提升1%。随着文本序列窗口的增加,尽管相对收益幅度在递减,但是累积收益一直在增加。因此,使用超长建模窗口对于风控预测会有比较大的提升。但这同时也会带来模型复杂度的增加。现在使用的一般都是基于transformer的模型,其复杂度与输入长度的二次方成正比,建模窗口为一个月时使用的文本长度可能是1000,如果用两年的特征,文本长度就是24000,文本长度增加24倍,模型复杂度会增加约500多倍,训练和预测难度都会加大。
③ 超长文本模型结构
目前一些主流论文里超长文本建模的方法主要可以分为三类:
1、SparseAttention方法,当前token只关注局部token而不是关注整体的,关注长度会小很多,主流模型结构有Longformer、Big Brid、Reformer等;
2、Low-rank and Kernel方法,低秩分解和核方法本质上都是把n2d的矩阵计算复杂度降低到nk*d或是nd2,代表性的模型结构如performer、cosformer或flowformer等;
3、Segment-level方法,把超长文本按照长度进行截断,分成独立的块,降低时间复杂度,代表性模型如FLASH、Transformer-XL、block-recurrent transformer等。
④ 超长文本模型结构-实践1
根据业务数据实际情况,基于segment-level方法构建seg-split-lstm模型:
实际业务文本数据跟论文相比不一样的地方在于实际业务文本数据还带有其他属性信息,比如时间属性信息。论文中基于Segment-level方法对长度切分会把同一个文档切分到不同Segment的块,信息存在不连续性,效果会下降。
在业务中则可以根据时间窗口进行划分,比如用户每十天的文本作为切分窗口,可以保证同一个文档肯定在一个Segment中,同时,每个分片都会具有时序意义,比如按照十天进行切分,那么最近一个分块的信息就可以严格表示为用户在最近十天以内的文本向量表达结果。这种建模方法还有一个好处是每个分块之间参数完全共享。目前文本模型都会涉及预训练问题,如果文本输入长度在1万以上,对于现有GPU资源是很难直接做预训练的,按照时间窗口进行划分,每个时间窗口内的文本长度可能就只有1000左右,完全可以用现有资源做预训练,由于不同窗口间参数共享,预训练好的模型可以直接在下游任务做finetune,总体模型耗时也会降低。
⑤ 超长文本模型结构-实践2
但这样也存在一个问题,用户昨天和今天的文本虽然是独立的,但文本内容也可能存在一定关联性,将昨天的用户信息跟今天的用户信息做交叉,两者可能会学到相互补充信息。基于这种情况,我们构建了能够学习超长文本全局信息依赖的seg-split-crossUnder-lstm模型,在seg-split-lstm模型的基础上引入了底层crossUnder交互模块。具体做法是在分块基础上先做一层transformer,用lstm或其他时序建模方法学习不同分块之间的全局交互信息,把这个全局交互信息的输出和第一层的输出进行拼接输入到剩余的n-1层模型中,这样既学到了分块内的文本信息,又学到了不同分块之间的全局依赖信息。
目前这种模型结构在实际业务中已经支持了超7万+的文本输入长度(参数也是亿级别规模)。
⑥ 超长文本模型结构-总结
- 基于Sparse Attetion和低秩的模型速度比较快,在资源的有限情况下可以采用这种方法,但这种方法信息存在损失且损失不易控制;
- 基于核方法的线性Attetion模型,只有当文本输入长度n远大于d的情况下(比如一般使用的隐层维度是768,当文本长度是512时,这种方法并不能带来速度上的明显增益)这种方法才适用,效果也相对稳定;
- 基于分段方法,它的速度与分段数量大小严格相关,分成n段时间复杂度会降低n倍,效果在三个方法中最为稳定。这种方法最大的优点在于预训练过程更容易实现,也更容易适配开源的大模型结构。上面两种方法都需要把文本长度拉长到下游任务长度上,但第三种方法不存在这种问题,因为不同分段之间完全参数共享。
03非文本序列建模与预训练
1.背景
实际业务中涉及比较多非文本序列建模的问题,如用户的交易流水数据、产品使用日志等。
传统方法是对这些信息先做特征构建,然后进行特征选择,最后做上层建模。特征构建,如按照时间空间维度做切分,根据用户的基础属性信息做不同维度交互或通过数学方法做数值平均、差值等,此外还涉及如数值转换等;特征选择,一般是基于统计的相关性分析、特征稳定性分析等,模型方面,主要是基于可输出特征重要性权重的方法,LR/XGB等;上层建模可能涉及DNN/XGB/FM等模型。它的优点是构建出来的特征有比较强的解释性,缺点是整体流程冗余、工程量大,需要专家经验水平(做特征构建时依赖专家特征经验),效果比较有限,模型使用场景单一(更换场景需重新做特征构建与选择)。
使用NLP技术提升非文本序列建模的能力主要包括两方面,一是把NLP模型结构应用到非文本序列建模中,二是把NLP训练方法,如数据增强、无监督训练(预训练)、迁移训练等方法应用到这种非文本结构中。
2.非文本序列建模
在业务实践中,(如图所示有多个产品,每个产品都有各自的日志信息、基础属性信息),如何基于这些信息尽量使用比较少的特征工程,结合nlp模型取得更好的模型效果,是我们建模的目标。
第一个问题是如何进行特征构建,最简单的方法是对每一个产品取不同的时间点(每隔一个月或每次用户日志变动时)做信息截取,截取后把日志信息做数值映射,使之能够输入到模型中,然后构建深层nlp序列模型(如lstm、transformer等),让模型自主学习复杂的序列表征,这样就用非常少的特征工程方法(且几乎不依赖专家经验)建立了深度学习模型。
第二个问题是在做传统特征构建时,会涉及到不同产品的特征交叉,如何把这种交叉信息引入到深度学习模型中(如把产品123的信息和基础属性信息进行交互)。我们借鉴前面讲的seg-split-crossUnder-lstm方法,非文本基础属性信息可以先用xgb先做训练,得到的叶子节点直接输入到深度学习模型中,不同产品信息底层做类似于transformer模型的序列结构,然后第一层把产品123+基础属性信息的输出做向量拼接,通过模型做深度交叉(例如使用DCN模型把不同产品信息做特征交互),再通过DNN映射回到每个产品结构上,与原来各自的输出相加再进行后续训练。应用nlp超长文本依赖方法,这里我们实现了不同产品特征信息的深层交互。
总体流程来看,需要做特征处理的只有日志抽取与数值化表达,模型整体框架也比较容易迁移(如新增一个产品特征,可以直接把底下的产品123扩建成产品1234,模型迁移性高)。传统方法新增一个特征做交叉,可能会乘几倍增加交叉特征产生的特征量,相应的做特征选择也会更加困难。在我们相关业务上,相比传统方法各项指标提升也非常明显。
3.预训练
① 文本和非文本预训练
文本和非文本都涉及到模型预训练的问题。预训练总体上来说是通过学习与下游任务标签无关的、无监督的、大规模数据的共性特征,得到一个更好的初始化模型参数。它依赖于两点,一个是庞大的无标注数据集,一个是较大的模型参数。
文本预训练现在比较通用,通过上下文信息,依赖语义关联性学习某一个词的向量表征。但是非文本预训练,现在业界并没有明确结论,论文里涉及的也比较少。事实上我们可以使用类似语言模型的方法,通过上下文特征,学习某一个特征的向量表征,也就是学习特征之间的关联性。
举个例子,业务中可能会涉及到使用用户软件的建模方法,如用户使用软件涉及到软件1、软件2、软件3等,我们把软件3位置做掩码处理(就类似于文本中的mask language model),让它预测文本3位置的软件特征表征,这样我们就可以学到初始化的一个模型参数。相比于直接建模,通过这种预训练再进行微调的方法能够提升2%的效果,也就是说这种方法也是可以学到类似于文本预训练信息的。
但这种非文本数据关联性一般情况下是很难靠人们的感知直接获得的,目前还是以实践经验为主。
② 预训练迁移
预训练的成本一般比较高,一些开源的预训练又很难直接在下游任务上做适配(一方面不同领域之间存在语义差别直接使用效果不佳;另一方面下游任务的模型结构可能存在独特性)。
目前我们在业务上使用的方法是通用结构做集中维护迁移。使用通用预训练模型在特定业务数据集上继续预训练得到领域训练模型,如果有多个下游数据集可以把多个数据集进行结合做一个多领域联合预训练模型。通过定期更新领域数据集(新数据、新样本),定期更新维护预训练模型,用于提供给下游任务使用。
下游任务使用上也包括两个问题:
- 下游业务方使用的模型框架与预训练模型框架相同,可以直接微调使用;
- 下游业务方对模型结构做了特殊化处理,如提供的预训练模型使用的是普通bert,下游任务使用的flash等,这样是不能直接做finetune的。但即使模型结构存在比较大的差异,他们仍然有很多相同的参数,如底层向量的映射参数矩阵(每一层transformer都会先经过特征映射成qkv),这种参数维度相同的情况下,是可以直接拿过来做参数初始化的,即不同模型结构中的相同参数是可以直接做初始化的,初始化之后再在期望的数据集上(特定的领域数据集)做简单的进一步预训练。这种预训练的成本相比从零开始在这个数据集上做训练可以节约50%-90%左右,大幅加快训练过程,节省资源消耗。
04多模融合
1.背景
多模融合的背景是在数据和模型都固定的情况下怎样快速提升模型的效果。在很多机器学习相关比赛中,大家常用的方法是做多模融合,包括两种:一个是单数据的多模融合,一个是多数据的多模融合。
2.单数据多模融合
单数据多模融合是使用一路数据,进行多次模型训练得到不同的模型结果,然后将多次的结果进行融合。多模融合的目的是提高模型的泛化性与稳定性,提高模型评估指标。多模的结果可以来自于不同的采样方法、不同的模型参数、不同的模型结构等。将多模结果进行融合,一些简单的方法是直接将模型的输出(如打分)做加权平均,或通过boosting/bagging方法做融合。上述是比赛中常使用的方法,但这存在一个问题是比赛不涉及线上部署,实际业务场景涉及到部署,采用这种方法就需要把多模涉及的多个模型都部署到线上,如果涉及n个底层模型,线上也就要部署n个模型,资源消耗量增加n倍,成本大幅增加。
我们在业务实践中是用一个单模把多模结果融合在一起,如图中,中间是融合模型,两边是采用不同方法训练出来的不同模型结果。在中间模型底座不变的情况下,用融合模型的最后一层直接学习其他模型的隐层结果,如果我们训练出了n个模型结果,就把要训练的这个融合模型的隐层扩大n倍,让每一个隐层去学习不同模型的输出结果。这个学习方法类似于来蒸馏学习,训练过程中也可以加上软标签和硬标签的损失结果。实测中,我们使用中间融合模型学习到的结果与XGB多模融合的学习结果基本相当,即融合模型学到了我们期望的多模结果。这种情况下,线上只需部署这一个模型,且模型大小只有最后的隐层被扩大n倍,相比于一个多层模型来说,资源消耗的增量几乎可以忽略不计。
进一步来看,下游模型在进行线上部署时通常会进行蒸馏和压缩,实际上我们也可做成一步到位的形式,也就是融合模型可以直接设计成要蒸馏的目标模型结构(如层的大小以及要训练模型的层数),然后就可直接得到用于线上部署的小模型。
3.多数据多模融合
业务上一般不是一路数据而是多路数据,每路数据在训练时均采用了预训练+finetune方法得到的大模型。大模型结果在上层一般是通过DNN或XGB方法进行融合,但它存在的问题是仅将每个数据模型结果做融合,没有做端到端的训练,缺少底层数据上的交互,这种自然不如端到端学习的结果。但是端到端学习,如n路数据就涉及到底层n个大模型,同时进行训练一般的机器资源无法满足相应的资源消耗。
我们开展的多数据多模融合实践是对每一个数据先单独训练一个大模型,然后对每路数据的大模型进行中等蒸馏(如原始输入长度是768,将这个维度缩小两倍,原始层数是十二,中等蒸馏到六层),经过中等蒸馏后每个模型大小都相应缩小几倍,即可把每个中等蒸馏的模型结构联合在一起做端到端的学习,最后用一个小模型对端到端训练结果进行最后的蒸馏用于线上部署。
通过这种方式,相比于每个数据单独训练上层再直接融合的结果,效果至少提升1%以上。
05样本优化
1.背景
样本优化主要包括两部分,一是正负比例,一是样本量。金融领域样本具有特殊性,正样本少,负样本比较多(正样本是逾期样本,负样本是正常的样本)。
2.样本优化:正负比例失衡
常用的解决办法是过采样、欠采样或是对损失函数进行加权,如focal loss加权。除此之外,在业务实践中,我们设计了不需要预先构建过采样/下采样样本的训练逻辑,我们将全体数据shuffle后输入,训练时如判断为正样本则直接加入到当前要训练的batch中,如判断是负样本就以一定概率丢弃,通过丢弃概率这个参数可以随时调整正负样本比例,通过在不同 epoch设置不同的随机种子,可以保证正样本全部有效利用,负样本以需要的样本分布策略充分利用。在实际使用过程中,模型收敛更快,训练资源消耗量更少,训练速度可提升3-5倍。
3.样本优化:数据增强
数据增强本质上也是解决样本问题。通过数据增强的方法,构建一部分正样本和负样本。常用的方法如EDA、插值法及基于生成的方法(回译法)。
除此之外,我们在业务中做了两个实践:
第一个实践的业务场景是:负样本量较少、远小于正样本,且随机采样正样本比例比较低;同时有海量无标签数据,那么可以从海量无标签数据里面直接采样作为负样本与现有的正样本结合作为训练数据集。但这有一个前提条件:从海量数据中随机选取一个样本,这个样本是正样本的比例不能特别大,如在一些获客场景中这个比例非常小,一般情况<0.5%。系统会有一个“允许加噪比例”(随机采样引入的假正样本与原有真正样本的比例),在这个比例之内我们可以直接引入大量的无标签数据。举例来说,如果正样本的量是40万,R是0.5,允许加到比例是1/30的话,那么可以增加的负样本量就是200万(这些负样本是从海量数据中随机选取),这样就可以有效增强模型训练效果。
第二个就是一个简单的span copy方法,基于esimcse文章中提出了word repeat方法(将单词做简单重复,就可以对数据量进行扩充)。在我们的实际业务中使用这种方法并不稳定,于是我们提出了一个span copy的方法,随机截取输入中的一个片段,随机插入到文本的不同位置,得到新样本。在下游任务使用过程中,这种相比普通的基于字或词的方法效果更稳定,相关指标上能提升0.3%。
今天的分享就到这里,谢谢大家。