文本相似度计算之余弦定理
前言
余弦相似度,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度。余弦相似度将向量根据坐标值,绘制到向量空间中。用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似,反之越接近0就表示两个向量相似度越低,这就叫"余弦相似性"。
正文
重温余弦定理
先简单的重温一下高中数学知识,余弦定理
这个公式大家不知道还有没有印象呢?没有的话我们看下下面的图
此时a=(xa,ya)
,b=(xb,0)
,那么怎么计算各边长的长度呢?
此时将各边长代入上图的公式当中,最后可以得出最终的计算公式
文本相似度计算步骤
那么在我们的文本相似度计算中,都有哪些步骤呢?
- 分词,比如有两行文本,第一句:
你好,我是小王,我是个程序员”
,将会分割成你好/我/是/小王/我/是/个/程序员
。第二句:你好,我是设计师
,将会分成你好/我/是/设计师
- 统计词频,其实就是统计所有语句中的每个词在当前句子出现的次数,第一句:
你好1,我2,是2,小王1,个1,程序员1,设计师0
,第二句你好1,我1,是1,小王0,个0,程序员0,设计师1
- 组合词频向量,第一句
(1,2,2,1,1,1,0)
,第二句(1,1,1,0,0,0,1)
。 - 将数据代入上面的公式计算相似度
maven 引入ikanalyzer依赖
这里使用ikanalyzer来实现一个简单的分词功能
<dependency> <groupId>com.janeluo</groupId> <artifactId>ikanalyzer</artifactId> <version>2012_u6</version> </dependency>
IKUtils分词工具类,代码比简单,唯一一个方法返回的是语句分词的List对象
/** * 分词相关工具类 * @author wangzh */ public class IKUtils { /** * 以List的格式返回文本分词的结果 * @param text * @return */ public static List<String> divideText(String text){ if(null == text || "".equals(text.trim())){ return null; } List<String> resultList = new ArrayList<>(); StringReader re = new StringReader(text); IKSegmenter ik = new IKSegmenter(re, true); Lexeme lex = null; try { while ((lex = ik.next()) != null) { resultList.add(lex.getLexemeText()); } } catch (Exception e) { //TODO } return resultList; } }
下面是主要的代码逻辑,相关步骤已注释在代码里面
public class Analysis { public static void main(String[] args) { Map<String,int[]> resultMap = new HashMap<>(); //测试文本 String text1 = "你好,我是小王,我是个程序员"; String text2 = "你好,我是设计师"; //统计 statistics(resultMap, IKUtils.divideText(text1),1); statistics(resultMap, IKUtils.divideText(text2),0); //计算类 final Calculation calculation = new Calculation(); resultMap.forEach((k,v)->{ int[] arr = resultMap.get(k); calculation.setNumerator(calculation.getNumerator() + arr[0] * arr[1]); calculation.setElementA(calculation.getElementA() + arr[0] * arr[0]); calculation.setElementB(calculation.getElementB() + arr[1] * arr[1]); }); System.out.println("文本相似度:" + calculation.result()); } /** * 组合词频向量 * @param words * @param direction * @return */ private static void statistics(Map<String,int[]> map,List<String> words ,int direction){ if(null == words || words.size() == 0){ return ; } int[] in = null; boolean flag = direction(direction); for (String word : words){ int[] wordD = map.get(word); if(null == wordD){ if(flag){ in = new int[]{1,0}; }else { in = new int[]{0,1}; } map.put(word,in); }else{ if(flag){ wordD[0]++; }else{ wordD[1]++; } } } } //判断不同句子 private static boolean direction(int direction){ return direction == 1?true:false; } }
用于计算余弦相似度的类
public class Calculation{ private double elementA; private double elementB; private double numerator; public double result(){ return numerator / Math.sqrt(elementA * elementB); } //省略get/set }
输出结果:
文本相似度:0.7216878364870323
从结果可以看出这两句话大致上还是比较相似的。用通俗一点的话来说就是有72%的相似度。
参考图例:
https://www.jianshu.com/p/f4606ae118b3
公众号博文同步Github仓库,有兴趣的朋友可以帮忙给个Star哦,码字不易,感谢支持。
https://github.com/PeppaLittlePig/blog-wechat
推荐阅读
《如何提高使用Java反射的效率?》
《Java日志正确使用姿势》
《论JVM爆炸的几种姿势及自救方法》
有收获的话,就点个赞吧
关注「深夜里的程序猿」,分享最干的干货

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
以太坊智能合约之如何执行智能合约?
区块链技术在顶级技术中占据主导地位的主要原因在于其去中心化。虽然区块链的主要目的是在没有中心的情况下维护交易记录,但为了实现自动化,智能合约被引入。那么在写完智能合约之后呢?在本文的这个以太坊智能合约教程中,我们将了解如何使用Truffle Ethereum和以太坊专用网络来执行智能合约。 我们将在以太坊智能合约教程中查看以下主题: 使用案例:保险流程中的智能合约 智能合约的好处 安装先决条件 配置Genesis Block 运行以太坊专用网络 创建以太坊帐户 创建以太坊智能合约 执行以太坊智能合约 使用案例:保险流程中的智能合约 区块链遵循的是“没有中央权力机构”,这就是智能合约引入的原因。但你有没有想过如何使用智能合约?那么,在以太坊智能合约的这一部分中,我将解释保险流程中智能合约的使用案例。 让我们考虑一个航班延误保险的例子。假设你想要从出发地A到目的地C进行飞行,但你没有直接飞行。那么,你决定通过B来转机。现在,你的路线将从A到B,然后从B到C,其中B是机场,你将更改航班。不幸的是,从A到B以及从B到C的航班之间没有太大的时间差距。所以,如果有任何问题,一旦从A到B的航班延误,...
- 下一篇
处理网络超时问题的最佳实践
对于云上的用户来说,业务日志里面报超时问题处理起来往往比价棘手,因为1) 问题点可能在云基础设施层,也有可能在业务软件层,需要排查的范围非常广;2) 这类问题往往是不可复现问题,抓到现场比较难。在本文里就分析下如何来分辨和排查这类问题的根本原因。 业务超时 != 网络丢包 由于业务的形态不同,软件实现语言和框架的不同,业务日志中打印出的信息可能是各不相同,比如如下关键字: "SocketTimeOut", "Read timed out", "Request timeout" 等 从形式看都属于网络超时这一类,但是需要明确一个概念:这类问题是发生的原因是请求超过了设定的timeout时间,这个设置有可能来自客户端,服务器端或者网络中间节点,这是直接原因。网络丢包可能会导致超时,但是并不是充分条件。总结业务超时和网络丢包的关系如下: 网络丢包可能造成业务超时,但是业务超时的原因不一定是丢包。 明确了这个因果关系后,我们再来看怎么分析业务超时。如果武断地将业务超时等同于网络抖动丢包,那这个排查分析过程就完全错过了业务软件层本身的原因,很容易进入困局。 本文会从云基础设施层和业务软件层对业务...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8
- Mario游戏-低调大师作品
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题