项目源码: https://github.com/zhang2172268/mygit/tree/master/textSimilarity/textSimilarity
文本
- 原理(基于词频):统计词频,构建词频特征向量,利用特征向量夹角余弦表示文本相似度。
统计文本中每个词出现的次数,即词频,通过词频构建文本向量,通过计算两个文本向量之间的余弦相似度,反映两个文本之间的相似度;这类算法也有缺点,没有很好地解决文本数据中存在的自然语言问题,即同义词和多义词。 - 文本分词->去掉停用词->统计词频->构建词频向量->计算余弦相似度
分词
第一步进行文本分词
词是最小的能够独立活动的有意义的语言成分,英文单词之间是以空格作为自然分界符的,而汉语是以字为基本的书写单位,词语之间没有明显的区分标记,因此中文是一定要分词的。
- 基于jieba分词第三方库。
- 介绍一下jieba第三方库所用到的算法。
- 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG);
- 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合;
- 对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法。
- 我主要是用这个库来实现文本的精确分词,接着拿到这些词的出现的频率,构建基于词频的特征向量。通过特征向量借助多种算法来求文本相似度。
- 注:在linux下编码方式是UTF-8的,但是在windows下编码方式是GBK的;但是jieba 分词只支持UTF-8编码方式,因此我在windows下VS中使用jieba 时,要先将词的编码方式进行转换。
第二步去掉停用词
人类语言包含很多功能词。与其他词相比,功能词没有什么实际含义。 停用词主要包括数字、标点符号及使用频率特高的词(代词,语气助词、副词、介词、连接词 )等。
我
我们
怎么办
总之
此外 然而 不如 不妨 。 , ?
…
停用词不代表实际意义,所以不需要统计停用词的词频,停用词不参与构建词频向量。
统计词频
第三步统计词频
- 词频
- 词频即为单词在文章中出现的次数。
- 词频的大小一般可以反映一个词在一篇文章中的重要性,词频越大,可以认为该词越重要。
- 一篇文章的语义可以由一组关键词简要概括,比如"今天早上八点钟,我要去教室上课",关键词"八点,教室,上课"。
- 分词编码
- 在构建文本词频向量时,需要考虑向量的意义,也必须保证向量的一致性,这样才有可比性。
- 意义:文本的语义,用词频来表示
一致性:如何保证一致性?向量中的每一维值都应该表示相同的意思。
更具体的说,一致性就体现在两个文本向量的每一维都应该表示同一个词的词频。
举个例子:
文档1:今天/有事/,/没办法/去/教室/上课/了
文档2:真想/去/教室/上课/,/但是/今天/有事/,/去不了/教室/了
文档1中的词频:[今天:1,有事:1,没办法:1,去:1,教室:1,上课:1,了:1]
文档2中的词频:[真想:1,去:1,教室:2,上课:1,但是:1, 今天:1,有事:1,去不了:1,了:1]
- 去掉停用词之后:
文档1中的词频:[有事:1,没办法:1,去:1,教室:1,上课:1]
文档2中的词频:[真想:1,去:1,教室:2,上课:1, 有事:1,去不了:1]- 直接用上述词频构建每一个文本的词频向量无意义,每一维表示的意思不同,两个向量没有可比性。
- 构建一致的词频向量:给每一维的词频编码,然后去看每一维的词频向量。
- 把两个文本中的所有有效词全部编码,对于长文本可以按词频从大到小排序,取前n个关键词按照码值构建词频向量.
比如:
文档1中的词频:[有事:1,没办法:1,去:1,教室:1,上课:1]
文档2中的词频:[真想:1,去:1,教室:2,上课:1, 有事:1,去不了:1]
所有有效词:比特,去,真想,上课,有事,去不了,没办法
给所有有效词编码:教室:0,去:1,真想:2,上课:3,有事:4,去不了:5,没办法:6
词频向量
第四步统计词频向量
通过上述词的编码值,构建词频向量
文档1中的词频:[0:1,1:1,2:0,3:1,4:1,5:0,6:1]
文档2中的词频:[0:2,1:1,2:1,3:1, 4:1,5:1,6:0]
文档1词频向量:[1,1,0,1,1,0,1]
文档2词频向量:[2,1,1,1, 1,1,0]
相似度计算
第五步计算余弦相似度
余弦相似度,是通过计算两个向量的夹角余弦值来评估他们的相似度:
其它常用计算向量相似度的方式:欧几里得距离,jaccard系数(类似余弦相似度),曼哈顿距离(类似欧几里得距离)。
应用
论文检测,文本分类。