没有挂网公布,需要咨询专业人士。
C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。
C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。
C语言诞生于美国的贝尔实验室,由丹尼斯·里奇(Dennis MacAlistair Ritchie)以肯·汤普森(Kenneth Lane Thompson)设计的B语言为基础发展而来,在它的主体设计完成后,汤普逊和里奇用它完全重写了UNIX,且随着UNIX的发展,c语言也得到了不断的完善。
为了利于C语言的全面推广,许多专家学者和硬件厂商联合组成了C语言标准委员会,并在之后的1989年,诞生了第一个完备的C标准,简称“C89”,也就是“ANSI C”,截至2020年,最新的C语言标准为2018年6月发布的“C18”。
众所周知,英文是以词为单位的,词和词之间是靠空格隔开,而中文是以字为单位,句子中所有的字连起来才能描述一个意思。例如,英文句子I am a student,用中文则为:“我是一个学生”。计算机可以很简单通过空格知道student是一个单词,但是不能很容易明白“学”、“生”两个字合起来才表示一个词。把中文的汉字序列切分成有意义的词,就是中文分词,有些人也称为切词。我是一个学生,分词的结果是:我 是 一个 学生。
中文分词技术属于自然语言处理技术范畴,对于一句话,人可以通过自己的知识来明白哪些是词,哪些不是词,但如何让计算机也能理解?其处理过程就是分词算法。
现有的分词算法可分为三大类:基于字符串匹配的分词方法、基于理解的分词方法和基于统计的分词方法。
1、基于字符串匹配的分词方法
这种方法又叫做机械分词方法,它是按照一定的策略将待分析的汉字串与一个“充分大的”机器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。按照扫描方向的不同,串匹配分词方法可以分为正向匹配和逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与标注相结合的一体化方法。常用的几种机械分词方法如下:
1)正向最大匹配法(由左到右的方向);
2)逆向最大匹配法(由右到左的方向);
3)最少切分(使每一句中切出的词数最小)。
还可以将上述各种方法相互组合,例如,可以将正向最大匹配方法和逆向最大匹配方法结合起来构成双向匹配法。由于汉语单字成词的特点,正向最小匹配和逆向最小匹配一般很少使用。一般说来,逆向匹配的切分精度略高于正向匹配,遇到的歧义现象也较少。统计结果表明,单纯使用正向最大匹配的错误率为1/169,单纯使用逆向最大匹配的错误率为1/245。但这种精度还远远不能满足实际的需要。实际使用的分词系统,都是把机械分词作为一种初分手段,还需通过利用各种其它的语言信息来进一步提高切分的准确率。
一种方法是改进扫描方式,称为特征扫描或标志切分,优先在待分析字符串中识别和切分出一些带有明显特征的词,以这些词作为断点,可将原字符串分为较小的串再来进机械分词,从而减少匹配的错误率。另一种方法是将分词和词类标注结合起来,利用丰富的词类信息对分词决策提供帮助,并且在标注过程中又反过来对分词结果进行检验、调整,从而极大地提高切分的准确率。
对于机械分词方法,可以建立一个一般的模型,在这方面有专业的学术论文,这里不做详细论述。
2、基于理解的分词方法
这种分词方法是通过让计算机模拟人对句子的理解,达到识别词的效果。其基本思想就是在分词的同时进行句法、语义分析,利用句法信息和语义信息来处理歧义现象。它通常包括三个部分:分词子系统、句法语义子系统、总控部分。在总控部分的协调下,分词子系统可以获得有关词、句子等的句法和语义信息来对分词歧义进行判断,即它模拟了人对句子的理解过程。这种分词方法需要使用大量的语言知识和信息。由于汉语语言知识的笼统、复杂性,难以将各种语言信息组织成机器可直接读取的形式,因此目前基于理解的分词系统还处在试验阶段。
3、基于统计的分词方法
从形式上看,词是稳定的字的组合,因此在上下文中,相邻的字同时出现的次数越多,就越有可能构成一个词。因此字与字相邻共现的频率或概率能够较好的反映成词的可信度。可以对语料中相邻共现的各个字的组合的频度进行统计,计算它们的互现信息。定义两个字的互现信息,计算两个汉字X、Y的相邻共现概率。互现信息体现了汉字之间结合关系的紧密程度。当紧密程度高于某一个阈值时,便可认为此字组可能构成了一个词。这种方法只需对语料中的字组频度进行统计,不需要切分词典,因而又叫做无词典分词法或统计取词方法。但这种方法也有一定的局限性,会经常抽出一些共现频度高、但并不是词的常用字组,例如“这一”、“之一”、“有的”、“我的”、“许多的”等,并且对常用词的识别精度差,时空开销大。实际应用的统计分词系统都要使用一部基本的分词词典(常用词词典)进行串匹配分词,同时使用统计方法识别一些新的词,即将串频统计和串匹配结合起来,既发挥匹配分词切分速度快、效率高的特点,又利用了无词典分词结合上下文识别生词、自动消除歧义的优点。
到底哪种分词算法的准确度更高,目前并无定论。对于任何一个成熟的分词系统来说,不可能单独依靠某一种算法来实现,都需要综合不同的算法。笔者了解,海量科技的分词算法就采用“复方分词法”,所谓复方,相当于用中药中的复方概念,即用不同的药才综合起来去医治疾病,同样,对于中文词的识别,需要多种算法来处理不同的问题。
以下分词工具均能在Python环境中直接调用(排名不分先后)。
1、jieba(结巴分词) 免费使用
2、HanLP(汉语言处理包) 免费使用
3、SnowNLP(中文的类库) 免费使用
4、FoolNLTK(中文处理工具包) 免费使用
5、Jiagu(甲骨NLP) 免费使用
6、pyltp(哈工大语言云) 商用需要付费
7、THULAC(清华中文词法分析工具包) 商用需要付费
8、NLPIR(汉语分词系统) 付费使用
1、jieba(结巴分词)
“结巴”中文分词:做最好的 Python 中文分词组件。
项目Github地址:jieba
安装 :
pip install jieba
使用 :
import jieba
jiebainitialize()
text = '化妆和服装'
words = jiebacut(text)
words = list(words)
print(words)
2、HanLP(汉语言处理包)
HanLP是一系列模型与算法组成的NLP工具包,由大快搜索主导并完全开源,目标是普及自然语言处理在生产环境中的应用。HanLP具备功能完善、性能高效、架构清晰、语料时新、可自定义的特点。
项目Github地址:pyhanlp
安装:
pip install pyhanlp
使用 :
import pyhanlp
text = '化妆和服装'
words = []
for term in pyhanlpHanLPsegment(text):
wordsappend(termword)
print(words)
3、SnowNLP(中文的类库)
SnowNLP是一个python写的类库,可以方便的处理中文文本内容,是受到了TextBlob的启发而写的,由于现在大部分的自然语言处理库基本都是针对英文的,于是写了一个方便处理中文的类库,并且和TextBlob不同的是,这里没有用NLTK,所有的算法都是自己实现的,并且自带了一些训练好的字典。
项目Github地址:snownlp
安装:
pip install snownlp
使用:
import snownlp
text = '化妆和服装'
words = snownlpSnowNLP(text)words
print(words)
4、FoolNLTK(中文处理工具包)
可能不是最快的开源中文分词,但很可能是最准的开源中文分词。
项目Github地址:FoolNLTK
安装:
pip install foolnltk
使用:
import fool
text = '化妆和服装'
words = foolcut(text)
print(words)
5、Jiagu(甲骨NLP)
基于BiLSTM模型,使用大规模语料训练而成。将提供中文分词、词性标注、命名实体识别、关键词抽取、文本摘要、新词发现等常用自然语言处理功能。参考了各大工具优缺点制作,将Jiagu回馈给大家。
项目Github地址:jiagu
安装:
pip3 install jiagu
使用:
import jiagu
jiaguinit()
text = '化妆和服装'
words = jiaguseg(text)
print(words)
6、pyltp(哈工大语言云)
pyltp 是 LTP 的 Python 封装,提供了分词,词性标注,命名实体识别,依存句法分析,语义角色标注的功能。
项目Github地址:pyltp,34模型下载链接:网盘
安装:
pip install pyltp
使用:
import pyltp
segmentor = pyltpSegmentor()
segmentorload('model/ltp_data_v340/cwsmodel') # 模型放置的路径
text = '化妆和服装'
words = segmentorsegment(text)
words = list(words)
print(words)
7、THULAC(清华中文词法分析工具包)
THULAC(THU Lexical Analyzer for Chinese)由清华大学自然语言处理与 社会 人文计算实验室研制推出的一套中文词法分析工具包,具有中文分词和词性标注功能。
项目Github地址:THULAC-Python
安装:
pip install thulac
使用:
import thulac
thu = thulacthulac(seg_only=True)
text = '化妆和服装'
words = thucut(text, text=True)split()
print(words)
NLPIR(汉语分词系统)
主要功能包括中文分词;英文分词;词性标注;命名实体识别;新词识别;关键词提取;支持用户专业词典与微博分析。NLPIR系统支持多种编码、多种操作系统、多种开发语言与平台。
项目Github地址:pynlpir
安装:
pip install pynlpir
下载证书覆盖到安装目录,NLPIRuser 例如安装目录:/usr/lib64/python34/site-packages/pynlpir/Data
使用 :
import pynlpir
pynlpiropen()
text = '化妆和服装'
words = pynlpirsegment(text, pos_tagging=False)
print(words)
pynlpirclose()
那么我们如果想要获得更多的搜索流量,就需要我们标题当中的关键词的权重比较高,这样当买家在搜索关键词的时候,我们的宝贝才会有机会排在前面,有了展现,才有机会获得点击,进而才会有更多的免费搜索流量。
在讲如何提升标题关键词的权重的方法之前,我先为大家讲解一下搜索引擎的分词原理。
搜索引擎分词原理:分词技术就是搜索引擎针对用户提交查询的关键词串,进行一定的处理后,根据用户的关键词串用各种匹配方法进行的一种关键词处理技术。
以上专业化的定义可能大家还不是太明白。
那么我举个例子,当我们的宝贝标题写好后,一切都准备好,然后上架了,对于淘宝的搜索引擎一般更新是比较快的,通常情况下不到10分钟就可以用你宝贝的全标题搜索到你的宝贝了!
这个时候呢,只要发现全标题能搜索到我们的宝贝,我们就可以用老A市场分析精灵中的智能分词功能,来看下搜索引擎对我们的标题到底会切分成什么样的独体词。
(注:什么是独体词?独体词也叫词根,通常是搜索引擎调用分词算法,切分出来的词的最小单位)
如图:
针对这个标题:
2015夏 韩版新款 棉麻亚麻收腰连衣裙修身显瘦背心裙打底裙 短裙
切分后:
(2015,夏,韩版,新款,棉麻,亚麻,收腰,连衣裙,修身,显瘦,背心,裙,打底,短裙)
那么搜索引擎为什么一定要为一个标题进行关键词的切分呢?
1、通过分词算法来判断你的宝贝是什么
2、通过分词算法来计算各关键词的位置以及相邻的词
3、通过分词算法来为宝贝提供更正确的排序索引集合
(2015,夏,韩版,新款,棉麻,亚麻,收腰,连衣裙,修身,显瘦,背心,裙,打底,短裙)
在这里我给大家提个问题吧?这些独体词中,哪个词是最重要的词,为什么?欢迎大家评论回答,互动一下!
大家把上面的内容搞清楚后,就可以学习一下我们如何一步步提升整个标题的关键词权重了。
请看如下思维导图:
以上说明了什么 我来解释一下
1、如果有一个顾客通过搜索 大码立领蕾丝衫 产生了转化,那么大码立领蕾丝衫是可以切分成三个词根,分别是 (大码,立领,蕾丝衫)那么每一个词根都会被加分。
2、如果有一个顾客通过搜索 大码修身蕾丝衫 产生了转化,那么大码修身蕾丝衫是可以切分成三个词根,分别是 (大码,修身,蕾丝衫)那么每一个词根都会被加分。
如图
大家仔细看这个图表,假设加分规则如上,我们会知道,大码被加了2分,蕾丝衫加了2分,立领加1分,修身加1分。
通过这样的计算,相当于标题当中的某些词分值高了,整个标题的权重也增加了!
这里为什么说整个标题的权重都增加了呢?
因为 蕾丝衫 是这个标题当中的中心词,所有的搜索关键词,都是围绕着这个中心词的组合,只要这个中心词的分值越高,整个标题的权重就会提高。
那么讲到这里大家就要回想一下我们的标题打造为什么那样设计?
标题打造的思维导图大家再对照看一下!
注明:本标题打造方法 就是考虑到一步一步提升关键词权重的,先从长尾词再到竞争关键词,再到中心词一步一步提升整个标题的权重,让你在不同的阶段抢到跟你宝贝权重相匹配的流量。
接下来我再抛出一个疑问,如果有买家搜索某个词进入到我的宝贝如果没转化是不是不加分呢?
当然不会的,在搜索引擎系统的计算中肯定不会只考虑转化了,当然还有其它参数 (上面用转化来举例是为了方便大家理解)
事实上,我们可以把整个影响搜索加分的参数统称为点击反馈数据
如图 影响点击反馈的主要指标有:
转化率
收藏率
停留时间
关键词点击率
加购率
等
只要这些指标反馈好,关键词词根一样会加分。
但是这里大家要明白一个道理,这样数据好会加分,那么不好也会减分的啊!所以我们如果想要让我们的标题中的关键词权重越来越高,就需要考虑如何跟搜索引擎交换正向的数据,而不是反向的,同时一个关键词权重的提升,也是需要一定时间的,只有达到一定的时间,它才会体现出来,为你抢到更多的搜索流量。
最后呢 我给大家出个题吧,因为经常有同学会问我,老师我新做的标题好不好呢? 在这里我举个示例,你们回答一下这个标题好不好,它的问题在哪里?
标题:2015春装新款连衣裙女包臀修身显瘦短裙子OL气质长袖蕾丝打底裙女
分词结果:2015,春装,新款,连衣裙,女包,臀,修身,显瘦,短裙,子,OL,气质,长袖,蕾丝,打底,裙,女
如图:
在产品算法化的时代,不了解算法,恐怕难以做好一款产品的设计。无论是信息流的推送还是搜索结果的展示,算法深刻塑造了用户体验。因此,了解算法,是作为PM的一项基础功课。本文总结了常见的一些算法知识,很多来自我对网路大神们的分享进行的梳理,大家一起补补课。由于文章内容较长,因此会分很多天更新完,下面进入正题。
一、热度算法。
假如现在我们要给一款新闻应用设计内容的分发机制,请问怎样分发新闻内容更为合理呢?在考虑算法时,我们首先想到有几个约束条件:
①不同新闻的重要性并不相同。
②用户参与的各种行为会助推或拉低新闻热度。
③新闻有时效性,热度随时间衰减。
④不同的人,新闻喜好是不同的。
前3个问题,我们首先解决。
11初始热度分S0
问题1的解决方案很简单,给不同类型的新闻赋予不同的初始值S0。比如,娱乐类新闻往往比文化类的新闻的热度更高,大家更爱看,因此初始值更大一点。
上图中,06、08、12、15就是不同类别新闻的初始权重。
上述初始值的设定还有一条补充,就是当天的重大头条新闻,我们希望入库时热度就很高。比如马保国老师打拳居然赢了迪迦奥特曼。为了让新闻媒体刚发出来就有很高的热度。我们需要提前准备一个 热词库 ,每天抓取各类头部门户网站或社交网站上的新闻热词。一旦平台上有用户发布的新闻命中了当天的热词,如:“马保国”、“奥特曼”、“迪迦”,我们就给这个用户的内容赋予较高的初始热度。
12用户交互热度分S(Users)
问题2的解决方案,是把表征用户喜好的各种行为拎出来。比如浏览、评论、点赞、喜欢、收藏、分享、转发、点踩、举报、截图等等。行为越多,颗粒越细。
比如我们只取几个指标:浏览(1分)、点赞(3分)、评论(5分)、分享(10分)
一个用户如果在某条新闻上都命中了上述行为,那么这条新闻可以获得的该用户S(Users)为:18分。
但是,这种计算方法还有一个问题要解决,那就是用户规模的问题。刚发出去的新闻,肯定看得人少,我们希望可以强化用户行为分,让用户的一个点赞和评价可以很强地助推该条新闻热度。但是随着阅读的人越来越多,我们希望可以弱化用户行为分。因此,需要针对用户规模,强化或者弱化用户的行为权重。用什么数学工具去解决这一问题?留给你思考。
13时间衰减热度分
问题3的解决方案需要用到一个工具。我们希望新闻的热度是随着时间而递减的,这样大家随时看到的都是新闻而不是旧闻了。如何来度量这种随时间递减的热度呢?
想像一下,房间里放了一杯热咖啡,这杯咖啡会随着温度慢慢衰减,直到与房间室温持平。新闻的热度就像房间里的热咖啡,随着时间而慢慢降温。因此,这里的工具就是牛顿冷却定律。
牛顿冷却定律 是由英国物理学家艾萨克·牛顿爵士(1642-1727)所提出的一个经验性的关系。是指物体所损失的热的速率与物体和其周围环境间的温度差是成比例的。当物体表面与周围存在温度差时,单位时间从单位面积散失的热量与温度差成正比,比例系数称为热传递系数。
数学公式为:
公式变换之后,变成下面更容易理解的公式:
其中,T0:初始温度、T(t):物体当前的温度、to:初始时刻、t:某个时刻、H:周围的温度、α: 冷却系数。
将公式里的温度T换成热度,就可以用来衡量新闻的热度衰减了。这里面最核心的是冷却系数α,α在控制不同类型内容的衰减程度。有些内容的更替速度快,我们设置的冷却系数可以大一些,有些更替速度慢,我们可以控制得小一些。
具体计算冷却系数,可以这样操作。假设我们认为初始热度分为100,24小时后,热度分为1,那么就有:1=100e^(-24α),得到α=0192。从这里可以看到,当我们希望一条内容,用时多久,可以冷却到何种程度时,即可确定α值。需要注意的是,此处计算我们设定的t-to的差值,是按小时为单位来计算的,而不是按照分钟或者秒。
找到了衡量新闻热度衰减的办法,如何用在整体的新闻热度分呢?
开头部分用了这个公式来大概描述我们希望达成的效果: 新闻热度分 = 初始热度分 + 用户交互产生的热度分 – 随时间衰减的热度分, Score = S0 + S(Users) – S(Time)。
看了上面的牛顿冷却定律后,该公式可以演化为Score =(S0 + S(Users))/(e^α(t-t0))
如果只是解决了前3个问题,即:初始热度分、用户行为助推热度分、热度分衰减,那么大家看到的新闻都是一样的,以前的网易新闻、腾讯新闻不就是这样么?现在我们想给不同的人推荐不同的新闻,怎么办?这便是今日头条解决的问题了。需要用到个性化推荐了。
个性化推荐一般有两种方法,方法1是根据内容相识度推荐。比如你喜欢看科比的新闻,那么我推荐欧文的似乎也不错。方法2是根据用户品味相识度推荐。比如你喜欢科比,另一个人也喜欢科比,那么我可以推荐另一个喜欢的新闻给到你。下来来说一说如何采取这两种办法来推荐。
二、基于内容推荐
按照方法1,我们是需要计算出两篇新闻的相似度。那么两篇新闻的关系要怎么计算呢?
首先呢,第一步我们需要对新闻进行分词。比如这样一个句子:科比是世界上最优秀的篮球运动员,詹姆斯也是。这句话我们分词后便得到了如下词组:科比、世界、优秀、篮球运动员、詹姆斯、是、也、上。
从这个词组可以看出,“是”、“也”、“上”这类词并没有太多含义,需要去掉,留下的词才有意义。因此,我们分词的时候,需要用到两个词库,正常词库和停用词库。停用词库的内容就是上述去掉的那类词,而正常词库就是我们拆解内容的标准。一篇新闻就是按照正常词库拆成一个个单独的词&词组的。
那么这里有个问题,就是分词到底是怎么分的。一般分词的方法有很多种,正向匹配拆分,逆向匹配拆分,最少切分。
正向匹配法是从左向右扫描寻找词的最大匹配。一般会先规定一个词的最大长度,每次扫描的时候寻找当前开始的这个长度的词来和字典中的词匹配,如果没有找到,就缩短长度继续寻找,直到找到或者成为单字。
举个例子。我们拟分词的长句为:科比见过凌晨四点的天空。
我们词典是这样的:{科比、见过、凌晨四点、天空}
那么正向匹配法是怎么运行的呢?
首先我们设定最大词长为4。我们从左到右,先试试4个字符"科比见过",来跟我们词典匹配,发现没有匹配到的。那就缩短字符,试一试“科比见”,发现还是没有。继续缩短字符,试一试“科比”,词组中出现了!
好了,我们分出了第一个词,把这个词从原句中踢掉,那么原句现在变为:见过凌晨四点的天空。
继续按照原方法分词。先试试最左侧的4个字符“见过凌晨”,来跟词典匹配,找不到匹配的词。继续缩短字符“见过凌”,来跟词典匹配,还是匹配不到,那么继续缩短。
依次按照上述方法,这样长句就会被分成一个个词组了。这就是正向匹配法。
逆向匹配法是从右至左,分词规则跟正向匹配法差不多,就不赘叙了。
最少切分法是依据最少切分原则,从几种分词算法切分结果中取切分词数最少一种的。比如,从正向最大匹配和逆向最大匹配两者中选择词数较少的方案,当词数相同时,采取某种策略,选择其中一个。
在 《浅谈智能搜索和对话式OS》 中,提到过,人机对话系统的常见场景有三种,分别为: 闲聊型(Chatbot) 、 问答型(QA) 、 任务型(VPA) 。本篇文章所关注的解析方式主要适用于QA系统中的封闭域问答,也即: 将用户问句解析为库中存在的标准问句 。
这里讲的七种方法均为我个人阅读文献后归纳整理而来,并不都是成熟稳定可以商业化的做法,目的只是提出思路以作参考。
基于规则的方法通常在缺乏训练数据的情况下采用,由于与后面的基于统计的方法区别较大,所以记为第零种方法。
基于规则的解析系统通常由两部分构成:一个是『规则库』,解析规则通常为 CFG 上下文无关文法;另一个是『同义词库』,记录了一些标准词的常见同义词。
整个解析就是一个上下文无关文法归约的过程。首先进行自动分词,接着将用户问句中的词依照『同义词库』归约为标准词,然后再将词归约后的问句与『规则库』中的解析规则比对,一旦比对成功,即该条用户问句被成功归约到该条解析规则所对应的标准问句上。
举个例子,同义词库中有这样两条记录:『失败:不上去、不进去、不成功、错误』『登录:登陆、登录』,规则库中有这样一条规则:『账号登录失败:[账号][登录][失败]』。
有一条用户问句是这样的『我账号怎么登陆不上去了』。首先假定分词正确,分词结果为『我|账号|怎么|登陆|不上去|了』;之后进行词归约,归约结果为『我账号怎么登录失败了』;接着与规则『账号登录失败:[账号][登录][失败]』比对,发现比对成功。该条用户问句被成功归约为标准问句『账号登录失败』,我们将系统中『账号登录失败』所对应的标准答案提供给用户,完成交互流程。
这样做在一定程度上能够解决问题,但缺点也特别严重。首先『规则库』与『同义词库』需要人工构建,这需要巨大且长期的人力资源投入。因为语言的表达方式理论上是无限的,而能想到的规则和同义词总是有限的;且随着语言的发展,或是业务的变动,整个规则库和同义词库的维护也需要持续的人力资源投入。
其次,编写规则库需要丰富的经验,对于人员素质的要求极高。因为解析规则的抽象程度相当高,在这样高的抽象程度上,即便编写者具有较丰富的经验(如果没经验会更糟),不同解析规则之间的冲突也是不可避免的,也即同一条用户问句会与多条标准问句的解析规则比对成功,这种情况下的标准问句选择/评分问题,又需要另一套系统来解决。
换个角度,我们可以将依照用户问句找到标准问句的过程看做是输入 Query 得到 Document 的搜索过程。
我们可以尝试采用传统搜索引擎中使用的检索模型来进行用户问句解析。 《浅谈搜索引擎基础(上)》 中提到,BM25 是目前效果最好的检索模型,我们就以 BM25 模型为例来分析。
BM25 模型的计算公式如下:
BM25 模型计算公式融合了 4 个考虑因素: IDF 因子 、 文档词频 、 文档长度因子 和 查询词频 ,并利用 3 个自由调节因子(k1、k2 和 b)对各种因子的权值进行调整组合。
其中,N 代表文档总数,n 代表出现对应单词的文档个数,f 指文档中出现对应单词的词频,qf 是查询语句中对应单词的词频,dl 是文档长度。
利用 BM25 模型可以有三种思路,分别把标准问句、标准问句及标准答案、历史中曾经正确匹配过该标准问句的用户问句集作为 Document,利用公式计算其与用户问句的相似度,然后利用相似度进行排序,取出评分最高的标准问句作为解析结果。
对于这个思路我没有做过实验,不过我推测,这种方法虽然节省了大量的人力,但在这种封闭域的 QA 系统中,其表现应当是不如上一种基于规则的方法,基于检索模型的方法在开放域中的表现会更好。
此外,基于传统检索模型的方法会存在一个固有缺陷,就是检索模型只能处理 Query 与 Document 有重合词的情况,传统检索模型无法处理词语的语义相关性。在上一种方法中,通过人工搭建的同义词库,一定程度上解决了语义相关性的问题。
上文提到,完全基于检索模型的方法无法处理词语的语义相关性。
为了在一定程度上解决这个问题,我们可以利用 LDA/SMT 等方法通过语料挖掘词之间的同义关系,为每个词自动构建一个同义度高于阈值且大小合适的同义词表。在代入检索模型公式进行计算的过程中,若文档中发现所查找关键词的同义词,可以依据同义程度乘以一定权重后纳入到关键词的词频计算之中。
《浅谈智能搜索和对话式OS》 中有对 LDA/SMT 的介绍。
简单的说,LDA 可以合理的将单词归类到不同的隐含主题之中;并且通过计算两篇文章主题向量 θ 的 KL 散度(相对熵),可以得到两篇文章的相似性。SMT 模型出自微软之手,目的即是将翻译模型引入传统检索模型,提高检索模型对语义相关词对的处理能力,该模型也曾被百度采用过以提高搜索引擎返回结果的质量。
word embedding 将词表示为 Distributed Representation,也即低维向量空间中的一个词向量,Distributed Representation 下的词可以利用余弦距离来计算词之间语义的相关关系。与 one-hot Representation 相对应,one-hot Representation 下的词向量的维数与单词表的维数相同,不同词的词向量之间均正交。传统的词集模型(SOW)和词袋模型(BOW)采用的即是 one-hot Representation。
我们可以采用深度学习的方法来得到词 Distributed Representation 的词向量。比如训练一个普通的神经概率语言模型,就可以得到词的词向量,或者参考 word2vec 中的方式,训练 CBOW 或者 Skip-gram 模型。神经概率语言模型、CBOW 以及 Skip-gram 的介绍在 《浅谈智能搜索和对话式OS》 均有提及。
借助百度这张图来讲,利用 DNN 建模的思路如下:
我们需要使用一批 用户问句-标准问句对 的正例和反例作为训练语料,借助上面的方式,同时将正例和反例进行 word embedding 后送入 DNN 中,并采用 Pairwise ranking loss 的方式来建模正例和反例之间的语义差别。
上一种基于 DNN 的方法,在一定程度上已经可以解决词的语义相关性的问题,但对句子中的短距离依赖关系并没有做恰当的处理,比如无法区分『甲到乙』和『乙到甲』。
根据百度的评测结果,CNN 在处理短距离依赖关系上拥有更好的表现。
该图出自李航博士 Convolutional Neural Network Architectures for Matching Natural Language Sentences 中的 ARC-1:
其做法的基本思路是:将问句中的每个词,都做 word embedding,得到每个词所对应的固定长度的词向量,我们将问句表示成一个二维矩阵,每一行代表问句中相应词所对应的词向量。将这个二维矩阵进行多次卷积池化(卷积核的宽度与词向量维数相同,高度多为 2-5),最后得到一个一维特征向量,我们用 CNN 同时处理用户问句和标准问句,得到用户问句和库中标准问句所对应的特征向量。之后将这两个向量拼接起来送入多层感知机,由它来计算两个问句之间的匹配程度。
另外,有人指出,直接将两个特征向量拼接起来送入 MLP 会丢失边界信息,所以我们同时将特征向量 a、特征向量 b 和 aTb 同时送入 MLP 来计算相似度。
ARC-2 结构同样出自李航博士的上述论文:
ARC-2 相较于 ARC-1 的改进在于,ARC-2 尝试让两个句子在得到像 ARC-1 结果那样的高层抽象表示之前就进行相互作用,不再先分别通过 CNN 结构得到各自高层抽象表示。
在 ARC-1 模型中,一张 feature map 仅仅是一个列向量,或者说是一个一维矩阵,若干个列向量并在一起形成了 ARC-1 示意图中的模样(二维),而在 ARC-2 中,一张 feature map 成为了一个二维矩阵,若干个二维矩阵叠在一起形成了 ARC-2 示意图中的模样(三维)。
再之后的卷积、池化过程就与 CV 中 CNN 的卷积、池化过程类似了。与上一种方法类似的,在进行 1D convolution 时,涉及到两个词向量的连接,同样可以采用之前提到的做法来避免边界信息的丢失。
同样有人提出,在 ARC-2 结构中,直接采用传统的 word embedding 方法得到的词向量组成句子作为输入并不是最佳方案,最佳方案是采用已经过了 LSTM 的 hidden state。
我们可以采用 LSTM 结构训练一个 RNN 语言模型,如下图(以普通 RNN 为例):
从图中可以发现,当输出为『e』时,hidden layer 向量中第三分量最大,而输出为『l』时,第一分量最大,输出『o』时,第二分量最大。我们可以将 RNN 的 hidden state 当做 Distributed Representation 的词向量来使用,将其作为 CNN(ARC-2)的输入,经测试可以得到更好的结果。
一个可信度高的分词结果是进行后续解析步骤的基本前提。
在 《浅谈自然语言处理基础(中)》 中,我介绍了一些经典的分词方法,不过都是些较早的研究成果。CRF方法是目前公认的效果最好的分词算法。
CRF 方法的思想非常直接,就是将分词问题看作一个序列标注问题,为句子中的每个字标注词位:
CRF 分词的过程就是对词位标注后,将 B 和 E 之间的字,以及 S 单字构成分词。网上有很多公开的基于 CRF 的分词工具。
至少存在四个角度可以在已有模型的基础上进一步提高解析质量,包括:问句归一化、用户状态、强化学习、多轮对话。
问句归一化的目的是对用户的输入具有较好的容错性。
简单的一些比如:简繁体归一化、全角半角归一化、标点符号处理和大小写归一化。复杂一些的比如汉语错别字的纠正。错别字自动纠正技术的应用非常广泛,而且在提高系统用户体验上能够发挥很大的作用,可以说性价比极高。
错别字纠正通常的做法是训练噪声信道模型。
我们可以对用户状态提取特征,在训练和解析时将其作为附加信息一并作为神经网络的输入。
可以被考虑的用户状态至少包含:
其次可以采用强化学习的方法,通过设计合理的奖赏机制,让解析系统在与环境互动的过程中自主进行策略更新。
强化学习与普通的监督学习方法相比存在两个明显的优点:一个是强化学习策略更新所需要的数据主要来源于与环境的交互/采样,而不是昂贵的人工标记数据;另一个是强化学习所产生的策略是根据奖赏机制自主迭代更新的,会有一些创新的做法,而不仅仅是模仿人类提供的『标准』做法。
QA 问句解析中虽然不像游戏一样拥有『策略\创新玩法』这样的概念,但仍然可以在解析优化中帮助大量节省数据的人工标记开销。
应用强化学习方法的核心问题之一就是奖赏机制的设计,在 QA 的场景下设计奖赏机制,至少可以考虑以下几个角度:
多轮对话技术可以进一步提高与用户对话的连贯性。
我倾向于将多轮对话划分为『封闭域』和『开放域』两个场景,不同场景的实现思路也应该不同。
封闭域场景多轮对话的特点是:系统能解决的问题是一个有限集,多轮对话的目的是将用户引导到我们可以解决的问题上。
而开放域场景多轮对话的特点是:系统需要解决的问题是一个无限集,多轮对话的目的是依照上下文更准确的理解用户的需求。
在这样的指导思想下,封闭域多轮对话的核心思路应该是『填槽』,而开放域多轮对话的核心思路是『上下文替换』和『主体补全』。
《浅谈智能搜索和对话式OS》 中介绍了百度利用 slot filling 技术来做 NLU,并利用『上下文替换』和『主体补全』来提高其 DuerOS 的对话能力的。
而更进一步的,填槽、上下文替换和主体补全的技术基础都是『序列标注』,这里给出百度的两张 PPT:
根据百度的 PPT,采用双向 LSTM + CRF 做序列标注,是一个商业上可行的方法。
选择合适的人工接入时机同样是提高 QA 系统整体表现的方法之一,其核心问题在于平衡用户体验与投入成本。人工接入的越早,用户体验越好,但成本也越高。
这里简单提供蚂蚁金服小蚂答的做法:若系统连续提供给用户三次相同的回答,显示人工接入按钮;若用户连续询问两次客服类问题(比如『我要人工』、『你们客服电话多少』),显示人工接入按钮。
QA 系统的另一个重要组成部分是答案库。
答案录入的优化至少可以从三个角度来思考:
答案形式的多样性非常容易理解,比如小蚂答就支持包括文本、链接、、视频在内的多种答案形式。
个性化问题在上文解析优化中已有涉及(考虑用户状态的解析优化),上文的分析思路同样可以应用于答案录入,我们可以对不同注册时长、付费金额不同、进入路径不同等等的用户提供不同的个性化答案。
答案对用户的帮助看起来比较抽象,但也很容易理解。通俗的,我个人以『地图级』、『导航级』、『专车级』来为 QA 系统的答案进行分级:
依照文章最初的人机对话系统场景分类,提供『专车级』答案的 QA 系统,可以被称为 VPA 了。
对于答案库的优化,在答案完备录入(答案形式足够丰富、针对不同用户提供个性化的回答)的前提下,至少存在两个优化点:
上文解析优化中强化学习方法奖赏机制的设计思路也可以被用来发现答案库中存在的问题,因为大多数时候我们还很难明确的区分用户的负面反馈是针对解析系统还是答案本身。
除了从用户负面反馈中发现问题,针对上面的两个优化点,我们还应该有一些预防机制来提前避免这些问题的发生。
比如第一点『答案库中标准答案存在错误』,如果不是录入人员的素质问题,最大的可能性就来源于答案的时效性,也即我们提供给了用户过期的答案。针对这个问题,我们可以在录入答案时特别添加『临时』标签,以标明该答案具有较强的时效性,需要及时更新。
而针对第二点『答案库中缺失某些问题的答案』,最大的可能性来源于突发事件以及业务的变动。比如系统服务宕机、系统上了新版本或者组织了一些运营活动,我们都应该针对这些可能引发用户疑惑的变动,提前准备一些 FAQ 并录入到答案库之中。
此外,当我们录入新问题及其标准答案的时候,需要注意新录入问题与原解析系统的适配性,以避免出现新录入的问题较难被解析系统解析到的情况。可采用的方法比如在录入新问题的同时,主动录入一些不同的问法作为初始训练语料(网易七鱼云客服的做法)。
欢迎分享,转载请注明来源:品搜搜测评网