Java实现TFIDF算法
算法介绍
最近要做领域概念的提取,TFIDF作为一个很经典的算法可以作为其中的一步处理。
关于TFIDF算法的介绍可以参考这篇博客http://www.ruanyifeng.com/blog/2013/03/tf-idf.html。
计算公式比较简单,如下:
预处理
由于需要处理的候选词大约后3w+,并且语料文档数有1w+,直接挨个文本遍历的话很耗时,每个词处理时间都要一分钟以上。
为了缩短时间,首先进行分词,一个词输出为一行方便统计,分词工具选择的是HanLp。
然后,将一个领域的文档合并到一个文件中,并用“$$$”标识符分割,方便记录文档数。
下面是选择的领域语料(PATH目录下):
代码实现
- package edu.heu.lawsoutput;
- import java.io.BufferedReader;
- import java.io.BufferedWriter;
- import java.io.File;
- import java.io.FileReader;
- import java.io.FileWriter;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Set;
- /**
- * @ClassName: TfIdf
- * @Description: TODO
- * @author LJH
- * @date 2017年11月12日 下午3:55:15
- */
- public class TfIdf {
- static final String PATH = "E:\\corpus"; // 语料库路径
- public static void main(String[] args) throws Exception {
- String test = "离退休人员"; // 要计算的候选词
- computeTFIDF(PATH, test);
- }
- /**
- * @param @param path 语料路经
- * @param @param word 候选词
- * @param @throws Exception
- * @return void
- */
- static void computeTFIDF(String path, String word) throws Exception {
- File fileDir = new File(path);
- File[] files = fileDir.listFiles();
- // 每个领域出现候选词的文档数
- Map<String, Integer> containsKeyMap = new HashMap<>();
- // 每个领域的总文档数
- Map<String, Integer> totalDocMap = new HashMap<>();
- // TF = 候选词出现次数/总词数
- Map<String, Double> tfMap = new HashMap<>();
- // scan files
- for (File f : files) {
- // 候选词词频
- double termFrequency = 0;
- // 文本总词数
- double totalTerm = 0;
- // 包含候选词的文档数
- int containsKeyDoc = 0;
- // 词频文档计数
- int totalCount = 0;
- int fileCount = 0;
- // 标记文件中是否出现候选词
- boolean flag = false;
- FileReader fr = new FileReader(f);
- BufferedReader br = new BufferedReader(fr);
- String s = "";
- // 计算词频和总词数
- while ((s = br.readLine()) != null) {
- if (s.equals(word)) {
- termFrequency++;
- flag = true;
- }
- // 文件标识符
- if (s.equals("$$$")) {
- if (flag) {
- containsKeyDoc++;
- }
- fileCount++;
- flag = false;
- }
- totalCount++;
- }
- // 减去文件标识符的数量得到总词数
- totalTerm += totalCount - fileCount;
- br.close();
- // key都为领域的名字
- containsKeyMap.put(f.getName(), containsKeyDoc);
- totalDocMap.put(f.getName(), fileCount);
- tfMap.put(f.getName(), (double) termFrequency / totalTerm);
- System.out.println("----------" + f.getName() + "----------");
- System.out.println("该领域文档数:" + fileCount);
- System.out.println("候选词出现词数:" + termFrequency);
- System.out.println("总词数:" + totalTerm);
- System.out.println("出现候选词文档总数:" + containsKeyDoc);
- System.out.println();
- }
- //计算TF*IDF
- for (File f : files) {
- // 其他领域包含候选词文档数
- int otherContainsKeyDoc = 0;
- // 其他领域文档总数
- int otherTotalDoc = 0;
- double idf = 0;
- double tfidf = 0;
- System.out.println("~~~~~" + f.getName() + "~~~~~");
- Set<Map.Entry<String, Integer>> containsKeyset = containsKeyMap.entrySet();
- Set<Map.Entry<String, Integer>> totalDocset = totalDocMap.entrySet();
- Set<Map.Entry<String, Double>> tfSet = tfMap.entrySet();
- // 计算其他领域包含候选词文档数
- for (Map.Entry<String, Integer> entry : containsKeyset) {
- if (!entry.getKey().equals(f.getName())) {
- otherContainsKeyDoc += entry.getValue();
- }
- }
- // 计算其他领域文档总数
- for (Map.Entry<String, Integer> entry : totalDocset) {
- if (!entry.getKey().equals(f.getName())) {
- otherTotalDoc += entry.getValue();
- }
- }
- // 计算idf
- idf = log((float) otherTotalDoc / (otherContainsKeyDoc + 1), 2);
- // 计算tf*idf并输出
- for (Map.Entry<String, Double> entry : tfSet) {
- if (entry.getKey().equals(f.getName())) {
- tfidf = (double) entry.getValue() * idf;
- System.out.println("tfidf:" + tfidf);
- }
- }
- }
- }
- static float log(float value, float base) {
- return (float) (Math.log(value) / Math.log(base));
- }
- }
运行结果
测试词为“离退休人员”,中间结果如下:
最终结果:
结论
可以看到“离退休人员”在养老保险和社保领域,tfidf值比较高,可以作为判断是否为领域概念的一个依据。
当然TF-IDF算法虽然很经典,但还是有许多不足,不能单独依赖其结果做出判断。
很多论文提出了改进方法,本文只是实现了最基本的算法。
如果有其他思路和想法欢迎讨论。
转载请注明原文链接:http://www.cnblogs.com/justcooooode/p/7831157.html
Java实现TFIDF算法的更多相关文章
- Hanlp分词实例:Java实现TFIDF算法
算法介绍 最近要做领域概念的提取,TFIDF作为一个很经典的算法可以作为其中的一步处理. 关于TFIDF算法的介绍可以参考这篇博客http://www.ruanyifeng.com/blog/2013 ...
- 吴裕雄--天生自然HADOOP操作实验学习笔记:tf-idf算法
实验目的 通过实验了解tf-idf算法原理 通过实验了解mapreduce的更多组件 学会自定义分区,读写缓存文件 了解mapreduce程序的设计方法 实验原理 1.TF-IDF简介 TF-IDF( ...
- TF-IDF算法学习报告
TF-IDF是一种统计方法,这个算法在我们项目提取关键词的模块需要被用到,TF-IDF算法是用来估计 一个词汇对于一个文件集中一份文件的重要程度.从算法的定义中就可以看到,这个算法的有效实现是依靠 一 ...
- Java常用排序算法+程序员必须掌握的8大排序算法+二分法查找法
Java 常用排序算法/程序员必须掌握的 8大排序算法 本文由网络资料整理转载而来,如有问题,欢迎指正! 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排 ...
- TF-IDF算法
转自:http://www.cnblogs.com/eyeszjwang/articles/2330094.html TF-IDF(term frequency–inverse document fr ...
- Java字符串排列算法
Java字符串排列算法 题目:现有ABCDE 5个球 构成的排列组合 可重复抽取 最多取到16个 共有多少种组合方式? 比如:取1个球可以构成的组合有 A B C D E 共5种,取2个球可以构成的组 ...
- Java 常用排序算法/程序员必须掌握的 8大排序算法
Java 常用排序算法/程序员必须掌握的 8大排序算法 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排序(直接选择排序.堆排序) 4)归并排序 5)分配 ...
- TF-IDF算法扫盲2
TF-IDF算法是一种简单快捷的文档特征词抽取方法,通过统计文档中的词频来对文档进行主题分类.TF-IDF(term frequency–inverse document frequency)是一种统 ...
- 阮老师讲解TF-IDF算法
TF-IDF与余弦相似性的应用(一):自动提取关键词 作者: 阮一峰 日期: 2013年3月15日 这个标题看上去好像很复杂,其实我要谈的是一个很简单的问题. 有一篇很长的文章,我要用计算机提取它 ...
随机推荐
- python---time模块使用详解
python中的time模块提供一些方法用来进行关于时间的操作,time模块中有以下方法可供使用: time() --- 返回当前时间的时间戳. 调用:time.time(), 可用于计算程序运行的 ...
- mysql-5.7.17-winx64解压版本安装图解附带一些常见问题
第一步:下载mysql-5.7.17-winx64解压版本:http://dev.mysql.com/downloads/mysql/ 第二步:解压到安装目录,如:D:\MySql\mysql-5.7 ...
- Android UI 笔记
EditText中添加小图标 <TextView android:layout_width="wrap_content" android:layout_height=&quo ...
- NSString与NSMutableString的浅拷贝与深拷贝
浅拷贝:指针拷贝,指针与原指针地址相同,没有创建新的对象. 深拷贝:内容拷贝,创建了新的对象,指针地址与原对象的指针地址不同. NSString测试代码如下 打印结果如下(后面打印出的两个NSCFCo ...
- angualrJs清除定时器
angualrJs清除定时器爬坑之路: 今天发现一个奇怪问题,放在自定义指令里边的定时器竟然在页面跳转之后,在另一个页面这个循环定时器还在执行,这肯定是不行的,会影响系统的性能. 我在angular里 ...
- Jquery仿京东分类导航层简单实现
<script src="/js/jquery-1.11.1.min.js" type="text/javascript"></script& ...
- 线性布局(LinearLayout)
线性布局(LinearLayout) 备注 match_parent填充布局单元内尽可能多的空间 wrap_content完整显示控件内容 orientation有两个值,horizontal水平显示 ...
- dig 命令使用
1.简单查询 # dig www.guoxh.cn 2.按记录类型查询,默认为A记录 # dig www.guoxh.cn cname # dig www.guoxh.cn mx # dig www. ...
- C 其他一些
1.联合,语法 union{成员1;成员2;} 联合间的成员共享同一个空间,也就是说,成员1赋值如果没有被清除,会体现在成员2上 2.位字段,结合结构体瓜分完整的类型存储空间,如 struct{ ; ...
- appium测试代码nullpoint
今天写了个简单向上滑动,执行到向上滑动操作,报nullpoint异常,经过各种乱碰终于解决了,现记录一下过程,以备以后参考! 环境背景:java+testng+appium 在@Test下调用 dir ...