算法介绍

最近要做领域概念的提取,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  没课割绿地 的博客

Hanlp分词实例:Java实现TFIDF算法的更多相关文章

  1. Java实现TFIDF算法

    算法介绍 最近要做领域概念的提取,TFIDF作为一个很经典的算法可以作为其中的一步处理. 关于TFIDF算法的介绍可以参考这篇博客http://www.ruanyifeng.com/blog/2013 ...

  2. NLP自然语言处理中的hanlp分词实例

    本篇分享的依然是关于hanlp的分词使用,文章内容分享自 gladosAI 的博客,本篇文章中提出了一个问题,hanlp分词影响了实验判断结果.为何会如此,不妨一起学习一下 gladosAI 的这篇文 ...

  3. Java-Runoob-高级教程-实例-方法:03. Java 实例 – 汉诺塔算法-un

    ylbtech-Java-Runoob-高级教程-实例-方法:03. Java 实例 – 汉诺塔算法 1.返回顶部 1. Java 实例 - 汉诺塔算法  Java 实例 汉诺塔(又称河内塔)问题是源 ...

  4. 基于结构化平均感知机的分词器Java实现

    基于结构化平均感知机的分词器Java实现 作者:hankcs 最近高产似母猪,写了个基于AP的中文分词器,在Bakeoff-05的MSR语料上F值有96.11%.最重要的是,只训练了5个迭代:包含语料 ...

  5. 吴裕雄--天生自然HADOOP操作实验学习笔记:tf-idf算法

    实验目的 通过实验了解tf-idf算法原理 通过实验了解mapreduce的更多组件 学会自定义分区,读写缓存文件 了解mapreduce程序的设计方法 实验原理 1.TF-IDF简介 TF-IDF( ...

  6. HanLP分词命名实体提取详解

    HanLP分词命名实体提取详解   分享一篇大神的关于hanlp分词命名实体提取的经验文章,文章中分享的内容略有一段时间(使用的hanlp版本比较老),最新一版的hanlp已经出来了,也可以去看看新版 ...

  7. HanLP分词研究

    这篇文章主要是记录HanLP标准分词算法整个实现流程. HanLP的核心词典训练自人民日报2014语料,语料不是完美的,总会存在一些错误.这些错误可能会导致分词出现奇怪的结果,这时请打开调试模式排查问 ...

  8. hanlp分词工具应用案例:商品图自动推荐功能的应用

    本篇分享一个hanlp分词工具应用的案例,简单来说就是做一图库,让商家轻松方便的配置商品的图片,最好是可以一键完成配置的. 先看一下效果图吧: 商品单个推荐效果:匹配度高的放在最前面 这个想法很好,那 ...

  9. Java常用排序算法+程序员必须掌握的8大排序算法+二分法查找法

    Java 常用排序算法/程序员必须掌握的 8大排序算法 本文由网络资料整理转载而来,如有问题,欢迎指正! 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排 ...

随机推荐

  1. Vue项目初始化

    1. 生成项目模板 vue init <模板名> 本地文件夹名称2. 进入到生成目录里面 cd xxx npm install3. npm run dev vue项目模板介绍: simpl ...

  2. css引入外部字体使网站字体更美观

    @font-face{font-family: myFont;src:url("../font/timesi.ttf");src:url("../font/timesbi ...

  3. :after和:before伪元素的解释

    :after  是清除浮动  让其高度和内容高度相同 :before   是防止上边塌陷 关注微信小程序

  4. LeetCode--1、26、27、35、53 Array(Easy)

      1. Two Sum Given an array of integers, return indices of the two numbers such that they add up to ...

  5. 解析XML技术

    转载:http://developer.51cto.com/art/200903/117512.htm XML现在已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交 ...

  6. Java 面试题 —— java 源码

    1. 静态工厂方法 静态工厂方法不必在每次调用它们的时候都创建一个新的对象: Boolean.valueOf(boolean): public final class Boolean { public ...

  7. php 怎样将有范围的ip转化为整型范围

    php中将IP转换成整型的函数ip2long()容易出现问题,在IP比较大的情况下,会变成负数.如下: <?php $ip = "192.168.1.2"; $ip_n = ...

  8. MySQL(1) 基本操作(MySQL的启动,表的创建,查询表的结构和表的字段的修改)

    MySQL启动流程 1 启动服务器 2 用户名登录到MySQL数据库中 3  查看有哪些数据库 4 使用其中的数据库 5 查看该数据库中已有哪些表,没有就新建 mysql> CREATE TAB ...

  9. tmux允许鼠标滚动

    /********************************************************************** * tmux允许鼠标滚动 * 说明: * 默认tmux貌 ...

  10. Shell #*/ 和 %/*

    #!/bin/bash i="this/is/a/path.config" name=${i#*/} path=${i%/*} echo $name echo $path is/a ...