ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

金融NLP需求落地实践总结——热门话题生成

2021-03-28 20:51:10  阅读:209  来源: 互联网

标签:NLP 抽取 落地 新闻 聚簇 热门话题 话题 聚类 描述


图片


作者:邱震宇(华泰证券股份有限公司 算法工程师)

知乎专栏:我的ai之路




很久没写文章了,今天一不说论文(攒了一堆还没复现),二不说算法基础(没复习),主要来说说我到华泰NLP后做的第一个比较有意义的事情——热门话题生成。事实上,我在接手这个模块时,已经有其他同事输出了一个较为完整的解决方案,效果也尚可,只是还有一些需要改进优化的地方,因此,我的主要工作是在其基础上从性能和效果两个方面进行各种优化。本文主要是总结了个人在经历该项目期间的一些工作和思考,如果有不合理的地方,欢迎同行留言交流。

热门话题生成是什么?

首先,介绍一下热门话题生成这个功能需求。它的载体是我们内部开发的一套基于自然语言处理技术的金融舆情事件分析系统,该系统主要目标是构建风险、交易事件信号,助力投资交易、风控领域。

关于这套系统具体内容,我们团队长之前在公众号AINLP上有投过文章,标题为:《自然语言处理在金融实时事件监测和财务快讯中的应用》,有兴趣的同学可以自行检索查看。

而热门话题生成的需求目标则是通过对当前最新新闻的快速分析,获取当前世界范围内比较热门的、与金融相关的话题,话题内容包括但不限于公司金融事件、国内外政治军事事件等。用户可以通过该功能模块快速感知当前全球的热点话题,为期在做投资决策时提供舆情情报。这个功能可能与一些社交平台上的热点、热门比较类似,不过我们主要针对的是不同平台发布的新闻数据,大部分以金融新闻为主。下图为热门话题展示的结果样例:

图片

以第一条为例,下图展示了第一条示例的新闻聚簇效果,可以看到该话题的聚簇效果还是不错的。

图片

我们内部有一套完整的新闻数据获取与处理流程,使得我们能从多个数据源总实时快速获取大量的新闻数据,这块内容我就不过多介绍了,下面着重描述热门话题生成模块的实现过程,主要分为三个小节:

1、模块问题定义与需要解决的问题。主要阐明热门话题任务需要解决哪些问题。

2、模块解决方案基本框架。主要介绍初版解决方案的基本流程。

3、模块优化过程。主要介绍在初版方案的基础上进行的一系列优化工作。

热门话题生成问题定义

首先我们将热门话题生成任务拆解成三个子问题:

1、首先必须从新闻文本中提取话题。不同于一些比较传统的NLP任务,如文本多分类、多标签分类、信息抽取等,这个任务并没有一个很明确的学习目标,即我们并不知道要抽取的话题的schema集合,因为每天出现的新的话题都是未知的,这种场景下的数据一般也是无标注的,所以无法用有监督的学习方式来解决。

2、除了提取话题之外,我们还需要将包含类似话题的新闻聚合起来,以获得当前阶段的话题簇,这样我们就可以计算出每个话题的热度,将热度较高的话题推送给用户。

3、最后,对于每个话题簇,我们需要为其生成一个话题描述文本或者标题等等,用于直接展示给用户查看。生成的描述需要充分代表该话题簇的话题内容,且需要一定的可读性。

对于问题1,相对于目前比较火热的深度神经网络NLP方法,通常会使用基于统计学方法的topic model来做话题抽取,经典的方法如LDA等等。topic model通常会无监督的对每篇新闻文本抽取话题,它的产物包括得到文档-话题的概率分布,每篇文本可以使用这个概率分布来当做向量表示;对于问题2,可以使用解决问题1时得到的文本向量基于无监督的聚类方法做无监督的聚类;对于问题3,则相对复杂一些,目前并没有现成的方法工具能够直接解决这个问题,因此需要设计适合该场景的方法,具体见下文描述。

热门话题生成解决方案基本框架

基于上述问题定义,我们团队基于此设计了一个基础的方案框架,框架流程如下图所示:

图片

具体来说,主要分为以下几个模块:

1、新闻数据定时批量推送与文本预处理模块。基于性能和效率的考量,我们并非是实时对新的新闻文本进行话题抽取分析,而是设置了定时机制,以T分钟为间隔,每隔T分钟执行一次算法那服务,将过去一天内的所有新的新闻作为话题抽取的源数据(已经对这些新闻进行了去重)。另外,我们舍弃了新闻的正文,只将新闻标题送入到话题抽取模块。这样做的原因有两点,其一是新闻文本的内容通常较多,而且topic model的训练时间通常都比较长,我们对于正文内容抽取话题的时间成本是无法忍受的;其二是很多新闻正文内容通常包含多个不同的主题,对其进行主题抽取和聚类后,得到的话题簇效果较差,存在簇与簇之间区分度不高的问题。另外,我们的目标只是对当前热门的新闻话题进行聚合,因此只用标题从而产生的一些信息损失也是可以接受的。对于新闻标题,我会做一些常见的文本预处理,例如繁体转简体,中文分词(我们尝试使用了哈工大的LTP和Baidu的LAC分词,效果差不多)、去除停用词等。

