这是文本离散表示的第二篇实战文章,要做的是运用TF-IDF算法结合n-gram,求几篇文档的TF-IDF矩阵,然后提取出各篇文档的关键词,并计算各篇文档之间的余弦距离,分析其相似度。
TF-IDF与n-gram的结合可看我的这篇文章:https://www.cnblogs.com/Luv-GEM/p/10543612.html
用TF-IDF来分析文本的相似度可看阮一峰大佬的文章:http://www.ruanyifeng.com/blog/2013/03/cosine_similarity.html
本文用hanlp进行分词,hanlp比jieba安装起来复杂,网上的安装教程也没看到比较好的,我会附在本文的结尾。
1、文档说明
这次从网上找了三篇文档,都是关于新任证监会主席易会满“首秀”的。前两篇都是偏事实性的新闻报道,第三篇是侠客岛的评论文章,之所以找三篇是为了进行对比。每个篇报道都保存为了一篇txt文档,一共3篇txt文档。
文档的原网页:
1、https://baijiahao.baidu.com/s?id=1626615436040775944&wfr=spider&for=pc
2、https://baijiahao.baidu.com/s?id=1626670136476331971&wfr=spider&for=pc
3、http://finance.sina.com.cn/roll/2019-02-28/doc-ihrfqzka9798377.shtml
2、实战内容
第一步是对分词、清洗文本并生成3-gram:使用hanlp对每篇文档进行分词,根据词性和运用正则表达式,过滤停用词和特殊符号,然后对每篇文档都生成3-gram的集合。
第二步是计算TF-IDF矩阵,提取各篇文档的top30的3-gram关键词,并生成3张词云图:这里用到sklearn来计算TF-IDF矩阵,然后用wordcloud库画词云图进行可视化。
第三步是计算三篇文档的文本相似度:将各篇文档的关键词合并为一个词汇表,统计各篇文档相对于该关键词词汇表的词频矩阵,然后两两计算文档的余弦距离。
下图来自于阮一峰的博客,介绍了计算文本相似度的流程:
看起来比较简单是不是?其实还是涉及到了很多小技巧,一起来看看吧!
这里先放出完整的代码,代码的说明比较简洁,先大致看看就行,下面会把代码拆成一段一段来说明详细说明我做这个任务的过程。
代码、文档和词云图可去我github主页下载:https://github.com/DengYangyong/TF-IDF_txt_similarity
一、文本的分词、清洗和生成3-gram
首先导入需要的各种库。
三篇文档都保存为了txt文档,在cnews这个目录下。于是从主函数开始读取三篇文档,每篇文档的内容都放在一个列表中,所以列表有三个元素。列表的第一行对应第三个网页,第三行对应第一个网页的内容。
第二列的内容大致是,['证券日报 ', '02-2808:25 ', '易会满首秀“施政理念” 聚焦“市场化” ', '■董文 ', '昨天,证监会主席易会...],本身也是一个列表,元素为txt文档中的每一行文本。
从第二列元素可见,读入的文本中有大量的数字,换行符和其他特殊字符,需要清洗掉。而且,为了后续处理方便,要把列表中的每行文本拼接起来。
定义了两个正则表达式,然后这里用到了第一个正则表达式,去掉除数字、字母和中文以外的其他字符。第二个正则表达式在后面才用于去掉数字。这里先不去掉数字,在生成3-gram时再去掉,一会就知道为什么了。
最后得到的结果是 ['解局易会满...', '证券日报...', '信息量巨大易会满首秀直面科创板...'] 这样的列表,即每篇文档被弄成了一整个字符串,列表中有三个字符串。
好,接下来用hanlp进行分词,首先配置好调用hanlp的路径,导入Tokenizer这个类。看起来复杂,都是套路,这个在后面的安装和使用中会简单介绍一下。
然后开始分词,为了看起来简洁,定义了一个分词函数,然后在主函数部分引用。
这里通过词性标注来进行分词和过滤停用词。为什么要搞得这么麻烦,jieba直接分词不就得了吗?我认为通过这种方法可以根据自己的需要更灵活地去掉自己不想要的词,即通过词性来去掉。
drop_pos_set是停用词词性表,每个词性代表的意思可以看中科院计算所的词性标注集,网页在这里:http://ictclas.nlpir.org/nlpir/html/readme.htm
接下来,生成3-gram并去掉数字。这里说明三点:
一是这里的3-gram并不包含单个词(如解局),而是2个词或3个词成一个单元,词之间用下划线连接起来(如 解局_易会满,新任_证监会_主席),这是为了克服计算单个词的TF-IDF的问题,即会忽略词的前后信息。
理论上3-gram是会包含单个词,但这里我还是把单个词去掉。
二是数字在这里去掉,举个例子就明白了,比如[今天, 2, 月, 27, 日, 下午],如果先去掉数字再3-grm,就会有[今天_月,月_日] 这种单元,明显是没有意义的,应该把[2,月], [27, 日] 整个去掉。 所以在生成3-gram时连同数字的前后词一起去掉。
去掉数字用到了上面pattern1这个正则表达式。
三是每个单元之间用空格连接起来:''解局_易会满 易会满_首 首_秀',这是方便下面输入到sklearn中进行计算。这就类似于英文句子'The cat is so cute',单词之间用空格隔开。
doc的结果是:['解局_易会满 易会满_首 首_秀 秀_今天 日_下午...', '...', '...'],有三个元素,每个元素是一篇文档的3-grm连成的字符串。
二、计算TF-IDF矩阵和提取关键词
根据上面3-gram的输出doc,去求词频和TF-IDF矩阵。sklearn的计算原理是把3篇文档的3-gram去重后,得到8519个词汇,做成一个词汇表,基于这个词汇表计算词频和TF-IDF。
freq.toarray()和 tfidf.toarray() 分别可以得到词频矩阵和TF-IDF矩阵。
有了每篇文档的词频和TF-IDF矩阵,是不是可以直接求余弦距离,得出文本相似度了呢?还不行,想想看,这个矩阵太大了,数据过于稀疏,会对结果造成不好的影响。
要基于关键词词汇表计算词频矩阵,开头的那张图里已经写明白了。在提取关键词之前,先做准备工作,得到含8519个词汇的词汇表和每个词的索引。
词汇表和索引是这样的:{7257: '解局_易会满', 5137: '易会满_首', 8451: '首_秀', 6516: '秀_今天',..},这里是键值反转之后的词汇表,是为后面根据索引得到关键词而准备的。
下面这段代码是提取出每篇文档的TOP30关键词,因为都是自己造轮子,所以看起来比较复杂。大致的思路就是:得到每篇文档中每个词汇的在词汇表中对应的索引和TF-IDF值,形如(7557, 0.2459),然后按照TF-IDF值进行排序;得到排序后的索引列表后,根据索引在词汇表字典中取到相应的词,然后取前30个作为关键词。
得到的结果:[['资本_市场', '科创_板', '注册_制', '好_企业', ...],['资本_市场', '科创_板', '注册_制', '易会满_表示'...],['资本_市场', '科创_板', '上_表示', '新闻发布会_上_表示'...]], 可见资本市场,科创板,注册制是关键的一些词。
为了更形象,用词云图进行可视化。这里定义了一个函数,用来生成词云图,一共生成了三张词云图,背景图片是一头牛。
背景图片以及词云图如下:
三、基于关键词统计词频和计算余弦距离
终于要进行文本相似度分析啦!这一步先把3篇文档的关键词合并成一个集合,去掉重复后得到74个关键词,构成一个词汇表。然后得到3篇文档相对于这个词汇表的词频矩阵。
得到词频矩阵后,再两两计算余弦距离。对照我们的词频矩阵, Ai表示第一篇文章第i 个词的词频,Bi表示第二篇文章第i个词的词频。这里调用了scipy的包来计算。
最后得到的余弦距离是第1/2,1/3,2/3 篇文档的余弦相似度为[0.83047182,0.7130633,0.81106869],看来侠客岛的那篇文章(列表第一行,网页第三篇)和第二篇文档(网页第二篇)的相似度最高,和第一个网页上的文档相似度最低。
到此,这个小任务就完成了。
四、hanlp的安装
hanlp是个java工具包,是上海外国语大学日本文化经济学院的小哥哥凭一己之力写出来的,工具包里词性标注、命名实体识别、自动摘要,HMM、CRF、textrank,等很多功能和算法都有,非常佩服,向小哥哥致敬!
hanlp提供了python的接口,我看很多安装教程是直接:
1、Hanlp环境安装
我的操作系统是:ubuntu18.04
(1)安装Java和Visual C++: 我装的是Java 1.8和Visual C++ 2015,
(2)安裝Jpype:conda install -c conda-forge jpype1
(3)测试是否按照成功
2、Hanlp安装
(1)下载hanlp.jar包: https://github.com/hankcs/HanLP
(2)下载data.zip:https://github.com/hankcs/HanLP/releases中http://hanlp.linrunsoft.com/release/data-for-1.7.0.zip后解压数据包。
(3)配置文件:修改示例配置文件: hanlp.properties,配置文件的作用是告诉HanLP数据包的位置,只需修改第一行: root=usr/home/HanLP/,比如data目录是
/Users/hankcs/documents/data,那么root=/Users/hankcs/documents/
3、Hanlp调用
调用之前先输入以下的代码,给hanlp分配调用的路径,然后整个程序都运行完后,用 shutdownJVM() 来关闭。
参考资料:
1、TF-IDF 文本相似性分析:
https://blog.csdn.net/worryabout/article/details/79792880
2、计算所词性标记集:
http://ictclas.nlpir.org/nlpir/html/readme.htm
3、词云图:
https://www.cnblogs.com/derek1184405959/p/9440526.html
4、计算距离:
以上就是本篇文章【文本离散表示(三):TF-IDF结合n-gram进行关键词提取和文本相似度分析】的全部内容了,欢迎阅览 ! 文章地址:http://dfvalve.xrbh.cn/news/2806.html 资讯 企业新闻 行情 企业黄页 同类资讯 首页 网站地图 返回首页 迅博思语资讯移动站 http://keant.xrbh.cn/ , 查看更多