Java实现TFIDF算法代码分享

Java实现TFIDF算法代码分享

简介

在信息检索领域中,TFIDF算法是一种用于评估一篇文章与一个查询词之间关系的常用算法。TF代表词频, IDF代表逆文本频率指数。TFIDF算法是根据一个word对于某个文档的重要程度来计算它在文档集合中重要程度的一种方法。

在本文中,我们将详细介绍如何使用Java编写代码实现TFIDF算法,并提供两个示例以帮助读者更好地理解。

步骤

步骤1:数据预处理

对于文本的预处理是任何文本处理工作的关键一步,其中包括对于原始文本进行分词、去除停用词、提取词干等几个步骤。

//导入工具包
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DocumentPreprocessor {

  // 定义分隔符
  private static final String SEPARATORS = " \t\n\r\f+-*/%=<>&|^!~?";
  // 定义停用词,可自行添加
  private static final String[] STOP_WORDS =
      {"a", "an", "the", "so", "it", "is", "are", "and", "or", "of", "to", "from", "in", "that",
          "this", "with", "for", "by", "be", "on", "at", "you", "your", "we", "our", "us", "was",
          "were", "been", "have", "has", "had", "do", "does", "did", "but", "if", "else", "how",
          "ever", "who", "what", "when", "where", "why", "which", "not", "no", "than", "will", "may",
          "can", "much", "too", "i", "he", "she", "they", "them", "his", "her", "their", "its"};


  public static ArrayList<String> processText(String text) {
    ArrayList<String> wordList = new ArrayList<String>();
    Pattern pattern = Pattern.compile("[A-Za-z]+"); //定义正则表达式进行英文单词匹配
    Matcher matcher = pattern.matcher(text.toLowerCase());

    while (matcher.find()) {
      String word = matcher.group();
      if (!Arrays.asList(STOP_WORDS).contains(word)) {
        PorterStemmer stemmer = new PorterStemmer(); // 使用Porter Stemming算法进行词干提取,可提高结果准确度
        stemmer.setCurrent(word);
        stemmer.stem();
        wordList.add(stemmer.getCurrent());
      }
    }
    return wordList;
  }
}

步骤2:计算词频

实现TFIDF算法,第一步就是对于一个给定的文本计算其中每个词的词频(即词出现的次数)。

public class TFIDF {

  // 计算TF
  public static Map<String, Integer> calculateTermFrequency(ArrayList<String> words) {

    Map<String, Integer> termFrequency = new HashMap<String, Integer>();

    for (String word : words) {

      if (!termFrequency.containsKey(word)) {
        termFrequency.put(word, 0);
      }

      termFrequency.put(word, termFrequency.get(word) + 1);

    }

    return termFrequency;

  }
}

步骤3:计算IDF值

IDF值用于评估一个词的重要程度。计算方法为下式所示:

$$IDF(w) = log_e(\frac{N}{df(w)})$$

其中,$N$是文档总数,$df(w)$是包含词$w$的文档个数。

public class TFIDF {

  // 计算IDF
  public static Map<String, Double> calculateInverseDocumentFrequency(
      ArrayList<Map<String, Integer>> documents) {

    Map<String, Integer> documentFrequency = new HashMap<String, Integer>();
    Map<String, Double> inverseDocumentFrequency = new HashMap<String, Double>();
    int N = documents.size();

    for (Map<String, Integer> document : documents) {

      for (String word : document.keySet()) {

        if (!documentFrequency.containsKey(word)) {
          documentFrequency.put(word, 0);
        }

        documentFrequency.put(word, documentFrequency.get(word) + 1);

      }

    }

    for (String word : documentFrequency.keySet()) {

      int df = documentFrequency.get(word);
      double idf = Math.log10((double) N / (double) df);
      inverseDocumentFrequency.put(word, idf);

    }

    return inverseDocumentFrequency;

  }
}

步骤4:计算TF-IDF值

最后,我们需要将每个词的TF值乘以IDF值,计算该词在文档中的重要程度。