2、主题抽取与聚类。该模块使用topic model对新闻标题集合进行主题抽取,然后对每条新闻进行向量化。最后使用这些向量使用无监督的聚类方法进行聚类。

主题抽取

主题抽取可以说是整个方案的核心,主题抽取的质量决定了后续步骤得到的话题簇以及话题描述的质量。通常我们会使用LDA来对文本集合进行主题的抽取,然而在我们这个场景中,这种方法并不合适。主要原因为LDA的稀疏性问题。对于长文本来说,每篇新闻都能包含足够多的文本篇幅来囊括不同主题词的信息,对于一篇文档来说其本身通过一个Dirichlet分布采样得到一个文档-主题的概率分布图片,生成文章的某个词时,根据图片生成主题隐变量z,然后根据z从另一个Dirichlet分布采样得到主题-词的分布 图片 ,最后根据图片采样生成词。对于短文本来说,由于一篇文章包含的词过少,上述生成过程的统计意义就不明显了,无论增加多少篇文章都不能缓解这个问题。(有关LDA的具体原理详见网上其他博客)

最后,我们经过一番调研,决定使用一种专门针对短文本主题抽取的topic model方法,即BTM(Biterm Topic Model)。

详细的BTM算法在知乎上也有博客专门总结,这里我就不详细得描述了,仅仅针对其原理做简要的介绍。可参考目前有比 Topic Model 更先进的聚类方式么?比如针对短文本的、加入情感分析的?- 苏格兰折耳喵的回答 - 知乎 https://www.zhihu.com/question/298517764/answer/760362033 或者zhuanlan.zhihu.com/p/11

BTM的学习过程其实与LDA是类似的,但是它在做概率分布学习之前,对文档词的处理方式不同,主要体现Biterm上。所谓的Biterm就是从分词后的文档词集合中,抽取两个词组成一个词对,以词对为基础元素进行主题词的学习。另外,它不同于LDA,所有文档共同使用一个概率分布图片,使得主题稀疏的问题得到了缓解,很适合标题短文本中词较少的场景,另外对于一个新闻标题来说,很多情况下只会包含一个主题。

话题聚类

得到得到话题分布后,我们相当于得到了每篇新闻标题文本的向量化表示,然后我们尝试了最简单的k-means方法拉进行聚类,这种方法需要指定聚簇的个数,不过实现和调试比较方便,在经过了几轮数据的调参后,也比较方便确定一个大概的聚簇个数。另外,我们还尝试了Xmeans,这种聚类方法不需要指定聚簇的个数,但是也要指定聚簇的一个大概范围,每次迭代计算,它通过BIC score(Bayesian Information Criterion)来判断的当前聚簇是否要分裂。最终通过综合考虑,我们还是使用了xmeans作为最终的聚类方法。

关于话题聚类,还有一个细节要说明一下。通过BTM学习后,我们能够得到文档-主题的概率分布,以及主题-词的概率分布。我们主要使用文档-主题的概率分布来做话题聚类,聚类完成后,我们通过整合聚类后每个聚簇中心的话题分布和主题-词概率分布,能够得到每个聚簇上的词的分布,这个概率分布大致可以表示一个词在该聚簇上的重要性。后续在做聚簇优化时,可以利用该关键词信息进行聚簇的合并或者分裂。下图为某个聚簇计算得到的关键词结果:

图片

3、聚类后处理。上述话题抽取和聚类后,已经能够得到一些相对不错的结果。但是还会存在一些质量不高的聚簇,此时需要通过引入一些规则,对做聚簇的合并和分裂,这块内容将着重在下一章节的优化介绍中进行详细的描述。

4、话题热度计算。对于话题热度,目前我们只是暂时考虑了新闻在不同新闻源上的出现次数,并未考虑全网中其他平台的转发、引用等情况。因此该热度只能在一定程度上反应一个话题的热门程度,不过通过一段时间的验证可以发现这种热度的计算方式基本能反应话题间的相对热度关系。

5、话题描述生成。本模块主要对每个话题聚簇生成一个合适的话题描述用于代表该簇并展示给用户。初始的实现方式是通过使用哈工大的LTP工具对聚簇中的所有标题进行句法分析,抽取标题文本中的主谓宾、定语后置动宾关系、介宾关系主谓动补等结构。然后对一个聚类中的新闻提取的语法要素进行相似度的分析,并抽取重合度最高的语法结构拼接得到临时话题描述。这种方式实现上来说比较简单,但是存在一些问题,具体将在下章节优化介绍中描述。

