首页 > 编程语言 >Java中的文本聚类算法:如何进行大规模无监督文本分类

Java中的文本聚类算法:如何进行大规模无监督文本分类

时间:2024-09-19 23:22:40浏览次数:8  
标签:Java int 聚类 new lucene org apache import 文本

Java中的文本聚类算法:如何进行大规模无监督文本分类

大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!

文本聚类是自然语言处理中的一个重要任务,旨在将大量的文本数据分成几个有意义的类别。由于文本数据的高维性和稀疏性,处理大规模无监督文本分类通常面临不少挑战。本文将介绍在Java中实现文本聚类的基本步骤,包括特征提取、相似度计算和聚类算法的应用。

1. 文本预处理

在进行文本聚类之前,通常需要对文本数据进行预处理,包括分词、去除停用词和词干提取。

1.1 文本预处理示例

以下是一个简单的文本预处理示例:

package cn.juwatech.textprocessing;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class TextPreprocessing {

    public static void main(String[] args) {
        String text = "Java is a versatile programming language. Java is widely used in various applications.";
        List<String> processedText = preprocessText(text);
        System.out.println("Processed text: " + processedText);
    }

    public static List<String> preprocessText(String text) {
        // 转小写
        String lowerCaseText = text.toLowerCase();
        
        // 去除标点符号
        String cleanedText = lowerCaseText.replaceAll("[^a-zA-Z\\s]", "");
        
        // 分词
        List<String> words = Arrays.asList(cleanedText.split("\\s+"));
        
        // 去除停用词(示例中不包含具体停用词列表)
        List<String> stopWords = Arrays.asList("is", "a", "the", "and", "in", "of");
        List<String> filteredWords = words.stream()
                .filter(word -> !stopWords.contains(word))
                .collect(Collectors.toList());
        
        return filteredWords;
    }
}

2. 特征提取

文本特征提取将文本数据转换为数值表示,常用的方法包括词袋模型(Bag of Words)和TF-IDF(Term Frequency-Inverse Document Frequency)。

2.1 使用TF-IDF进行特征提取

以下是使用TF-IDF进行特征提取的示例代码:

package cn.juwatech.textprocessing;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.TokenStreamComponents;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.en.EnglishAnalyzer;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.Version;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.TokenStreamComponents;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;

import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;

public class TFIDFVectorization {

    public static void main(String[] args) throws IOException {
        String[] documents = {
            "Java is a versatile programming language.",
            "Java is widely used in various applications.",
            "Python is another popular programming language."
        };

        Map<String, Map<String, Double>> tfidfMatrix = computeTFIDF(documents);

        for (String doc : tfidfMatrix.keySet()) {
            System.out.println("Document: " + doc);
            System.out.println("TF-IDF Values: " + tfidfMatrix.get(doc));
        }
    }

    public static Map<String, Map<String, Double>> computeTFIDF(String[] documents) throws IOException {
        Map<String, Map<String, Double>> tfidfMatrix = new HashMap<>();
        Map<String, Integer> documentFrequency = new HashMap<>();
        int totalDocuments = documents.length;

        // Create a RAMDirectory to hold the index
        RAMDirectory ramDirectory = new RAMDirectory();
        IndexWriterConfig config = new IndexWriterConfig(new StandardAnalyzer());
        IndexWriter indexWriter = new IndexWriter(ramDirectory, config);

        // Index documents
        for (int i = 0; i < documents.length; i++) {
            Document doc = new Document();
            doc.add(new TextField("content", documents[i], Field.Store.YES));
            indexWriter.addDocument(doc);
        }
        indexWriter.close();

        // Compute document frequency
        DirectoryReader directoryReader = DirectoryReader.open(ramDirectory);
        for (IndexableField field : directoryReader.document(0).getFields()) {
            String term = field.stringValue();
            documentFrequency.put(term, documentFrequency.getOrDefault(term, 0) + 1);
        }
        directoryReader.close();

        // Compute TF-IDF values
        for (int i = 0; i < documents.length; i++) {
            Map<String, Double> tfidfValues = new HashMap<>();
            TokenStream tokenStream = new StandardAnalyzer().tokenStream("content", new StringReader(documents[i]));
            CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);

            tokenStream.reset();
            while (tokenStream.incrementToken()) {
                String term = charTermAttribute.toString();
                int termFrequency = termFrequency(term, documents[i]);
                double idf = Math.log((double) totalDocuments / (documentFrequency.get(term) + 1));
                double tfidf = termFrequency * idf;
                tfidfValues.put(term, tfidf);
            }
            tokenStream.end();
            tokenStream.close();

            tfidfMatrix.put(documents[i], tfidfValues);
        }

