1-2计算模块接口的设计与实现过程。
刚开始查阅资料的时候先找到的是simhash函数,在用自己的文本进行初步测试时发现得出的测试结果不忍直视,就放弃了。然后又看到了评价很好的TF-IDF模型,可是自己查重效果也不太好,原因是语料库不够多,没有足够的训练样本,不适用于这种一对一文档对比。还有看到其他几种方法,总会出现一些能力之外的错,最后终于找到简单易懂的余弦算法
1.第一步肯定是简单地读取文档
2.接下来就是处理文本,这里我选择了最简单也适合我的jieba分词,不禁感叹python的方便
3.分词完就是可以用各种方法进行计算了
4.最后在指定路径输出结果
(1)找出两篇文章的关键词
(2)每篇文章各取出若干个关键词,合并成一个集合,计算每篇文章对于这个集合中的词的词频
(3)生成两篇文章各自的词频向量
(4)计算两个向量的余弦相似度,值越大就表示越相似。
这里我主要定义了三个函数:
1.去标点符号
2.建立词袋模型
3.余弦相似度的计算
1-3计算模块接口部分的性能改进。
1.标点符号的去除,效果还是有的
2.cos方法在计算短文本重复率有较好的性能,而在计算长文本容易结果偏高(如下图)
(ps:因为为了更好地观察文本相似度,这一步骤没有取小数点后两位)
改进:不再直接用jieba分词处理后的文本建立词典,而是通过提取关键词来建立词典(这次的结果就比较符合预期了)
3.关键词数的选择对结果影响很大,但是对于一篇文档重要的词数不容易确定(有些精炼,有些啰嗦)
(因为想展示关键词的影响,所以在词数选择时选择了比较极端的情况(极大和极小))
想法:我是比较想用去除自定义停用表的方法,但是因为不能读写其他的文件,就只能pass了。
从总时间来看,2.5s,要求以内(毕竟余弦虽然准确率没有其他方法高,但是好歹跑的快)
1-4计算模块部分单元测试展示。
import codecs import re import jieba.analyse import math #去除文本内的空格、中文标点符号 def del_reg(filename): reg = "[^0-9A-Za-z\u4e00-\u9fa5]" file_content = re.sub(reg, '', filename) return file_content #建立词袋模型,将中文词语降维成二维向量 def code(keyword, dictionary): array = [0] * len(dictionary) for content in keyword: array[dictionary[content]] += 1 return array #通过计算两个向量的余弦距离来求文本相似度 def cos(vector1, vector2): vector_sum = 0 fq1 = 0 fq2 = 0 for content in range(len(vector1)): vector_sum += vector1[content] * vector2[content] fq1 += pow(vector1[content], 2) fq2 += pow(vector2[content], 2) try: answer = round(float(vector_sum) / (math.sqrt(fq1) * math.sqrt(fq2)), 3) except ZeroDivisionError: answer = 0.0 return answer #encoding='utf-8' #file_path1 = input("文件1路径:") #file_path2 = input("文件2路径:") file_path1='sim_0.8/orig.txt' fileList=['sim_0.8/orig.txt', 'sim_0.8/orig_0.8_add.txt', 'sim_0.8/orig_0.8_del.txt','sim_0.8/orig_0.8_dis_1.txt', 'sim_0.8/orig_0.8_dis_3.txt','sim_0.8/orig_0.8_dis_7.txt','sim_0.8/orig_0.8_dis_10.txt', 'sim_0.8/orig_0.8_dis_15.txt','sim_0.8/orig_0.8_mix.txt','sim_0.8/orig_0.8_rep.txt'] for r in range(0,10): file1 = codecs.open(file_path1, mode='r', encoding='utf-8').read() file2 = codecs.open(fileList[r], mode='r', encoding='utf-8').read() file1 = del_reg(file1) file2 = del_reg(file2) #提取文本里的关键词 keyword1 = jieba.analyse.extract_tags(file1, topK=200, withWeight=False) keyword2 = jieba.analyse.extract_tags(file2, topK=200, withWeight=False) #将文档1和文档2提取到的关键词合并成一个集合 word_set = set(keyword1).union(set(keyword2)) #建立一个词典 word_dict = dict() i = 0 #将两篇文章出现的关键词存入到字典里 for word in word_set: word_dict[word] = i i += 1 file1_code = code(keyword1, word_dict) file2_code = code(keyword2, word_dict) result = cos(file1_code, file2_code) print("文档1和文档%d的相似度是:%.2f" % (r+1, result))控制台输出结果如下:
输出结果还是可以接受的吧,至少不是毫无区分度。
1-5计算模块部分异常处理说明。
1.当给出路径不存在可以读取的文件时:
2.当进行余弦计算时出现0:
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 80 |
Estimate | 估计这个任务需要多少时间 | 10 | 20 |
Development | 开发 | 40 | 60 |
Analysis | 需求分析 (包括学习新技术) | 300 | 360 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 | 10 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 60 |
Design | 具体设计 | 40 | 40 |
Coding | 具体编码 | 240 | 300 |
Code Review | 代码复审 | 60 | 120 |
Test | 测试(自我测试,修改代码,提交修改) | 40 | 100 |
Reporting | 报告 | 60 | 60 |
Test Repor | 测试报告 | 40 | 50 |
Size Measurement | 计算工作量 | 60 | 40 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 60 | 40 |
合计 | 1010 | 1390 |
刚开始看到这个题目,完全不理解应该怎么做,但是一步步摸索,一步步去看大佬的代码,自己就有思路了,虽然依旧比较粗糙,但是收益颇丰。