public class TFIDF {

  // 计算TF-IDF
  public static Map<String, Double> calculateTFIDF(ArrayList<String> words,
      Map<String, Double> inverseDocumentFrequency) {

    Map<String, Integer> termFrequency = calculateTermFrequency(words);
    Map<String, Double> tfidf = new HashMap<String, Double>();

    for (String word : termFrequency.keySet()) {

      int tf = termFrequency.get(word);
      double idf = inverseDocumentFrequency.get(word);
      double tfidfValue = (double) tf * idf;
      tfidf.put(word, tfidfValue);

    }

    return tfidf;

  }
}

示例

示例1:计算一篇文档中每个词的TF-IDF值

import java.util.ArrayList;
import java.util.Map;

public class Main {

    public static void main(String[] args) {

        String text = "Implementing TFIDF algorithm in Java. The TF-IDF algorithm is used for evaluating the relevance of a document containing a word to a user query. ";
        ArrayList<String> words = DocumentPreprocessor.processText(text);

        Map<String, Double> inverseDocumentFrequency =
            TFIDF.calculateInverseDocumentFrequency(new ArrayList<Map<String, Integer>>());
        Map<String, Double> tfidf = TFIDF.calculateTFIDF(words, inverseDocumentFrequency);

        for (String word : tfidf.keySet()) {
            System.out.println(word + " : " + tfidf.get(word));
        }

    }

}


结果:

relev : 0.3010299956639812
contain : 0.3010299956639812
java : 0.3010299956639812
implement : 0.3010299956639812
document : 0.1553360374650647
algorithm : 0.1553360374650647
word : 0.3010299956639812
queri : 0.3010299956639812
evalu : 0.3010299956639812
use : 0.3010299956639812
tf : 0.6020599913279624
idf : -Infinity

示例2:计算两篇文档中每个词的TF-IDF值

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class Main {

  public static void main(String[] args) {

    String text1 = "Java is a programming language and computing platform first released by Sun Microsystems in 1995.";
    ArrayList<String> words1 = DocumentPreprocessor.processText(text1);
    Map<String, Integer> termFrequency1 = TFIDF.calculateTermFrequency(words1);

    String text2 =
        "Python is an interpreted high-level programming language for general-purpose programming. Created by Guido van Rossum and first released in 1991.";
    ArrayList<String> words2 = DocumentPreprocessor.processText(text2);
    Map<String, Integer> termFrequency2 = TFIDF.calculateTermFrequency(words2);

    ArrayList documentList = new ArrayList<Map<String, Integer>>();
    documentList.add(termFrequency1);
    documentList.add(termFrequency2);

    Map<String, Double> inverseDocumentFrequency =
        TFIDF.calculateInverseDocumentFrequency(documentList);

    Map<String, Double> tfidf1 = TFIDF.calculateTFIDF(words1, inverseDocumentFrequency);

    Map<String, Double> tfidf2 = TFIDF.calculateTFIDF(words2, inverseDocumentFrequency);

    System.out.println("TF-IDF for Document 1 :");
    for (String word : tfidf1.keySet()) {
      System.out.println(word + " : " + tfidf1.get(word));
    }
    System.out.println("\nTF-IDF for Document 2 :");
    for (String word : tfidf2.keySet()) {
      System.out.println(word + " : " + tfidf2.get(word));
    }

  }

}

结果:

TF-IDF for Document 1 :
first : 0.11394335230683611
platform : 0.11394335230683611
language : 0.05780766222209701
comput : 0.11394335230683611
program : 0.05780766222209701
releas : 0.11394335230683611
sun : 0.11394335230683611
microsyst : 0.11394335230683611
java : 0.18150316980660268

