Java使用Nagao算法实现新词发现、热门词的挖掘攻略
本文将介绍如何使用Java实现Nagao算法对文本进行分析,从而实现新词发现和热门词挖掘。攻略分为以下四步:
- 数据预处理
在使用Nagao算法对文本进行分析前,需要对词语进行切分。Java中常用的中文分词工具有jieba、HanLP等,本文以使用HanLP为例:
import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.seg.Segment;
import com.hankcs.hanlp.seg.common.Term;
String text = "小明是一位机器学习的工程师";
Segment segment = HanLP.newSegment().enableNameRecognize(true);
List<Term> termList = segment.seg(text);
- 构建词语共现矩阵
将文本中分词后的每一个词语和它相邻的词语组合起来,形成词语共现对,并构建一个词语共现矩阵。在Java中可以使用Map< Pair
Map<Pair<String, String>, Integer> pairCount = new HashMap<>();
for (int i = 0; i < termList.size() - 1; i++) {
String word1 = termList.get(i).word;
String word2 = termList.get(i + 1).word;
Pair<String, String> pair = new Pair<>(word1, word2);
int count = pairCount.getOrDefault(pair, 0);
pairCount.put(pair, count + 1);
}
- 计算词语权重
基于词语共现矩阵,计算每一个词语的权重。使用Nagao算法来计算权重:
public Map<String, Double> calculateWordWeight(Map<Pair<String, String>, Integer> pairCount) {
Map<String, Integer> wordCount = new HashMap<>();
for (Pair<String, String> pair : pairCount.keySet()) {
String word1 = pair.getKey();
String word2 = pair.getValue();
int count = pairCount.get(pair);
wordCount.put(word1, wordCount.getOrDefault(word1, 0) + count);
wordCount.put(word2, wordCount.getOrDefault(word2, 0) + count);
}
Map<String, Double> wordWeight = new HashMap<>();
for (Pair<String, String> pair : pairCount.keySet()) {
String word1 = pair.getKey();
String word2 = pair.getValue();
double weight = (pairCount.get(pair) * 1.0) / Math.sqrt(wordCount.get(word1) * wordCount.get(word2));
wordWeight.put(word1, wordWeight.getOrDefault(word1, 0.0) + weight);
wordWeight.put(word2, wordWeight.getOrDefault(word2, 0.0) + weight);
}
List<Map.Entry<String, Double>> list = new ArrayList<>(wordWeight.entrySet());
list.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
Map<String, Double> ans = new LinkedHashMap<>();
for (Map.Entry<String, Double> entry : list) {
ans.put(entry.getKey(), entry.getValue());
}
return ans;
}
- 提取关键词
根据计算所得的词语权重,提取关键词。本文使用Top-K算法来提取权重最高的几个词语:
public List<String> extractKeywords(Map<String, Double> wordWeight, int k) {
List<String> keywords = new ArrayList<>();
int count = 0;
for (String word : wordWeight.keySet()) {
if (count >= k) break;
if (word.length() > 1) { // 只保留长度大于1的词语
keywords.add(word);
count++;
}
}
return keywords;
}
示例说明
示例1
文本:"我们是一道道题,我们是一道道难题,解决难题是我们最擅长的事情"
预处理后分词结果:["我们", "是", "一道道", "题", ",", "我们", "是", "一道道", "难题", ",", "解决", "难题", "是", "我们", "最", "擅长", "的", "事情"]
构建词语共现矩阵:"我们"和"是"的共现次数为2次,以此类推,得到以下词语共现矩阵:
我们 | 是 | 一道道 | 题 | , | 难题 | 解决 | 最 | 擅长 | 的 | 事情 | |
---|---|---|---|---|---|---|---|---|---|---|---|
我们 | 0 | 2 | 2 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
是 | 2 | 0 | 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
一道道 | 2 | 2 | 0 | 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
题 | 0 | 0 | 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
, | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
难题 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 |
解决 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
最 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
擅长 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
的 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
事情 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
根据词语共现矩阵,计算得到每一个词语的权重。以"题"为例,它的权重计算如下:
- "题"和"一道道"共现2次,"题"出现了1次,而"一道道"出现了3次。因此,"题"的权重为 $\frac{2}{\sqrt{2 \times 3}} = 0.816$
计算完所有词语的权重后,按照权重从高到低进行排序,得到:
- 一道道
- 题
- 我们
- 难题
- 是
- 最
- 擅长
- 解决
- 事情
- 的
- ,
提取权重最高的3个词语,得到:["一道道", "题", "我们"]
示例2
文本:"小天是一名机器学习工程师,他非常喜欢机器学习"
预处理后分词结果:["小天", "是", "一名", "机器学习", "工程师", ",", "他", "非常", "喜欢", "机器学习"]
构建词语共现矩阵:"小天"和"是"的共现次数为1,以此类推,得到以下词语共现矩阵:
小天 | 是 | 一名 | 机器学习 | 工程师 | , | 他 | 非常 | 喜欢 | ||
---|---|---|---|---|---|---|---|---|---|---|
小天 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | |
是 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | |
一名 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | |
机器学习 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | |
工程师 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | |
, | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | |
他 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | |
非常 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | |
喜欢 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
根据词语共现矩阵,计算得到每一个词语的权重。以"机器学习"为例,它的权重计算如下:
- "机器学习"和"小天"共现0次,"机器学习"出现了2次,而"小天"出现了1次。因此,"机器学习"的权重为 $\frac{0}{\sqrt{2\times 1}} + \frac{2}{\sqrt{2 \times 2}} = 0.707$
计算完所有词语的权重后,按照权重从高到低进行排序,得到:
- 机器学习
- 工程师
- 小天
- 非常
- 喜欢
- 一名
- 是
- 他
- ,
提取权重最高的3个词语,得到:["机器学习", "工程师", "小天"]
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java使用Nagao算法实现新词发现、热门词的挖掘 - Python技术站