接上一篇,同样在wind中考了,因为没怎么接触过自然语言处理,所以对这一类算法并不熟悉,只知道有这么个词儿···尴尬···
参考:https://blog.csdn.net/lionel_fengj/article/details/53699903
算法应用:是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。
基本思想:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TF-IDF实际上就是 TF*IDF,其中 TF(Term Frequency),表示词条在文章Document 中出现的频率;IDF(Inverse Document Frequency),其主要思想就是,如果包含某个词 Word的文档越少,则这个词的区分度就越大,也就是 IDF 越大。对于如何获取一篇文章的关键词,我们可以计算这边文章出现的所有名词的 TF-IDF,TF-IDF越大,则说明这个名词对这篇文章的区分度就越高,取 TF-IDF 值较大的几个词,就可以当做这篇文章的关键词。
代码实现(https://blog.csdn.net/lionel_fengj/article/details/53699903,来源戳这里)
package com.myapp.ml.nlp;
import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;
import org.ansj.util.FilterModifWord;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lionel on 16/12/15.
*/
public class TFIDFAlgorithm {
/**
* 根据文件路径,文件中存放的100个网址的 url,获取 url 路径列表
*
* @param path 本地文件路径
* @return 路径列表
*/
public List<String> readUrlFromText(String path) {
if (StringUtils.isBlank(path)) {
return null;
}
List<String> urls = new ArrayList<String>();
try {
BufferedReader reader = new BufferedReader(new FileReader(path));
String line;
while ((line = reader.readLine()) != null) {
urls.add(line.trim());
}
} catch (IOException e) {
e.printStackTrace();
}
return urls;
}
/**
* 利用 Jsoup 工具,根据网址获取网页文本
*
* @param url 网址
* @return 网页文本
*/
public String getTextFromUrl(String url) {
if (StringUtils.isBlank(url)) {
return null;
}
String text = "";
try {
Document document = Jsoup.connect(url).get();
text = document.text();
} catch (IOException e) {
e.printStackTrace();
}
return text.replace(" ", "");
}
/**
* 运用 ansj 给文本分词
*
* @param text 文本内容
* @return 分词结果
*/
public List<Term> parse(String text) {
if (StringUtils.isBlank(text)) {
return null;
}
List<Term> terms = FilterModifWord.modifResult(ToAnalysis.parse(text));
if (terms == null || terms.size() == 0) {
return null;
}
return terms;
}
/**
* 计算一篇文章分词后除去标点符号后词的总数
*
* @param terms 分词后的集合
* @return 一篇文章分词后除去标点符号后词的总数
*/
private Integer countWord(List<Term> terms) {
if (terms == null || terms.size() == 0) {
return null;
}
for (int i = 0; i < terms.size(); i++) {
if ("null".equals(terms.get(i).getNatureStr()) || terms.get(i).getNatureStr().startsWith("w")) {
terms.remove(i);
}
}
return terms.size();
}
/**
* 计算词频 IF
*
* @param word 词
* @param terms 分词结果集合
* @return IF
*/
public double computeTF(String word, List<Term> terms) {
if (StringUtils.isBlank(word)) {
return 0.0;
}
int count = 0;
for (Term term : terms) {
if (term.getName().equals(word)) {
count += 1;
}
}
return (double) count / countWord(terms);
}
/**
* 统计词语的逆文档频率 IDF
*
* @param path 存放 url 的文件路径
* @param word IDF
*/
public double computeIDF(String path, String word) {
if (StringUtils.isBlank(path) || StringUtils.isBlank(word)) {
return 0.0;
}
List<String> urls = readUrlFromText(path);
int count = 1;
for (String url : urls) {
String text = getTextFromUrl(url);
if (text.contains(word)) {
count += 1;
}
}
return Math.log10((double) urls.size() / count);
}
/**
* 计算词频-逆文档频率 TF—IDF
*
* @param filePath 存放url的文件路径
* @param terms 分词结果集合
* @param word 词
* @return TF—IDF
*/
public Double computeTFIDF(String filePath, List<Term> terms, String word) {
return computeTF(word, terms) * computeIDF(filePath, word);
}
}