        return tfidfMatrix;
    }

    private static int termFrequency(String term, String document) {
        String[] words = document.split("\\s+");
        int frequency = 0;
        for (String word : words) {
            if (word.equals(term)) {
                frequency++;
            }
        }
        return frequency;
    }
}

3. 聚类算法

常见的文本聚类算法包括K-means、层次聚类(Hierarchical Clustering)和DBSCAN。以下是使用K-means进行文本聚类的示例代码:

3.1 K-means聚类
package cn.juwatech.textclustering;

import org.apache.commons.math3.linear.ArrayRealVector;
import org.apache.commons.math3.linear.RealVector;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.DecompositionSolver;
import org.apache.commons.math3.linear.SingularValueDecomposition;
import org.apache.commons.math3.linear.BlockRealMatrix;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

public class KMeansClustering {

    public static void main(String[] args) {
        double[][] data = {
            {1.0, 2.0},
            {1.5, 1.8},
            {5.0, 8.0},
            {8.0, 8.0},
            {1.0, 0.6},
            {9.0, 11.0}
        };

        int k = 2; // 聚类数
        KMeans kMeans = new KMeans(data, k);
        kMeans.cluster();
        kMeans.printClusters();
    }
}

class KMeans {
    private final double[][] data;
    private final int k;
    private final int numFeatures;
    private final List<RealVector> centroids;
    private final List<Integer> labels;

    public KMeans(double[][] data, int k) {
        this.data = data;
        this.k = k;
        this.numFeatures = data[0].length;
        this.centroids = new ArrayList<>(k);
        this.labels = new ArrayList<>(data.length);

        // 初始化中心点
        initializeCentroids();
    }

    private void initializeCentroids() {
        Random random = new Random();
        for (int i = 0; i < k; i++) {
            centroids.add(new ArrayRealVector(data[random.nextInt(data.length)]));
        }
    }

    public void cluster() {
        boolean changed;
        do {
            changed = false;

            // 为每个样本分配簇
            for (int i = 0; i < data.length; i++) {
                RealVector point = new ArrayRealVector(data[i]);
                int label = findClosestCentroid(point);
                labels.add(label);
            }

            // 更新中心点
            List<RealVector> newCentroids = new ArrayList<>(k);
            for (int i = 0; i < k; i++) {
                RealVector newCentroid = computeMeanForCluster(i);
                newCentroids.add(newCentroid);
            }

            // 检查中心点是否发生变化
            for (int i = 0; i < k; i

++) {
                if (!centroids.get(i).equals(newCentroids.get(i))) {
                    changed = true;
                    break;
                }
            }

            centroids.clear();
            centroids.addAll(newCentroids);
            labels.clear();
        } while (changed);
    }

    private int findClosestCentroid(RealVector point) {
        double minDistance = Double.MAX_VALUE;
        int closestCentroid = -1;
        for (int i = 0; i < k; i++) {
            double distance = point.getDistance(centroids.get(i));
            if (distance < minDistance) {
                minDistance = distance;
                closestCentroid = i;
            }
        }
        return closestCentroid;
    }

    private RealVector computeMeanForCluster(int clusterIndex) {
        List<RealVector> clusterPoints = new ArrayList<>();
        for (int i = 0; i < data.length; i++) {
            if (labels.get(i) == clusterIndex) {
                clusterPoints.add(new ArrayRealVector(data[i]));
            }
        }

        RealVector mean = new ArrayRealVector(numFeatures);
        for (RealVector point : clusterPoints) {
            mean = mean.add(point);
        }
        return mean.mapDivide(clusterPoints.size());
    }