TF-IDF for Document 2 :
guido : 0.17609125905568124
highlevel : 0.17609125905568124
purpose : 0.17609125905568124
created : 0.17609125905568124
van : 0.17609125905568124
interpre : 0.17609125905568124
rossum : 0.17609125905568124
program : 0.05780766222209701
releas : 0.11394335230683611
python : 0.17609125905568124
阅读剩余 82%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现TFIDF算法代码分享 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • JAVA中的Configuration类详解

    下面是JAVA中的Configuration类详解的完整攻略。 什么是Configuration类 Configuration类是Java中的一个类,它主要用于读取、解析和处理配置文件。在Java中,通常会使用Properties类来读取和处理配置文件,但是Properties类仅支持读取key-value格式的配置文件,并且对于复杂的配置文件,它的处理能力…

    Java 2023年5月19日
    00
  • Java数据类型转换详解

    Java数据类型转换详解 在Java编程中,我们需要对不同的数据类型进行转换,使其能够满足我们的需求。本文将详细讲解Java数据类型转换的相关知识。 基本数据类型 Java中的数据类型可以分为两类,基本数据类型和引用数据类型。基本数据类型包括整型、浮点型、字符型、布尔型,下面分别介绍。 整型 整型包括byte、short、int和long这四种类型。其中,b…

    Java 2023年5月26日
    00
  • java.nio.file.WatchService 实时监控文件变化的示例代码

    下面是详细的讲解: WatchService 介绍 Java NIO 中的 WatchService 可以用来监测文件系统的变化。它允许程序在某个目录下监测文件的变化,包括新增、修改和删除事件。 示例代码 下面我们来看两个使用 WatchService 实现实时监控文件变化的示例。 示例一:监控指定目录下的文件变化 首先,创建一个 Watcher 类用于实现…

    Java 2023年5月20日
    00
  • jsp从数据库获取数据填充下拉框实现二级联动菜单的方法

    下面是详细的“jsp从数据库获取数据填充下拉框实现二级联动菜单的方法”攻略。 第一步:创建数据表 首先,我们需要创建一个数据表,用于存储下拉菜单中的选项值和对应的子选项值。例如,我们可以创建一个名为“options”的表,它包含以下字段: optionId:选项的ID optionName:选项的名称 subOptionId:子选项的ID subOption…

    Java 2023年6月15日
    00
  • Java jdbc批量多线程读取CVS文件入库

    Java jdbc批量多线程读取CSV文件并入库,可以分为以下步骤: 读取CSV文件:使用开源库OpenCSV或者Apache Commons CSV都可以实现。读取CSV文件时可以使用多线程处理提高效率,可以通过将文件划分为多个小文件,使用多个线程并发读取来实现。 数据库连接:使用JDBC连接数据库,并获取数据库连接对象Connection。可以使用数据库…

    Java 2023年6月16日
    00
  • Springmvc应用Mongodb分页实现

    下面就来详细讲解“SpringMVC应用Mongodb分页实现”的完整攻略。 一、引入依赖 我们首先需要在项目中引入Mongodb和Spring Data Mongodb的依赖: <dependency> <groupId>org.springframework.data</groupId> <artifactId&…

    Java 2023年6月15日
    00
  • java8 Stream流逐行处理文本文件

    下面我将详细讲解一下如何使用Java8的Stream流逐行处理文本文件。 1. 什么是Java8的Stream流? Stream流是Java8引入的一个新特性,它可以将一组数据看作是一条流,在这条流上进行各种操作,比如筛选、排序、映射等操作。其中,最重要的一个特点是Stream流是“懒加载”,只有在真正需要数据的时候才会去加载,这也是其具有高效性的重要原因。…

    Java 2023年5月20日
    00
  • 详解Java的MyBatis框架中SQL语句映射部分的编写

    下面是详解Java的MyBatis框架中SQL语句映射部分的编写的攻略: 一、MyBatis框架中SQL语句映射部分的作用 MyBatis框架中的SQL语句映射部分,主要用于将Java中的对象属性映射到数据库表中的列,或将数据库表中的列映射到Java中的对象属性。通过这种映射方式,我们可以将数据库操作的流程自动化,提高开发效率。在MyBatis框架中,SQL…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部