6、历史话题合并。本模块主要是将本迭代计算得到的话题簇和其对应的话题描述与历史迭代得到的话题结果进行合并。之所以要做这一操作的原因在于我们的热门话题服务模块是每个N分钟定时执行,一般两天之内,某些话题的新闻会在不同时间段重复出现,所以当前的迭代产生的话题有很大概率与前几次迭代的结果有重合,我们需要对重合的话题进行合并,更新其热度。初版方案的合并过程为:

  • 获取过去24小时内的已经抽取话题聚簇news_topic_latest_24_h

  • 将当前迭代处理的每条新闻,与news_topic_latest_24_h中的每个话题描述,计算其相似度。具体相似度计算方法参考使用了fuzzywuzzy的文本相似度计算工具。当相似度大于预设的阈值时,则视为重合,则进行合并,同时更新话题的热度。

  • 若上述步骤计算得到的相似度小于预设的阈值,则查看该新闻对应的关键词列表与当前话题的关键词列表的重合程度(关键词列表由话题聚类后得到,每个话题簇有一个关键词列表,每个簇下面的新闻共享这个关键词列表。)

可以看到上述方法实现时比较简单的,但是从性能和效果上都有很多待优化的地方。具体将在下章节优化介绍中描述。

热门话题生成优化过程

本章节将着重介绍本人对热门话题生成各个阶段中的瓶颈分析和优化过程,希望对业界的同行在业务落地时有一定的借鉴意义。

话题聚类优化

此处优化主要针对的是利用BTM进行话题抽取以及聚类后得到的话题聚簇结果。优化前,通过聚类得到的话题簇存在以下问题:

1、BTM本身话题抽取的误差,以及聚类算法的误差会向后传递,使得聚簇的纯度不高,如下图所示,微软推迟ES2010扩展支持结束日期话题明显不属于当前话题。

图片

2、BTM与聚类本身需要指定超参数来决定最后话题聚簇的粒度,这也导致后续某些聚簇的话题被误分裂,如下图所示,红框中的两个话题应当是能够合并的。

图片


3、有些聚簇虽然说的话题是相似的,但是其本身信息量不是很大,对于用户来说价值不大,反而容易将其他真正有价值的话题挤掉,如下图所示(忽略该图中的话题描述错误),虽然这几个新闻都讲与融资相关的事情,但是基本上是与不同实体公司相关,且新闻间也没有关联度,这种话题簇应该进行分裂。

图片

基于上述问题描述可以总结出,对于初步得到的聚簇结果,我们需要做进一步的后处理,来保证聚簇的纯度和区分度。主要从每个新闻标题关联的实体以及关键词来入手,引入一些启发式的规则,来进行聚簇的精炼。以关键词为线索,可以引入如下规则(示例):根据关键词列表,如果两个聚簇中的关键词重合度大于某个阈值,则进行合并。若不大于该阈值,则看其重合的关键词的概率是否均排在所有词的top3,如果是,则合并。

以实体为线索,则相对复杂一些,主要流程如下:

1、使用百度的LAC工具,对新闻标题进行实体标注和词性的标注,找出标题中类型为PER,ORG,nr,nt的实体词,打上标记。另外对于聚簇关键词列表中的实体词也打上相应标记。

2、通常来说,一个聚簇中真正相关的实体个数不会太多,一般只会有一个,如果在原有聚簇的基础上,加入实体的因素来判断是否合并或者分裂聚簇,最后可以得到一个更加纯净的聚簇结果。因此,可以引入一些实体相关的规则来进行后处理,示例如下:对于两个待处理的聚簇,如果两个聚簇中关键词包含的实体有重合,且重合度较高大于某个阈值(重合度根据实体类型以及实体内容综合判断,一般是ORG类型的实体权重较高,因为新闻通常关注机构的事件),则进行合并;若关键词中的重合实体不满足要求,则将两个聚簇中各自的实体列表进行比对,同样根据不同类型实体的权重计算重合度,若重合度大于某个阈值,则合并。

3、其他规则。另外,我们分析了一些bad case,发现有一些话题新闻本身确实没有问题,但是对于用户来说意义不大,且容易干扰其他话题,如下图所示,这些新闻通常包含物价类新闻、研报点评类等等,可以在话题聚类之前就过滤掉这些新闻。

图片图片

话题描述生成优化

通过分析一些bad case,可以总结出初代版本的话题描述生成存在的几个问题:

1、话题描述语句不通顺。因为是使用开源的NLP分析工具提取句法结构,然后将其简单拼接,因此难免会得到可读性较差的文本。如下图所示。

图片

2、话题描述与当前聚类下的新闻可能会不一致。这个问题与历史话题合并也有很大关联。由于历史话题合并模块的一些问题,使得合并后的话题新闻并不纯净,使得产生的话题描述也会受到污染。如下图所示,这个话题本意应当是讲对外投资相关的话题。

