java实现文本相似度计算

需求

**文本推荐:**有多个文本字符串,如何设计一个简单的统计方法(从词频的角度设计),来计算出多个文本字符串两两之间的相似度,并输出大于指定相似度阈值的文本

分析理解

使用Java实现文本相似度计算的一种方法是通过构建词频向量并计算余弦相似度,具体介绍如下,简单易懂
在这里插入图片描述
在这里插入图片描述

代码实现

复杂粘贴可以直接运行

        <!--  使用HanLP进行分词  -->
        <dependency>
            <groupId>com.hankcs</groupId>
            <artifactId>hanlp</artifactId>
            <version>portable-1.8.4</version>
        </dependency>
import com.hankcs.hanlp.tokenizer.StandardTokenizer;
import java.util.*;
import java.util.stream.Collectors;

public class ChineseTextRecommender {

    // 使用HanLP进行中文分词
    // 构建词频向量
    // 假设我们有两个文本文档,我们想衡量它们的主题相似性。每个文档可以被表示为一个向量,其中包含词频(TF)或TF-IDF值。
    // 文档A: "the cat sat on the mat on the mat"
    // 文档B: "the cat and the dog played"
    // 我们选择几个关键词:"the", "cat", "sat", "on", "mat", "and", "dog", "played"。每个词在文档中出现的次数(词频)可以构成一个向量。
    // 向量A: [2, 1, 1, 1, 2, 0, 0, 0]("the", "cat", "sat", "on", "mat", "and", "dog", "played")
    // 向量B: [1, 1, 0, 0, 0, 1, 1, 1]
    public static Map<String, Integer> buildTermVector(String text) {
        List<String> words = StandardTokenizer.segment(text).stream()
                .map(term -> term.word)
                .collect(Collectors.toList());
        Map<String, Integer> termVector = new HashMap<>();
        for (String word : words) {
            termVector.put(word, termVector.getOrDefault(word, 0) + 1);
        }
        return termVector;
    }

    // 计算余弦相似度
    public static double cosineSimilarity(Map<String, Integer> vectorA, Map<String, Integer> vectorB) {
        double dotProduct = 0.0;
        double normA = 0.0;
        double normB = 0.0;

        for (String key : vectorA.keySet()) {
            dotProduct += vectorA.get(key) * (vectorB.getOrDefault(key, 0));
            normA += Math.pow(vectorA.get(key), 2);
        }

        for (String key : vectorB.keySet()) {
            normB += Math.pow(vectorB.get(key), 2);
        }

        if (normA == 0 || normB == 0) {
            return 0.0;
        }

        return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
    }

    // 推荐与指定文本相似度高的文本 texts为待判断文本列表
    public static List<String> recommendTexts(List<String> texts, String targetText, double threshold) {
        Map<String, Double> similarityScores = new HashMap<>();
        Map<String, Integer> targetVector = buildTermVector(targetText);

        for (String text : texts) {
            Map<String, Integer> textVector = buildTermVector(text);
            double similarity = cosineSimilarity(targetVector, textVector);
            similarityScores.put(text, similarity);
            System.out.println(text + " ----Similarity: " + similarity);
        }

        return similarityScores.entrySet().stream()
                .filter(entry -> entry.getValue() >= threshold)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }

    public static void main(String[] args) {
        // 相似度分别为0.91 0.59 0.54 0.799 0.791
        List<String> texts = Arrays.asList("这是一个测试文档吗", "这是第二个文档", "这是第三个文档","这是一个文档吗","这是第一个测试文档吧哈哈");
        String targetText = "这是一个测试文档";
        double threshold = 0.8; // 理论上,阈值在0.5左右都可以接受

        List<String> recommendedTexts = recommendTexts(texts, targetText, threshold);

        System.out.println("推荐文本:");
        recommendedTexts.forEach(System.out::println);
    }
}

输出结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值