zoukankan      html  css  js  c++  java
  • 文本去重第一步:基于内容的文本相似性计算

    http://yshjava.iteye.com/blog/1560661

    为何要计算文档相似性

          在今年年初的时候,我开始尝试做文本的自动聚类,当时是从网上,找到的一个K-Means算法,稍作了修改。从测试结果来看,分类效果 不太好,究其原因,我认为有两个,一个是词库的问题,停用词词库太小,没有噪音词库,也没有近义词词库,最关键的是切出来的词,统计的TFIDF权重不准 确,第二个原因则是计算某文档与目标类别的相似度的算法不够合理。第一个问题经过两天多的尝试,于昨日解决了,剩下了第二个问题,真是让人头疼。
    本来我已打算放一阵子的,但就在前几天Merry跟我讲了他文本去重的原理和一些细节问题,让我又重新燃起了希望。同时我也认为,计算文档相似度,不仅能够为去重提供重要依据,稍后也可以在文本分类/聚类上有所作为,于是,我打算抽一点点时间,去尝试一下。 

     

     

     

    算法模型

     算法的模型,可以简单描述为:

    1、加载与将要分析的文档无关的TFIDF词库、停用词库;
    2、假设我们得到的是两篇正常的文档,首先切词,去除停用词;
    3、抽取两篇文档中的公共词汇,计算它们的TFIDF权重和;
    4、分别计算两篇文档的TFIDF权重,即每篇文档中所有词汇的TFIDF和;
    5、使用公共词汇的权重分别对两篇文档的权重求模,并计算它们的乘积;
    6、乘积即为两篇文档的相似度;

    算法的理论依据是,TFIDF权重越高的词,其在文章中代表意义就越大,由此,假设我们拥有了一个标准的TFIDF词库,那么我们就可以在将文章分 词后,将其向量化,并加权后虚拟成一个面积,两篇文章公共的部分,也可以虚拟成一个面积值,根据概率论的概率分布理论,公共部分在两个面积中出现的概率的 乘积,即为二者的相似程度。

    算法代码

    Java代码  收藏代码
    1. /* 
    2.  * To change this template, choose Tools | Templates 
    3.  * and open the template in the editor. 
    4.  */  
    5. package cn.ysh.studio.text.cluster.main;  
    6.   
    7. import cn.ysh.studio.text.cluster.TFIDFHelper;  
    8. import cn.ysh.studio.text.cluster.core.Dictionary;  
    9. import cn.ysh.studio.text.cluster.core.Document;  
    10. import cn.ysh.studio.text.cluster.utils.FileHelper;  
    11. import java.io.File;  
    12. import java.io.FileNotFoundException;  
    13. import java.io.IOException;  
    14.   
    15. /** 
    16.  * 计算两篇文档的相似度 
    17.  * 
    18.  * @author 杨胜寒 
    19.  */  
    20. public class SimpleComputeSimilarity {  
    21.   
    22.     public static float repeatValue(Document doc1, Document doc2) {  
    23.         float keywordTFIDF = 0.0f;  
    24.         float doc1TFIDF = 0.0f;  
    25.         float doc2TFIDF = 0.0f;  
    26.         for (String word : doc1.getContentTerms().keySet()) {  
    27.             if (doc2.getContentTerms().containsKey(word)) {  
    28.                 keywordTFIDF += doc1.getContentTerms().get(word);  
    29.             }  
    30.             doc1TFIDF += doc1.getContentTerms().get(word);  
    31.         }  
    32.         for (String word : doc2.getContentTerms().keySet()) {  
    33.             doc2TFIDF += doc2.getContentTerms().get(word);  
    34.         }  
    35.         return (keywordTFIDF / doc1TFIDF) * (keywordTFIDF / doc2TFIDF);  
    36.     }  
    37.   
    38.     public static void main(String[] s) throws FileNotFoundException, IOException {  
    39. //        String docPath1 = "F:\Workspaces\NetBeansTest\TextCluster\txt\洛阳空气质量差环保部门被批 环保局向市民道歉.txt";  
    40. //        String docPath2 = "F:\Workspaces\NetBeansTest\TextCluster\txt\洛阳空气质量差环保局公开道歉 细说原因对策.txt";  
    41.         String docPath1 = "F:\Workspaces\NetBeansTest\TextCluster\txt\英美媒体:美国暂时对南海争端避而远之.txt";  
    42.         String docPath2 = "F:\Workspaces\NetBeansTest\TextCluster\txt\美媒:黄岩岛争端结束中国获胜 美只求自由通航.txt";  
    43.         Document doc1 = FileHelper.loadDocument(new File(docPath1));  
    44.         Document doc2 = FileHelper.loadDocument(new File(docPath2));  
    45.         Dictionary.getInstance().loadDictionary("F:\Workspaces\NetBeansTest\TextCluster\自由自在词典.dic");  
    46.         Dictionary.getInstance().loadStopDictionary("F:\Workspaces\NetBeansTest\TextCluster\txt\stopwords.txt");  
    47.         long start = System.currentTimeMillis();  
    48.         TFIDFHelper.tfidf(new Document[]{doc1, doc2});  
    49.         float repeatValue = SimpleComputeSimilarity.repeatValue(doc1, doc2);  
    50.         long end = System.currentTimeMillis();  
    51.         System.out.println("相似值:" + repeatValue + ",用时[" + (end - start) + "]毫秒!");  
    52.     }  
    53. }  

    测试结果截图:

    测试中使用到两篇文档来自百度新闻,在附件中有,感兴趣的同学可以看一下内容,然后评判上述结果是否准确。

    使用上述算法,对数据库中的18609篇新闻资讯进行相似度计算,输出相似度大于0.5的资讯的信息。截图如下:

     

    算法优劣

    相 似度计算的算法极为简单,但是对依赖的词典要求很高,算法中使用的"自由自在词典.dic"是作者的另外一个工具根据爬虫收集的海量资讯信息抽取好统计出 来的,包含了词汇及其TF、IDF权重值,旨在为分析器提供一个中立的、与被分析文档无关的TF/IDF权重词库。附件中顺便提供了一份小的词典样例,随 着分析工具分析资讯信息的数量的不断增加,词库也将不断扩大。

    个人总结

    虽然目前来看,效果还可以,但是我认为还有以下几个方面应该改进:
    1、扩大停用词库,增加噪音词库,降低无用词汇的干扰;
    2、扩大TFIDF词库,同时标注词性,我认为特殊词性的词汇在不同场合应该特殊处理,如名词、动词和专用词汇在相似性计算中应该被加权;
    3、增加近义词库和转换词库(比如美方=美国,华盛顿=美国,北京=中国,叙=叙利亚等等),据我预测,在多数场合中,合并近义词、转换词可以提高计算结果的精确度;

    好吧,就先总结这么多吧,希望能够抛砖引玉,为大家提供一点思路。

  • 相关阅读:
    范围截取 字符串内容
    post请求 application/x‐www‐form‐urlencoded
    未能加载文件或程序集“Newtonsoft.Json”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)
    获取Url链接后的问号传值中的参数
    Post 提交跳转页面 Jquery请求
    C# POST application/x-www-form-urlencoded 请求
    《exception》第九次团队作业:Beta冲刺与验收准备(大结局)
    《Exception》第八次团队作业:Alpha冲刺
    《Exception团队》第七次作业:团队项目设计完善&编码
    《Exceptioning团队》第六次作业:团队项目系统设计改进与详细设计
  • 原文地址:https://www.cnblogs.com/timssd/p/5163239.html
Copyright © 2011-2022 走看看