您好,登錄后才能下訂單哦!
這篇文章給大家介紹Java中怎么實(shí)現(xiàn)一個(gè)TFIDF算法,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
算法介紹
最近要做領(lǐng)域概念的提取,TFIDF作為一個(gè)很經(jīng)典的算法可以作為其中的一步處理。
計(jì)算公式比較簡(jiǎn)單,如下:
預(yù)處理
由于需要處理的候選詞大約后3w+,并且語料文檔數(shù)有1w+,直接挨個(gè)文本遍歷的話很耗時(shí),每個(gè)詞處理時(shí)間都要一分鐘以上。
為了縮短時(shí)間,首先進(jìn)行分詞,一個(gè)詞輸出為一行方便統(tǒng)計(jì),分詞工具選擇的是HanLp。
然后,將一個(gè)領(lǐng)域的文檔合并到一個(gè)文件中,并用“$$$”標(biāo)識(shí)符分割,方便記錄文檔數(shù)。
下面是選擇的領(lǐng)域語料(PATH目錄下):
代碼實(shí)現(xiàn)
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"; // 語料庫(kù)路徑
public static void main(String[] args) throws Exception {
String test = "離退休人員"; // 要計(jì)算的候選詞
computeTFIDF(PATH, test);
}
/**
* @param @param path 語料路經(jīng)
* @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();
// 每個(gè)領(lǐng)域出現(xiàn)候選詞的文檔數(shù)
Map<String, Integer> containsKeyMap = new HashMap<>();
// 每個(gè)領(lǐng)域的總文檔數(shù)
Map<String, Integer> totalDocMap = new HashMap<>();
// TF = 候選詞出現(xiàn)次數(shù)/總詞數(shù)
Map<String, Double> tfMap = new HashMap<>();
// scan files
for (File f : files) {
// 候選詞詞頻
double termFrequency = 0;
// 文本總詞數(shù)
double totalTerm = 0;
// 包含候選詞的文檔數(shù)
int containsKeyDoc = 0;
// 詞頻文檔計(jì)數(shù)
int totalCount = 0;
int fileCount = 0;
// 標(biāo)記文件中是否出現(xiàn)候選詞
boolean flag = false;
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
String s = "";
// 計(jì)算詞頻和總詞數(shù)
while ((s = br.readLine()) != null) {
if (s.equals(word)) {
termFrequency++;
flag = true;
}
// 文件標(biāo)識(shí)符
if (s.equals("$$$")) {
if (flag) {
containsKeyDoc++;
}
fileCount++;
flag = false;
}
totalCount++;
}
// 減去文件標(biāo)識(shí)符的數(shù)量得到總詞數(shù)
totalTerm += totalCount - fileCount;
br.close();
// key都為領(lǐng)域的名字
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("該領(lǐng)域文檔數(shù):" + fileCount);
System.out.println("候選詞出現(xiàn)詞數(shù):" + termFrequency);
System.out.println("總詞數(shù):" + totalTerm);
System.out.println("出現(xiàn)候選詞文檔總數(shù):" + containsKeyDoc);
System.out.println();
}
//計(jì)算TF*IDF
for (File f : files) {
// 其他領(lǐng)域包含候選詞文檔數(shù)
int otherContainsKeyDoc = 0;
// 其他領(lǐng)域文檔總數(shù)
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();
// 計(jì)算其他領(lǐng)域包含候選詞文檔數(shù)
for (Map.Entry<String, Integer> entry : containsKeyset) {
if (!entry.getKey().equals(f.getName())) {
otherContainsKeyDoc += entry.getValue();
}
}
// 計(jì)算其他領(lǐng)域文檔總數(shù)
for (Map.Entry<String, Integer> entry : totalDocset) {
if (!entry.getKey().equals(f.getName())) {
otherTotalDoc += entry.getValue();
}
}
// 計(jì)算idf
idf = log((float) otherTotalDoc / (otherContainsKeyDoc + 1), 2);
// 計(jì)算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));
}
}
運(yùn)行結(jié)果
測(cè)試詞為“離退休人員”,中間結(jié)果如下:
最終結(jié)果:
關(guān)于Java中怎么實(shí)現(xiàn)一個(gè)TFIDF算法就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。