    public void printClusters() {
        for (int i = 0; i < k; i++) {
            System.out.println("Cluster " + i + ":");
            for (int j = 0; j < data.length; j++) {
                if (labels.get(j) == i) {
                    System.out.println(Arrays.toString(data[j]));
                }
            }
        }
    }
}

总结

在Java中实现文本聚类算法包括几个关键步骤:文本预处理、特征提取和聚类算法的应用。我们通过示例代码演示了如何实现这些步骤,包括使用TF-IDF进行特征提取以及应用K-means进行聚类。处理大规模文本数据时,通常需要结合高效的算法和优化的实现以提升性能和准确度。

本文著作权归聚娃科技微赚淘客系统开发者团队,转载请注明出处!

标签:Java,int,聚类,new,lucene,org,apache,import,文本
From: https://blog.csdn.net/weixin_44409190/article/details/142309052

相关文章

  • Java中的自适应学习率方法:如何提高训练稳定性
    Java中的自适应学习率方法:如何提高训练稳定性大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在机器学习和深度学习模型训练过程中,学习率是一个至关重要的超参数。不同的学习率会直接影响模型的收敛速度和性能。然而,固定的学习率往往难以应对复杂的......
  • Java中的高效模型压缩技术:从剪枝到知识蒸馏
    Java中的高效模型压缩技术:从剪枝到知识蒸馏大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!随着深度学习模型在各种任务中的广泛应用,模型的规模和复杂度也在不断增加。然而,较大的模型通常会占用大量的计算资源和内存,使其在资源有限的设备上(如移动设......
  • JavaScript(单分支语句,双分支语句,多分支语句判断闰年还是平年,三元运算符求最大值,switch
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>Document</title><......
  • [Java原创精品]基于Springboot+Vue的高校社团管理、学生社团招新平台
    项目提供:完整源码+数据库sql文件+数据库表Excel文件1、项目功能描述本项目角色为社团社长、学生用户、系统管理员三角色,社长登录进入后台,可切换至前台使用功能,学生用户只进入前台使用,系统管理员只进入后台管理操作。1.1注册注册功能:填写用户名、密码进行注册。(“我已......
  • js 文本
    目录js通过字符串类型表示文本字符串(string)是一组由16位值组成的不可变的有序序列,每个字符通常来自于Unicode字符集.js通过字符串类型表示文本字符串的长度(length)是其所含16位值的个数js字符串和其数组的索引从零开始,第一个字符的位置是0,第二个位置是1空字符串(empty......
  • Java 23 的12 个新特性!!
    Java23来啦!和Java22一样,这也是一个非LTS(长期支持)版本,Oracle仅提供六个月的支持。下一个长期支持版是Java25,预计明年9月份发布。Java23一共有12个新特性!有同学表示,Java8还没学完呢,又要学新特性?人麻了啊。。。别担心,其实改动并不大!我抽时间认真看了一下新......
  • ssm基于javaweb的疫情管理系统的设计与实现
    系统包含:源码+论文所用技术:SpringBoot+Vue+SSM+Mybatis+Mysql免费提供给大家参考或者学习,获取源码请私聊我需要定制请私聊目录摘要 IAbstract II第1章绪论 11.1研究背景及意义 11.2研究内容 1第2章开发环境与技术 32.1Java语言 32.2MYSQL数据库 3......
  • 关于我学习java的小结07
    一、知识点本节课的知识点为集合、泛型、Map。二、目标了解集合关系图。掌握List和Set的区别。掌握ArrayList和LinkedList的区别。熟练使用集合相关API。三、内容分析重点集合、泛型、Map。难点集合相关API的使用。各个集合底层原理的区别。四、内容1......
  • 计算机毕业设计 基于协同过滤算法的个性化音乐推荐系统 Java+SpringBoot+Vue 前后端分
    ......
  • web - JavaScript
    JavaScript1,JavaScript简介JavaScript是一门跨平台、面向对象的脚本语言,而Java语言也是跨平台的、面向对象的语言,只不过Java是编译语言,是需要编译成字节码文件才能运行的;JavaScript是脚本语言,不需要编译,由浏览器直接解析并执行。JavaScript是用来控制网页行为的,它能使......