穷人的语义处理工具箱之中的一个:语义版Jaccard
author: 张俊林
|为什么我们是ML界的穷人
假设对工业界里的机器学习(ML)从业者进行阶级划分的话,划线标准不是你用的算法的学名听起来多酷炫,不管你手里抡着的是最潮的深度高达1000层的深度学习核炸弹。还是听起来有点掉渣的大刀长矛朴素贝叶斯。假设没有大量数据,尤其是能跑监督学习算法的带标签训练数据。你就是ML界标准的底层渣男渣女或者渣娘炮。再加上计算资源,假设贵公司有上千台GPUserver集群可供阁下驱使,外加十几火车皮的训练数据,那你就可能成为ML界的新贵、大数据处理领域的马云。
可是,理想丰满现实骨感,大多数中小公司里ML界贫农们的日常生活写照是这样的:前一天晚上看到某篇论文。学到一个让人兴味盎然的新ML姿势,第二天一大早横刀立刻豪气干云地冲到公司。热血沸腾血往上涌准备撸起袖子大干一场,可是一转念掰着指头数数,看看自己手上超只是手指数量的数据资源。顿生有心杀贼。无力回天的挫败感。这画面的漂亮程度与“看不进书的时候照照镜子,加不了班的时候数数银行卡剩余金额”有异曲同工之妙。
可是穷人也应该有一颗追求美和好好活下去的强大心脏。既然没有训练数据。那我们就好好玩无监督学习,老老实实地去拟合你想要的公式,俗话说得好:无产阶级打破的仅仅有枷锁,而得到的是整个世界。而本文就是带给ML界底层农民工的礼物和福音。
好,安利部分到此为止,以下是正文。
|原生态Jaccard
原生态Jaccard作为类似性计算函数,不管是计算思想还是project实现都简单得令人发指。假设有两个集合:集合A和集合B,每一个集合内各自包括若干元素,那么Jaccard计算两个集合的类似性就是用两个集合元素的交集作为分子,两个集合元素的并集作为分母。除一下就完事。由于交集代表了两个集合同样部分的子集合。并集代表了两个集合加起来总共同拥有多少个元素,用同样部分占总元素数比例来代表集合类似性,两者重叠部分越多则两个集合越类似。
在文本处理领域。Jaccard也是一个比較经常使用的计算句子类似性的工具。
详细使用时,往往是把两个要计算类似程度的句子改造成n-gram片段组成的两个集合。然后通过计算两个集合同样的n-gram片段个数作为集合交集,两个集合合并后的n-gram片段个数作为集合并集。这样就能得出两个句子的类似性得分。比方以下两个句子:
句子A:苹果电脑的价格
句子B:苹果ipad的价格
两个句子转换为2-gram后,形成例如以下集合:
SetA={苹果,果电,电脑。脑的,的价,价格}
SetB={苹果。果ipad,ipad的。的价。价格}
两个集合求交集得出同样语言片段个数为:3.(即为:苹果,的价,价格)
两个集合求并集得出分母大小为:8
所以这两个句子的类似度为:3/8=0.375
在Jaccard的世界里,一切都是这么简单,智商80以上人群看完之后都会会心一笑,此刻,他们的眼里闪耀着智慧的光芒。
原生态Jaccard得分由于过于简单,在计算类似性仅仅用Jaccard的情形比較少。可是往往会被用来作为机器学习系统的一个比較重要的特征因子,非常多NLP领域的评測方法也參考这个思想。比方机器翻译评測方法BLUE,文本摘要评測方法ROUGE-N等本质上就是类似于Jaccard的思想,事实上语义Jaccard对传统Jaccard的改进思路也能够试着用来改造BLUE或者ROUGE-N评价标准,当然假设实验证明没效果就当我没说这句话。
|语义版Jaccard的诞生
公元2015年的第一场雪,来得比往年早了一些。镜头摇近,一位面容憔悴衣衫落魄的中年男子(注1:不是杜甫。是本文作者)飘入画面,他深深地吸入一口帝都醇厚甘冽的雾霾,由于吸得生猛,仅仅见他虎躯一震,止不住干咳两声。背手望着空中漫天纷扬飞舞的细雪,诗兴大发,正要蹦出:“月是故乡明,霾是故都纯,黄狗身上白,白狗身上肿”这首情景交融感人至深的千古咏雪名句。突然间。一个诡异的念头飘入他的脑中:经典Jaccard仅仅是衡量两个句子字面上的文本匹配程度。假设用语义类似性替代字面类似性来改造一下Jaccard,那么在处理文本的时候是否会更有效些呢?
这是一个好问题。
非常明显,引入语义版Jaccard后能够对传统使用字面版本号匹配的Jaccard进行改进,由于此时是在文本的语义空间进行的匹配,而非单独字面匹配,应该会引入很多其它信息量。比方:
句子A:请问苹果电脑的价格
句子B:问下联想笔记本多少钱
假设用3-gram构造句子集合片段的话。非常easy看出来字面匹配版Jaccard算出的类似性为0,由于两者没有不论什么字面上匹配的三元组片段。
可是非常明显地,我们能够看出以下的单词之间语义类似度是非常高的:
请问vs问下
苹果vs联想
电脑vs笔记本
价格vs多少钱
那么我们如今面临的问题是:是否能对传统仅仅进行字面匹配的Jaccard进行改造,使得两个句子能够进行语义级别的匹配计算?即能够将“电脑”/“笔记本”这样的字面不匹配可是语义匹配的情况考虑进去。这是触发那位中年男子头脑中语义版Jaccard的最初想法。
|语义版Jaccard
经过一番推敲试错调整。终于定稿的语义版Jaccard详细计算公式例如以下:
我知道,这个公式看上去有点丑陋。但请耐心让我把话说完。
上述公式中,分子部分代表两个句子语言片段组成集合的语义交集:即语义类似性部分,而分母代表两个句子语言片段组成集合的语义并集,又可分为两部分:第一个部分和分子一样。代表语义交集,而第二个部分代表这两个集合的语义差异程度,两者之和形成集合并集。
1.语义类似性部分(分子)怎样计算
为了便于绘图与说明,我们拿以下短语为样例来说明语义版Jaccard公式的分子是怎样计算出来的。
真实应用场景中句子长度能够不做这样的长度限制。
SentenceA: 电脑多少钱
SentenceB:计算机的价格
第一步: 把SentenceA分割成3-gram表达形式。于是SentenceA变成例如以下形式
SetA={电脑多,脑多少,多少钱}
第二步:把SentenceB分割成3-gram表达形式。于是SentenceB变成例如以下形式
SetB={计算机,算机价,机价格}
第三步:构造类似性矩阵:以句子长度比較短的句子集合元素作为矩阵纵坐标,较长的句子集合元素作为横坐标,改造为例如以下矩阵:
第四步:用横坐标和纵坐标相应的语言片段的语义类似性填充矩阵元素值。
首先能够用Word2Vec训练出每一个汉字的Word Embedding,也就是其低维向量表示,一定程度上代表其包括的语义信息。那么3-gram包括了三个汉字,这3-gram的语义向量Word Embedding该怎么表示?能够简单粗暴地把其三个汉字的Word Embedding相应维度上的值累加求和就可以。
这样两个3-gram片段相应的Word Embedding都有了,剩下的就简单了。它们两个的语义类似性直接用Cosine计算两个Word Embedding在语义空间的向量夹角就成。一般语义越类似。Cosine得分越大。
填充好的矩阵形式例如以下:
第五步:填好类似性矩阵值是基础工作,做完之后,让我们正式開始计算语义版Jaccard公式的分子部分。
首先,先拍脑袋选出一个阈值a=0.6。意思是在计算语义类似性的时候,假设语言片段类似性高于阈值,我们觉得两个语言片段语义匹配,这个阈值能够用来控制计算结束过程。
算法描写叙述例如以下。
算法:语义Jaccard类似性部分计算;
输入:语义类似性矩阵S,阈值a;
输出:语义Jaccard公式分子部分分值Total
步骤:
循环例如以下步骤,直到算法退出:
Step 1.找到类似性矩阵S中的当前全部元素中的最高值;
Step 2.假设这个最高值高于阈值a,则累加到Total中。转步骤3。
假设这个最高值低于阈值。则分子部分计算结束。输出Total值。
Step 3.把当前矩阵中的最高值相应矩阵横坐标和纵坐标的行及列中全部元素值置为0,其含义是这两个片段不再參与后面的计算了,然后返回Step 1步骤继续循环;
在我们上面给出的样例中。假设遵循上述算法流程。则如是循环:
1. 分子总分Total=0;我们假设阈值a取0.8;
2.首先找到矩阵中的最高值:坐标[1,1]相应的0.99。其代表片段“电脑多”和“计算机”的片段语义类似性。发现其大于阈值0.8,那么累积分子得分,更新Total值:Total=0.99;
3.将矩阵中第一行和第一列全部元素类似性置为0,则当前形成下图:
4.然后在矩阵剩下的元素里面找到最高值:坐标[3,3]相应的0.98,其代表片段“多少钱”和“的价格”的片段语义类似性。发现其值大于阈值0.8,那么累积分子得分。更新Total值:
Total=0.99+0.98=1.97
5.将矩阵中第三行和第三列全部元素类似性都置为0,则当前形成下图:
6.发现坐标[2,2]相应的当前最高值小于阈值a,则计算过程结束。输出分子值Total=1.97。
此时两个句子各自剩余1个语言片段没有进行匹配。即:“脑多少”和“算计价”,能够将这两个片段看做两个句子语义不同的部分,用来计算分母。
2.分母的计算
语义版Jaccard公式的分母分为两部分:第一部分事实上就是分子,代表两个语言片段集合语义类似的部分;第二部分从含义上代表两个语言片段集合语义不同的部分。而这两者之和代表两个集合的语义并集。
假设经过分子计算步骤后,我们已经把參与分子部分计算的语言片段陆续都从SetA和SetB中删除掉,那么两个集合SetA和SetB可能都会剩余部分语言片段没有进行匹配,则分母部分的m定义为:
其含义是两个集合中没有达到语义匹配标准(由阈值a控制)的总片段个数或者两者中取最大值。
Xdif代表SetA中没有參与分子计算的全部语言片段;Ydif代表SetB中没有參与分子计算的全部语言片段。
而Cosine(Xdif, Ydif)的意思是两者的语义类似性,所以1-Cosine(Xdif, Ydif)代表两者的语义差异大小。两者语义差异越大则两个句子整个语义版Jaccard类似性分数会被拉低。而m和1-Cosine(Xdif, Ydif)相乘能够这么理解其含义:两个集合有m个片段语义不匹配。而每一个不匹配片段的不匹配程度是1-Cosine(Xdif, Ydif),所以能够将其理解为不匹配片段的权重。而语义版Jaccard分子部分也能够理解为语义匹配片段与其权重乘积之和。而其权重则为两个语言片段的语义Cosine类似性。
也就是说,这个语义版Jaccard公式的本质是:把两个集合依据阈值a拆分为两个子集合:语义匹配片段子集合/语义不匹配片段子集合。分子部分是语义匹配片段及其权重乘积之和。而分母部分是两个集合的并集。即是分子部分代表的两个集合语义同样部分和由语义不匹配片段子集合计算出的两者语义差异部分。
我们接着把上面没有算完的语义Jaccard计算样例算完,在分子计算部分我们已经算出两者的语义类似性Total=1.97。此时能够算分母了:首先,由于两个句子仅仅剩下“脑多少”和“算计价”两个语义不匹配的片段,所以能够得出m=1,而Cosine(Xdif, Ydif)=0.45,所以1-Cosine(Xdif, Ydif)=0.55,于是m*(1-Cosine(Xdif, Ydif))=0.55,得出分母值为:1.97+0.55=2.52,由于分子部分是1.97,于是这两个句子的语义版Jaccard终于得分为:
SemJac(“电脑多少钱”,” 计算机的价格”)=1.97/2.52=0.78
而相应的原生态Jaccard计算出的类似性分值为0,由此可见,语义版Jaccard确实是能够改善经典Jaccard仅仅做字面匹配的缺点,体现出句子深层次的语义类似性的。
|阈值參数调节方法
假设细致观察,你会发现语义版Jaccard公式上方游荡着一个面目狰狞的幽灵,一个潜在的不安定因素,就是那个阈值a。由于它鬼魅般的存在,使得我们面临一个尴尬的选择,那就是这个阈值应该取多少是合理的。
虽说我们是ML界的无产阶级。从拥有的训练数据数量角度来说属于一穷二白三没辙。可是就算是解放前万恶的旧社会,过春节的时候杨白劳也要想办法给亲闺女扯个红头绳不是。
作为ML界的民工。我们也能够自力更生。自己做少量比方几百条训练数据,用这些极少量的训练数据来过个好年。
能够这么着来多快好省地调整出合理的阈值參数:做出一批语义同样的句子对作为正例。然后再做一批语义重叠可是又不同的句子对作为负例。然后不断调整阈值a的取值,优化目标是看哪个阈值能够使得语义Jaccard公式计算出正例的类似度得分总体偏高往上移,而负例的类似度得分总体偏低往下走。
这有点类似于机器学习里面通过验证集调整超參数的做法。只是对训练数据数量要求会小得多。
我们从自己做的整个训练集合中抽取子集合,选择大约400对语义同样的句子对作为正例集合,选择大约400对语义相关可是不同的句子对作为负例。然后推断使用不同阈值语义版Jaccard对这些句子对的分值区间分布情况,我们知道不管是原生态Jaccard还是语义版Jaccard,其分值区间都落在[0,1]之间。我们把分值区间再细分为10个子区间:
[0,0.1],[0.1,0.2],[0.2,0.3]……[0.9,1.0] (在兴许图示中。纵轴标号为10的为[0,0.1]区间,标号为9的为[0.1,0.2]区间,以此类推)
这样就能够画出不同阈值下正负例得分在10个区间的分布情况,而能够最好地把正负例区分开的阈值就是好阈值。以下各自是阈值a=0.5和a=0.9时的分值分布情况:
语义版Jaccard正负例分值区间区分度(阈值a=0.5)
语义版Jaccard正负例分值区间区分图(阈值a=0.9)
从上面两组不同阈值的实验结果能够看出,阈值a=0.9对正负例的区分情况要明显优于a=0.5的情况。通过设置不同的阈值进行实验,我们得出的最优阈值就是0.9,在这个阈值下对正负例句子对的语义区分程度最强。
通过上述方式。我们就能够仅仅利用少数训练数据来获得超參数a的合理取值范围,这就是我们ML界农民工们喜闻乐见的场景。
|语义版Jaccard vs原生态Jaccard实验效果对照
为了验证语义版Jaccard相对原生态Jaccard在句子类似性推断任务上的有效性,我们做了实验对照。
实验方法例如以下:
从整个训练集合中抽取子集合,选择大约400对语义同样的句子对作为正例集合,选择大约400对语义相关可是不同的句子对作为负例。然后推断使用原生态Jaccard及语义版Jaccard对这些句子对的分值区间分布情况。
由于原生态Jaccard没有可调參数,所以仅仅会得出一组分值。而语义版Jaccard我们依照上节介绍的阈值调优方法选择最优參数阈值a=0.9,得出的正负例得分分布情况如以下两图所看到的:
经典Jaccard正负例分值区间区分图
从这张图能够看出,原生态Jaccard公式对于正负例区分度非常差,大多数正例和负例得分都落在了[0.0.1]之间,这是由于其仅仅对句子进行字面级别的类似推断导致的。
语义版Jaccard正负例分值区间区分图(a=0.9)
从上面这张图能够看出。语义版Jaccard在进行阈值调优后。能够非常明显地把正例和负例语义类似性得分在[0,1]分值区间内散落区分开。正例大多数分值落在[0.4,1.0]区间,负例大多数分值落在[0,0.4]以内,。在这个数据集合下。当阈值a取0.9时,假设把语义Jaccard计算类似性阈值设定为0.4。即给定两个句子<A,B>,利用语义版Jaccard计算公式对其类似性打分,假设得分高于0.4即推断为语义同样。得分低于0.4推断为语义不同。那么其将获得较高的推断准确率。而原生版Jaccard公式由于大多数正例和负例得分都落在[0,0.1]区间。所以非常难选择推断标准。
当然对于非常多应用来说,仅仅须要知道0.9这个阈值就可以。不须要确定0.4这个区分标准。
由上述实验结果可知。语义版Jaccard公式能够表达句子深层语义的类似性。并且能够通过少量训练数据获取最具区分度的阈值,所以相信将其作为一个新的计算语义类似性工具箱的工具,会对非常多机器学习应用有直接的帮助作用。理论上凡是使用经典Jaccard的计算场景都能够引入语义版Jaccard计算公式。
致谢:感谢畅捷通公司智能平台桑海岩、薛会萍、沈磊、黄通文等同事对于计算实现或训练语料收集方面的工作。
当然,考虑到本文的行文风格,或许你们宁愿没有这段指名道姓的致谢。
扫一扫关注微信号:“布洛卡区” ,深度学习在自然语言处理等智能应用的技术研讨与科普公众号。
穷人的语义处理工具箱之中的一个:语义版Jaccard的更多相关文章
- 【浅墨Unity3D Shader编程】之中的一个 夏威夷篇:游戏场景的创建 & 第一个Shader的书写
本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...
- 使用Jquery+EasyUI进行框架项目开发案例解说之中的一个---员工管理源代码分享
使用Jquery+EasyUI 进行框架项目开发案例解说之中的一个 员工管理源代码分享 在開始解说之前,我们先来看一下什么是Jquery EasyUI?jQuery EasyUI是一组基于jQuery ...
- 包管理器Bower使用手冊之中的一个
包管理器Bower使用手冊之中的一个 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.Bower介绍 Bower是一个适合Web应用的包管理器,它擅长 ...
- WP系统推广难的原因之中的一个之我见
个人也觉得如今的Android市场几家独大,竞争太激烈.利润空间挤压太严重,有实力的厂家不如尝试剑走偏锋,在其它大佬都还没跟进的时候,把市场投向WP.先入为主,不失为良策! 话说Microsoft不开 ...
- zookeeper+kafka集群安装之中的一个
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/cheungmine/article/details/26678877 zookeeper+kafka ...
- 抄袭证据之中的一个CMM与CMMI的名称
以下文字来自我即将完毕的文章,谢博士说她没有抄袭,可是文中实在是有太多的漏洞了. 6.2.7 P120页中: "实际上终于所谓的统一方法论就是标准,尽管作标准并非目的.但标准是必须有的.能够 ...
- 在存放源程序的文件夹中建立一个子文件夹 myPackage。例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage)。在 myPackage 包中创建一个YMD类,该类具有计算今年的年份、可以输出一个带有年月日的字符串的功能。设计程序SY31.java,给定某人姓名和出生日期,计算该人年龄,并输出该人姓名、年龄、出生日期。程序使用YM
题目补充: 在存放源程序的文件夹中建立一个子文件夹 myPackage.例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage).在 m ...
- netty深入学习之中的一个: 入门篇
netty深入学习之中的一个: 入门篇 本文代码下载: http://download.csdn.net/detail/cheungmine/8497549 1)Netty是什么 Netty是Java ...
- 【IPC进程间通讯之中的一个】邮槽MailSlot
IPC进程间通信+邮槽MailSlot IPC(Inter-Process Communication.进程间通信). 现代计算机採用虚拟内存机制,为进程提 ...
随机推荐
- [Android开发教程]Android官网developer training中文版教程 - 1.1.1 创建一个Android项目
本系列持续更新中.转载请注明来源. 前言:近期打算系统学习一下Android开发,发现Android官网上的developer training也是个非常好的学习资料,于是想到一边学习一边写一个中文版 ...
- The application’s PagerAdapter changed the adapter’s contents without calling PagerAdapter#notifyDa
错误原因是在于修改了PageAdapter,却没有调用 PageAdapter的nodifyDataSetChanged方法.注意刷新数据 需要在主线程. 今天在做项目时出现了这个问题,一直报没有调用 ...
- 深入理解Apache Flink核心技术
深入理解Apache Flink核心技术 2016年02月18日 17:04:03 阅读数:1936 标签: Apache-Flink数据流程序员JVM 版权声明:本文为博主原创文章,未经博主允许 ...
- nose的测试报告
有时候我们要让报告整洁美观点,以html展示测试结果,我们可以借助pip install nosehtmloutput插件输出html格式报告 from nose.plugins.plugintest ...
- RecyclerView.ItemDecoration 间隔线
内容已更新到:https://www.cnblogs.com/baiqiantao/p/19762fb101659e8f4c1cea53e7acb446.html 目录一个通用分割线ItemDecor ...
- Webview 支持文件上传
默认情况下情况下,在一个带有input tpye=file标签的Html页面,使用Android的WebView是不能够支持上传文件的(在iOS和微信上完全正常工作).而这个,也是在我们的前端工程师告 ...
- 转:Android应用开发性能优化完全分析
转自:http://blog.csdn.net/yanbober/article/details/48394201 1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜 ...
- C经典之9-system,if,do,while---ShinePans
#include <stdio.h> #include <conio.h> #include <stdlib.h> //system(); 这个指令须要用到此头文件 ...
- 关于CPU的运行队列与系统负载
在linux操作系统中,我们一般查看系统的cpu负载情况常用的命令可以是uptime,top,还有vmstat等这些个都是可以有的.每个工具所提供的信息各不相同, 我这里要讨论的仅说cpu部分.使用u ...
- mysql安装错误总结
1.若在启动mysql服务时出现如下错误,可查看错误日志找出错误原因. Error:Starting MySQL.The server quit without updating PID file ( ...