文本相似度计算之余弦定理
2019-05-13 07:20:49来源:博客园 阅读 ()
前言
余弦相似度,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度。余弦相似度将向量根据坐标值,绘制到向量空间中。用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。余弦值越接近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%的相似度。
参考图例:
www.jianshu.com/p/f4606ae11…
公众号博文同步Github仓库,有兴趣的朋友可以帮忙给个Star哦,码字不易,感谢支持。
github.com/PeppaLittle…
推荐阅读
《如何优化代码中大量的if/else,switch/case?》
《如何提高使用Java反射的效率?》
《Java日志正确使用姿势》
关注「深夜里的程序猿」,分享最干的干货
原文链接:https://www.cnblogs.com/coding-night/p/10856473.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- Java实现圆柱体表面积和体积的计算 2020-06-08
- 计算机基础到底是哪些基础?为什么很重要! 2020-06-08
- 学习笔记之网络编程 2020-06-01
- Thymeleaf读取国际化文本时出现??xxxxxx_zh_CN??问题 2020-05-19
- 学习计算机基础必读的4本经典入门书籍,自学编程必备书单! 2020-05-15
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash