Java 代码实现

您所在的位置:网站首页 ik分词器源码 Java 代码实现

Java 代码实现

2023-05-13 00:20| 来源: 网络整理| 查看: 265

本文主要介绍如何通过 IK 分词器进行词频统计。

使用分词器对文章的词频进行统计,主要目的是实现如下图所示的词云功能,可以找到文章内的重点词汇。

后续也可以对词进行词性标注,实体识别以及对实体的情感分析等功能。

Java 代码实现——使用 IK 分词器进行词频统计_词云来自铭毅老哥对电影​​​《长津湖》的影评分析​​

词频统计服务具体模块如下:

数据输入:文本信息数据输出:词 - 词频(TF-IDF等) - 词性等内容使用的组件:分词器、语料库、词云展示组件等功能点:白名单,黑名单,同义词等

现存的中文分词器有 IK、HanLP、jieba 和 NLPIR 等几种,不同分词器各有特点,本文使用 IK 实现,因为 ES 一般使用 medcl 等大佬封装的 IK 分词器插件作为中文分词器。

由于 ES 的 IK 分词器插件深度结合了 ES,仅对文本分词使用不到 ES 的内容,所以文本采用申艳超大佬版本的 IK。

IK 地址:https://github.com/blueshen/ik-analyzer

1. IK 分词统计代码

IK 的代码相对比较简单,东西不多,将 String 拆分为词并统计代码如下:

单纯统计词频:/** * 全文本词频统计 * * @param content 文本内容 * @param useSmart 是否使用 smart * @return 词,词频 * @throws IOException */private static Map countTermFrequency(String content, Boolean useSmart) throws IOException { // 输出结果 Map Map frequencies = new HashMap(); if (StringUtils.isBlank(content)) { return frequencies; } DefaultConfig conf = new DefaultConfig(); conf.setUseSmart(useSmart); // 使用 IKSegmenter 初始化文本信息并加载词典 IKSegmenter ikSegmenter = new IKSegmenter(new StringReader(content), conf); Lexeme lexeme; while ((lexeme = ikSegmenter.next()) != null) { if (lexeme.getLexemeText().length() > 1) {// 过滤单字,也可以过滤其他内容,如数字和单纯符号等内容 final String term = lexeme.getLexemeText(); // Map 累加操作 frequencies.compute(term, (k, v) -> { if (v == null) { v = 1; } else { v += 1; } return v; }); } } return frequencies;}统计词频和文档频率:/** * 文本列表词频和词文档频率统计 * * @param docs 文档列表 * @param useSmart 是否使用只能分词 * @return 词频列表 词-[词频,文档频率] * @throws IOException */private static Map countTFDF(List docs, boolean useSmart) throws IOException { // 输出结果 Map Map frequencies = new HashMap(); for (String doc : docs) { if (StringUtils.isBlank(doc)) { continue; } DefaultConfig conf = new DefaultConfig(); conf.setUseSmart(useSmart); // 使用 IKSegmenter 初始化文本信息并加载词典 IKSegmenter ikSegmenter = new IKSegmenter(new StringReader(doc), conf); Lexeme lexeme; // 用于文档频率统计的 Set Set terms = new HashSet(); while ((lexeme = ikSegmenter.next()) != null) { if (lexeme.getLexemeText().length() > 1) { final String text = lexeme.getLexemeText(); // 进行词频统计 frequencies.compute(text, (k, v) -> { if (v == null) { v = new Integer[]{1, 0}; } else { v[0] += 1; } return v; }); terms.add(text); } } // 进行文档频率统计:无需初始化 Map,统计词频后 Map 里面必有该词记录 for (String term : terms) { frequencies.get(term)[1] += 1; } } return frequencies;}2. 获取词云 TopN 个词

获取 TopN 个词用于词云展示有多种排序方式,可以直接根据词频、文档频率或者 TF-IDF 等算法进行排序,本文仅根据词频求取 TopN。M 个数字获取 TopN 有以下算法:

M 小 N 小:快速选择算法M 大 N 小:小顶堆M 大 N 大:归并排序

本文采用小顶堆方式实现,对应JAVA中的优先队列数据结构 PriorityQueue:

/** * 按出现次数,从高到低排序取 TopN * * @param data 词和排序数字对应的 Map * @param TopN 词云展示的 TopN * @return 前 N 个词和排序值 */private static List order(Map data, int topN) { PriorityQueue priorityQueue = new PriorityQueue(data.size(), new Comparator() { @Override public int compare(Map.Entry o1, Map.Entry o2) { return o2.getValue().compareTo(o1.getValue()); } }); for (Map.Entry entry : data.entrySet()) { priorityQueue.add(entry); } //TODO 当前100词频一致时(概率极低)的处理办法,if( list(0).value == list(99).value ){xxx} List list = new ArrayList(); //统计结果队列size和topN值取较小值列表 int size = priorityQueue.size() = '0' && input = 'a' && input = 'A' && input


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3