图片

除了算法效果之外,初版方法的性能也不太理想。由于需要对所有新闻标题进行句法分析工具,然后进行相似度的计算,因此计算成本较高。这对于一次性处理接近万条的数据来说,是不太满意的。

基于性能和效果的双重考量,我设计了一种新的方式来做话题描述,即利用rank类(例如TextRank)的抽取式摘要算法来帮助生成描述文本。可行性在于通过rank类摘要提取出来的摘要句,通常会倾向于选择相似性比较高的一类句子作为摘要句,虽然在摘要抽取里面这回带来冗余的问题,但是在我们这个场景下,这种特性反而是一种优点,通过rank类抽取出来的权重较高的句子,通常是能够代表该聚类中大部分句子内容的,因此能够作为话题聚簇中的代表性描述。具体的算法流程如下:

1、对于话题聚类以及后处理得到的话题聚簇,将一个聚簇内的所有新闻标题文本拼接成一段文本,每个标题文本作为一个候选摘要句。

2、使用TextRank算法做抽取式摘要任务,得到权重分数排名前5的句子作为候选描述句。这一步骤主要关注的是如何去向量化新闻标题以及计算两个标题句的相似度。由于需要兼顾性能要素,因此不能使用太复杂的方式,经过综合考虑后,决定基于词的tfidf特征来向量化标题句,并使用余弦相似度来度量两个句子的相似程度。这种方式性能还是不错的,最后效果也不错。后续所有用到相似度计算的模块基本上都沿用这个方法。

3、若候选描述句中包含聚簇的实体词,则优先选择该句作为描述句。

4、前三步骤得到的句子会有一些问题,如有些标题本身很长,或者有些标题比较冗余,此时需要对这种标题进行后处理。当前设计为先判断句子长度是否大于某个阈值,若是,则对描述句进行句法分析,抽取出其主成分,将其作为最后输出的描述句。

历史话题合并优化

最后介绍一下历史话题合并中的优化问题。初代版本的方法在性能和效果上都有一些问题:

1、性能方面,每一轮更新时,从数据库中查询仅24小时内的已抽取话题,其归纳整理后的topic数量大概是600+,而每次新处理的新闻的量级大约在400-600的数量级(已去重),其中新id的新闻大致占总量的20-40%,假设平均的数量级为50+。做新闻话题合并时,需要将每篇新闻与当前已有的话题进行相似度以及实体相关的分析处理,而一条新的新闻完整合并逻辑的流程时间大概需要20秒(其中,大部分时间主要集中在需要和600+数量的topic逐一进行相似度比较,相似度计算的时间会比较长)。那么50+的新闻的合并流程则需要16+分钟,还需要加上数据库的入库操作的时间消耗,这个时间成本是不太理想的。

2、效果方面,由于之前的话题描述生成效果不佳,同时使用的相似度计算方法(fuzzywuzzy)也并不好,因此合并的效果也不好,如下图所示,两个罗永浩被列为老赖的话题是在不同迭代中生成的话题,但是最终没有被合并上。

图片

基于话题描述优化以及相似度计算优化的工作,我对历史话题合并进行了改造,具体如下:

image.png

其他未采用优化

除了上述优化外,我还花费了一些时间探索了其他优化的方法。例如通过使用一些复杂的句子表示方式以及相似度计算方式,来提升模块整体的效果,诸如使用sentence-Bert或者usif的方式来向量化一个句子。但是这些方法无一例外,计算成本都较高,对于我们的场景来说不太适用。有感兴趣的同学可以自行深入研究。

小结

本文主要描述了一个实际的NLP需求场景的落地过程,同时也展现了一部分算法人员的日常工作。这些工作往往并不会涉及到一些高大上的负责算法,有时候负责的算法基于性能原因也无法实际应用。个人认为,在金融NLP领域这块,需要具备一定的bad case分析和优化能力,简单点说就是能用效率最高的方法解决bug。不同于推荐场景需要硬指标的提升,我们很多场景的评测是没有办法量化评测的,就比如本文所说的热门话题生成,这种场景一般只能靠人力来质检,因此我们就需要快速对质检结果进行反馈,上线迭代版本。总而言之,算法和工程要两手抓两手硬。




本文由作者授权AINLP原创发布于公众号平台,欢迎投稿,AI、NLP均可。原文链接,点击"阅读原文"直达:


https://zhuanlan.zhihu.com/p/268564361


欢迎加入AINLP技术交流群
进群请添加AINLP小助手微信 AINLPer(id: ainlper),备注NLP技术交流

图片


标签:NLP,抽取,落地,新闻,聚簇,热门话题,话题,聚类,描述
来源: https://blog.51cto.com/15060464/2675548

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有