Java实现 TF-IDF算法

3 篇文章 0 订阅

0写在前面:

前些天研究所有个处理文本的任务,将文本分完词然后利用tfidf计算每个文档中单词的tfidf值,其中文本(是一些舆情的新闻)已经有特定标签,表示是正向、负向还是中性的文本。后续使用这些处理好的文档来做一些舆情的情感预测。
在网上查找了一些有关java编写的tfidf程序,发现有的写的很混乱,而且没有相关的注释,阅读起来有很大的不方便,遂自己重写编写了一下tfidf,大神轻喷代码。

1.TFIDF的思想

TFIDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
TFIDF实际上是:TF * IDF,TF词频(Term Frequency),IDF逆向文件频率(Inverse Document Frequency)。TF表示词条在文档d中出现的频率。
IDF的主要思想是:如果包含词条t的文档越少,也就是n越小,IDF越大,则说明词条t具有很好的类别区分能力。如果某一类文档C中包含词条t的文档数为m,而其它类包含t的文档总数为k,显然所有包含t的文档数n=m+k,当m大的时候,n也大,按照IDF公式得到的IDF的值会小,就说明该词条t类别区分能力不强。
但是实际上,如果一个词条在一个类的文档中频繁出现,则说明该词条能够很好代表这个类的文本的特征,这样的词条应该给它们赋予较高的权重,并选来作为该类文本的特征词以区别与其它类文档。这就是IDF的不足之处. 在一份给定的文件里,词频(term frequency,TF)指的是某一个给定的词语在该文件中出现的频率。这个数字是对词数(term count)的归一化,以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词数,而不管该词语重要与否。

2.程序实现

首先是计算tf的代码:我们使用map来存储tf的结果,这个地方需要注意的是,我们先通过分词软件将所有的文档读成一个map,Map< String,String >其中key是每个文档的文档名,对应的value是分完词后的文档内容,单词以空格分割。这里我们定义tf的方法传的参数是map中的value值(也就是一个String),然后计算单词的tf值。

举例:参数wordAll=“合肥 工业 大学 简称 合 工大 位于 安徽省 省会 合肥市 创建 1945年 秋 1960年 10月 22日 中共中央 批准 全国 重点 大学 教育部 直属 高校 工程 工程 优势 学科 创新 平台 项目 建设 高校 工科 主要 特色 工 理 文 经 管 法 教育 多 学科 综合性 高等院校”

/**
     * 计算每个文档的tf值
     * @param wordAll
     * @return Map<String,Float> key是单词 value是tf值
     */
    public static Map<String,Float> tfCalculate(String wordAll){
        //存放(单词,单词数量)
        HashMap<String, Integer> dict = new HashMap<String, Integer>();
        //存放(单词,单词词频)
        HashMap<String, Float> tf = new HashMap<String, Float>();
        int wordCount=0;

        /**
         * 统计每个单词的数量,并存放到map中去
         * 便于以后计算每个单词的词频
         * 单词的tf=该单词出现的数量n/总的单词数wordCount
         */
        for(String word:wordAll.split(" ")){
            wordCount++;
            if(dict.containsKey(word)){
                dict.put(word,  dict.get(word)+1);
            }else{
                dict.put(word, 1);
            }
        }

        for(Map.Entry<String, Integer> entry:dict.entrySet()){
            float wordTf=(float)entry.getValue()/wordCount;
            tf.put(entry.getKey(), wordTf);
        }
        return tf;
    } 

然后计算tfidf的值:这里需要说明的是,在计算idf的时候会涉及到包含某个单词的文档数,所以这里,会将分完词后的map传输进来。
最后用一个Map来存储最后的结果,Map< String>

/**
     * 
     * @param D 总文档数
     * @param doc_words 每个文档对应的分词
     * @param tf 计算好的tf,用这个作为基础计算tfidf
     * @return 每个文档中的单词的tfidf的值
     * @throws IOException 
     * @throws FileNotFoundException 
     */
    public static Map<String,Float> tfidfCalculate(int D, Map<String,String> doc_words,Map<String,Float> tf) throws FileNotFoundException, IOException{

        HashMap<String,Float> tfidf=new HashMap<String, Float>();
        for(String key:tf.keySet()){
            int Dt=0;
            for(Map.Entry<String, String> entry:doc_words.entrySet()){

                String[] words=entry.getValue().split(" ");

                List<String> wordlist=new ArrayList<String>();
                for(int i=0;i<words.length;i++){
                    wordlist.add(words[i]);                }
                if(wordlist.contains(key)){
                    Dt++;
                }
            }
            float idfvalue=(float) Math.log(Float.valueOf(D)/Dt);
            tfidf.put(key, idfvalue * tf.get(key));

        }       
        return tfidf;  
  }


3.最后
tfidf的githup地址:https://github.com/xudongMk/tfidfkdong

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TF-IDF(Term Frequency-Inverse Document Frequency)是一种常用于信息检索与文本挖掘的算法,用于评估一个词对于一篇文档或一个语料库的重要程度。 在Java实现TF-IDF算法可以借助一些常用的开源库,例如: 1. Lucene Lucene是一个全文检索引擎的Java实现。它提供了一个非常完整的文本搜索和分析库,可以方便地实现TF-IDF算法。Lucene具有良好的性能和可扩展性,并且有广泛的社区支持。 2. Apache Commons Math Apache Commons Math是一个常用的Java数学库,其中包含了计算TF-IDF所需的一些基本数学函数,例如对数函数和向量运算函数。使用Apache Commons Math可以方便地实现TF-IDF算法。 3. Stanford CoreNLP Stanford CoreNLP是斯坦福大学开发的一个Java自然语言处理库。它提供了丰富的文本处理功能,包括词性标注、分词、命名实体识别、依存分析等。使用Stanford CoreNLP可以很方便地对文本进行预处理,然后计算TF-IDF值。 下面是一个使用Lucene实现TF-IDF算法的示例代码: ```java import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.Term; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.RAMDirectory; public class TfIdfDemo { public static void main(String[] args) throws Exception { // 创建分析器 Analyzer analyzer = new SmartChineseAnalyzer(); // 创建索引 Directory directory = new RAMDirectory(); IndexWriterConfig config = new IndexWriterConfig(analyzer); IndexWriter writer = new IndexWriter(directory, config); Document doc1 = new Document(); doc1.add(new TextField("content", "我们是好朋友", Field.Store.YES)); writer.addDocument(doc1); Document doc2 = new Document(); doc2.add(new TextField("content", "我们是同学", Field.Store.YES)); writer.addDocument(doc2); Document doc3 = new Document(); doc3.add(new TextField("content", "我们是同学和好朋友", Field.Store.YES)); writer.addDocument(doc3); writer.close(); // 计算TF-IDF值 IndexReader reader = DirectoryReader.open(directory); IndexSearcher searcher = new IndexSearcher(reader); Query query = new TermQuery(new Term("content", "好朋友")); TopDocs topDocs = searcher.search(query, 10); double tf = 1.0 / 3; double idf = Math.log(3.0 / (double)(topDocs.totalHits + 1)); System.out.println("TF-IDF值为:" + tf * idf); } } ``` 这段代码使用Lucene创建了一个包含三个文档的索引,然后计算了包含“好朋友”这个词的文档的TF-IDF值。其中,tf表示该词在文档中出现的频率,idf表示该词在整个语料库中的逆文档频率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值