半岛全站本次分享的主题为医疗健康领域的短文本理解,主要介绍在丁香园的业务场景下,短文本理解的技术实践,并讨论知识图谱技术如何在医疗健康领域的搜索推荐中落地应用,希望能够给大家的日常工作提供一些思路。
丁香园的起点是打造一个专业的医学学术论坛,为医生、医学生及其他医疗从业者提供一个信息交流的平台,同时也推出了一系列移动产品以提供优质的医学信息服务半岛全站。
目前,丁香园围绕着医生和大众来发展,业务覆盖这两类人群的日常需求。对医生为主的医疗从业者来说,会涉及到日常的学术问题、经验分享、疑难病例的讨论以及查阅药品说明书、诊疗指南等等。对大众来说,包括线上问诊、科普知识、健康商城等服务。
搜索作为丁香园的基础服务,需要支持多个社交与工具类的应用,主要包括:丁香园论坛、用药助手、丁香医生、丁香家商场等主要App。处理的文本数据需跨越大众和专业医学这两个领域,涉及的业务线也需处理不同的场景。
第一个是丁香园论坛,主要用户是医疗相关的从业者。用户会在论坛中,讨论最近的热门医疗事件,新冠疫情、考博、规培的分数线、医疗纠纷,或者发帖求助一些疑难病例,求一些医疗文献等等。
第二、第三个场景是来自于用药助手,这是一个工具类的应用。用户会将其作为搜索药物信息或诊疗指南的工具。
后面三个场景是面向普通大众的,包括对科普文章的检索、线上问诊数据的检索 ( 举个例子,用户会问湿疹反复发作怎么办?、坐月子能不能洗澡?这类的问题 ) 以及电商场景 ( 大体上和市面上的电商场景都相似。不一样的是该场景会围绕健康线;等线. 垂直领域下的思考
左边第一张图是医学的新闻事件,这与大多数的普通新闻比较类似。新闻事件会天然形成一个线;新冠疫苗最新进展,用户会围绕这个话题产生一些相关的搜索行为,如搜索肺炎、柳叶刀等潜在的、需要获取的话题意图。
第二张图是我们想要谈论的,在医疗领域比较特殊的话题性半岛全站。因为在医疗领域关于症状相关的表述会非常多,或者用专业的表述我们会叫它临床表现。这里再解释一下临床表现的含义:你可以理解成生病后身体的一些症状,比如,头疼、发热、呕吐等。医生在做病例讨论时,常常会抛出他们认为比较关键,但又很让他们困扰、值得讨论的临床表现半岛全站,如术后出血引起的血肿、右下腹感染病变、胸部多发病变。所以当用户发起一个讨论时,某些临床表现的词也会自然形成一个话题。但是这些话题相关的词并不像开放领域中的词有那么明显的边界。举个例子,在开放领域中,梅西获得2019年金球奖这样的线年金球奖,在搜索时比较容易避免搜索的关键词与用户实际关注的事件间的差异。但在上述的例子中,腹腔镜与术后血肿相关,但是与腹腔镜相关的其他疾病和手术也非常多,同时也包含了其他非常多的复杂逻辑。所以,我们认为医疗健康领域的内容普遍存在着话题性。
最后一张图是面向大众的科普,这块比较容易理解。医疗话题的底层是由许多复杂逻辑与细节组成的。当用户提问坐月子能不能洗澡时,如果只回答能或者不能显然是不够的,而是需要组成一个话题来讨论或者用更加友好的方式来回答。
对于医学知识本身的复杂性,在处理面向医生的文本数据时,是不得不面对的问题。例如,这是在丁香园中的一则病例讨论。这位医生详细描述了在工作中遇到的一则病例,其中包括了非常多的专业术语。我们用了一个简单的实体抽取方法进行抽取可以获得腹胀、腹泻这样的疾病症状词。但是全文的信息量不仅在于这些实体词上,也有相当一部分是存在于这些词之间,复杂的逻辑关系。在常见的搜索方法中,我们会用词的倒排索引来完成文章检索这件事,但是倒排索引在执行过程中很难保证主题不会发生偏移。在理想情况下,我们更希望抽象出更具概括性的标签来结构化这些数据。
除了医疗话题在主题上不好做结构化,在处理面向大众的文本时,认知层面的差异也是个棘手的问题。医学知识、医学词汇都具有高度的专业性。比如用户在表述中,一个非医学背景的人会用痘痘、青春痘、闭口、痘印这样的词去表述自己的症状。在医生看来这些症状会是寻常痤疮、毛囊口角化异常等专业词汇。当我们想要帮助大众检索到想要的信息时,就要想办法跨过这些表述不一样的情况,因此我们在三个方面做了一些努力:
首先是错别字的问题。错别字问题在各个领域的搜索中都是非常常见的问题。常见的错别字原因,可能来自于拼音使用的错误。比如头癣这个词,大多数人会念成头藓,藓字就会常常出没在相关的搜索query里。另外,还会出现和拼音相关的识别问题,比如头xian和头xuan,这种汉字和拼音混搭的情况。
非医学科班的同学看到复发性阿弗他口炎这个词肯定是一脸懵。其实这个词和感冒一样是非常常见的问题,就是我们平常说的口腔溃疡。但对于大众来说,会有更多通俗的表述半岛全站,如口疮、口腔溃疡、口腔溃烂、嘴巴起泡等等。如果是医学背景的用户,他大概率会知道这个专业名词,但是会出现其他的一些错误,比如表述上会缺其中的一个组成部分或者缺一到两个字,如阿弗他口炎或者复发性口炎。还有种情况就是把通俗表述和缺省表述混搭的表述方式,如阿弗他溃疡、阿弗他口腔溃疡。
在我们这个例子中,症状性动脉粥样硬化性椎动脉起始部狭窄这个词长达18个字。仔细观察,你会发现它其实具有明显的组成部分,它是通过不同的组成部分拼接成的长词。如果我们在识别一个短文本中这样的长词没有被合并在一起,而是按照不同的组成部分分开的话,那系统就会默认每个组成部分具备单独的语义,那显然非常容易检索到不相关的内容。
拼写检测。就是检测query中到底哪个字错了。常用的方案是利用已有的词典或语言模型的统计结果,结合句法分析的规则来确定错误的字。目前学术界有些新颖的方案,比如说利用序列标注找错误点。但是在实际测试中,这样的模型都比较重,并且在我们的场景中其预测准确率的问题不会特别突出,所以我们目前还是保留比较传统的方式。
生成候选词。常见的做法就是利用同音、同型字典把出错的字替换掉,然后生成一个候选集合。这里值得一提的是:如果我们所在的业务场景是比较窄的情况下,比如只需要搜索药品或者搜索疾病时,我们借鉴18年发表在IEEE上一篇关于医疗概念归一化的文章,它的主要思路是对原文本中一些字做增减或者替换,然后构建一个confusion set ( 混淆字集合 ),把词跟字的连接构成一个graph,然后获得graph上的embedding之后一起放进端到端的auto encoder,即DAE,把DAE训练到收敛之后会使用一个向量集的检索生成候选集。在实践中,这个方案效果更优一些。
构建一个有标注的数据集,用PMI等统计量特征,借助automated prhase算法进行正负样本拆分,然后训练分类器,最后用一个对长度做修正的函数对名词短语打分。在本例中芒果过敏就是我们最终想要的名词短语。
这里的NER在结构上采用了业界的标配:CRF+Bi-LSTM。在离线场景,允许NER耗时长一点,可加一些BERT之类的encoder作为输入。目前在我们的场景,该NER可以支持20多种医学实体的识别。
生成类似短语的那种lexicon,把字、词、lexicon的关系建成一个graph,再把graph的特征融进NER中。
这两种方案在效果上确实有提升,但坦率地说,因为带有lattice这种结构,计算复杂度一般都比较高。我们这里谈论的是短文本理解,作为一个相对前置的任务,可能这样的复杂度耗时还是长了些。所以在实际的应用中我们还是会使用基础版NER模型作为我们流程中的一个组件。
我们现在还是以基础版的组件继续往下走,以上的几个步骤为后续做实体链接框定了词的边界。候选词一般我们用常见的搜索引擎,比如solr,给它做一个倒排索引,然后我们再拿mention去找目标实体词。如果是下面的情况,医学名词的span非常长,mention提取时,其实就失败了。这种失败也会直接导致实体链接的失败,所以我们的思路就是在召回阶段再做一层补充的策略。
前面提到医学中的长词通常会由多个组成成分进行组合。这种组成成分其实可以根据一些先验知识把它先规范好。相似的思路,我们在华东理工大学的一篇工作中也看到了。文章作者是根据SNOMEDCT中临床发现的分类层次体系把症状词拆分成了不同的组成。我们也根据自身的场景完善了12个类别的成分原子词,比如例子中的主动脉瓣退行性病变,然后可以分成:身体部位+特征词+性质修饰词。
同时,不同的组成成分在位置上存在的是有限的组合,通过对已有的一些实体词挖掘,最后我们可以固定1300多种组合。后续我们再将这些原子词和组成成分相互连接,构成一个graph。然后固定的组成成分的组合类型,就为图中的有向边提供了数据来源。我们拿这个graph可以使用LINE、node2vec之类的方式train一个embedding。我们采用的是清华大学19年在IJCAI上发表的矩阵分解的方法。可以看到我们train完graph embedding后,相似度聚合的一些结果。可以发现以这种方式结构化一个疾病词可以保证疾病词在结构上的稳定。也就是说,原始的排列组合想要表述的是某种肿瘤,我们需要保留这个肿瘤作为base词的结构。
当我们解决了识别准确率的问题后,接下来就是如何解决短文本的理解问题。我们认为短文本之所以难理解,不仅在于长度较短,同时也因为文本中的语法相对比较自由,且需要在非常有限的信息中解析出语义的逻辑。所以我们分析了在我们搜索场景中用户日常表述的特点,除了单一实体词为搜索query外,其他大致可以分为这四种情况:
第一种情况就是用户的需求在于想要获取围绕某个实体词的属性信息,比如:高血糖的判断标准、糖尿病的并发症。常规做法上,我们会对query做实体链接,高血糖是知识库中的一个实体词。在这样的流程下,经过一个倒排索引做文章的检索,或者帖子的检索,会很容易发生主题上的偏移。
第二种情况是由多个实体词合并出完整语义,比如2020年执业医师考试大纲。2020年、执业医师和考试大纲三者都是独立的实体词,但是存在相互约束和限制,所以需要合并成整个短语来保留语义。
第三种情况比较类似上面的例子,也是多个实体词,但不同的是:他们是围绕一个潜在的主题来表达的一些关键词。比如:新冠疫情在哈萨克斯坦的现状这一主题,用户可能只会搜索新冠+空格+哈萨克斯坦之类的表述。
第四种情况是包含复杂逻辑的句子。句子中会包含一些上下文的语境以及复杂的逻辑。
来看一个具体的query——短T1长T2,短T1长T2是什么意思呢?其实T1和T2分别代表着核磁共振中纵向与横向磁场变化的一个常量系数,两种磁场变化最终会影响骨骼与肌肉脏器在片子中的成像情况。这样的表述,通常会出现在病例影像讨论的帖子中,用户搜索的目的可能是想找类似的病例讨论,也可能是想学习一下核磁共振读片的方法。所以其语意从短短的几个字是无法从字面上获取的。所以,这些语义从何而来?可以很朴素的理解,信息始终只有两个来源:一个是人的先验知识,源自我们专业医学知识图谱的构建;第二是行为数据,对应的就是我们日常的业务日志以及文本上的挖掘。在理想的情况下,我们希望短T1长T2可以转换成,如:核磁共振的成像原理、影像、核医学、神经内科这样的主题,然后在这样的主题下再去关联到具体资讯的文章。
首先,我们收集了一批用户的搜索点击日志,然后在启动阶段定义一些种子模板,再利用模板和N-gram的策略产生一批短语,这些短语不会直接拿来用,因为其中会有一些边界问题或者模板带来的语义漂移问题。所以对生成的这些原始concept,我们会做一个分类器,作为在质量上的约束,留下质量比较高的concept。此外,再把生成的concept重新放到Query或者句子中,让它产生新的模板。这里模板的产生,我们也借鉴了韩家炜老师在MetaPAD上的一些工作。
最后,我们再对pattern做一层过滤,新的模板就可以重新再去抽concept。该算法整个结构就可以形成一个bootstrap的循环。这里安利一下腾讯团队郭老师等在去年KDD上发表的工作,工作做得非常的漂亮,也给我们提供了非常多的启发。
利用挖掘到的concept词,我们可以联合底层的专业的医学实体和上层的业务数据构建起一个完整的业务图谱,其中一对一的边计算的都是以Bayes模型为基础,会考虑全局统计量或者文本的局部特征;生成的多对多的边之后,我们参考王仲远老师的一些相关工作中提到的MDL ( Minimum Description Length ) 的原则做concept的筛选。这样半岛全站,论坛帖子、药品信息、商城的商品就可以通过中间的concept层完成了实体链接。
目前Query扩展的问题主要有两类方法:第一种是利用query词和document词的相关性构建一个贝叶斯模型,扩展的结果就是document词或者是document中出现的一些词组,这样会帮助在召回阶段扩大潜在用户想要的文本。第二种方法,是把它作为一种翻译模型,从query词翻译到document词。
早期比较朴素的方案是用EM算法找两类词的对齐关系,现在新的方案都是上神经网络train一个生成模型。在我们有了concept层之后,用一些很简单的策略就能有不错的效果,比如我们会直接使用相关性的方式,也就是刚才提到的第一类方法去建模,就可以把原始query向concept层上扩展。比如哈萨克斯坦,就可以扩展出新冠疫情或不明肺炎;同样,在电商场景下,我们可以利用扩展的concept和其他的实体关系做一个二级扩展,比如产褥垫可以扩展出待产包,然后再从待产包扩展出卫生巾、纸尿裤。这样的应用其实也带了一点推荐的意思。
我们在文本结构化上也可以利用concept做一些提升,文本结构化对于提升搜索效果起到了非常重要的作用。有了concept之后可以帮助我们从抽象的层面完成对文本打标签。业界中比较好的方案,是先用一个TransE之类的知识表示模型,把知识图谱train出Embedding,然后将这些Embedding融合进LDA的模型中。在模型中,会用vMF分布代替原来的高斯分布来处理实体词的部分。这样我们就会对一篇,如麻醉不良习惯的讨论帖子抽出麻醉医学和麻醉的不良习惯这样的关键词。
丁香园 资深NLP算法工程师杨比特,硕士毕业于军事医学科学院,负责丁香园大数据NLP组,目前专注于医疗健康领域下的自然语言处理、知识图谱构建与应用、搜索与推荐技术。
访问手机版
微信公众号