论文查重
一、代码链接
GitHub (点击链接可查看完整代码)
二、计算模块接口的设计与实现过程
首先,先呈上我的设计思路及流程图:
从流程图中可以看出主要有六个部分的内容。
(1)文本的读入:
事实上,我第一眼看到"命令行参数"时是很懵的,这个词听到过很多次,但实际自己并没有真正使用过命令行参数(说来属实惭愧),但经过不断地翻阅博客与向同学请教,我弄懂了如何使用命令行参数进行文件的读取:
(2)分词:
对文本进行分词可以这样简单理解:
例句:今天晚上我看电影 变为:今天 晚上 我 看 电影
在这里我最终直接采用了python库中jieba.cut()
函数并结合停用词对文本进行分词。
(3)字典映射以及构成词频矩阵:
我将分好的词在函数word_materix()
中进行字典映射,以及形成词频矩阵以方便进行计算每个TF-IDF值
(4)(5)计算TF-IDF与余弦相似度:
利用TF-IDF以及余弦相似度计算文本重复率是我的设计思路中的核心,利用TF-IDF找出两篇文章的关键词,再结合余弦相似度计算得到两个文本的相似率。
实际上在此之前我有尝试过LSI算法,但最终LSI似乎对我来说有点困于理解?在看了很多博客后理解得还是不是特别透彻。(希望自己在今后的学习过程中能够进一步学习LSI算法)
关于TF-IDF和余弦相似度是什么以及二者怎样计算可参考网上大佬的讲解,浅显易懂呀:
TF-IDF与余弦相似性的应用(二)
以下是二者的数学计算公式:
(6)输出重复率:
如果最初文本的读入解决了,那么这一步也就相应解决了
主要的函数:
其实我觉得每个函数都挺重要的,环环相扣(都花了我不少时间去码和在网上找资料),不过最最最最重要的应该是:
tf_idf()
:计算得到每个词的TF-IDF值
cos()
:计算余弦相似度
三、计算接口部分的性能改进
性能分析与优化:
采用了PyCharm的性能分析工具,得到最终的性能分析图:
在这之中消耗最大的函数是:
时间优化:
在作业最终版本出来以前,源代码测试10个样例实际花费时间为:
emmm,别人花费2~6秒解决的问题,我花费了30多秒!属实有点吓人(差点吐血)。
于是尝试利用单元测试测试各个函数,发现时间花费最严重的是cut()
(用于分词的函数),该函数中我调用了jieba.posseg.cut()
进行分词,后尝试改为调用jieba.cut()
后,时间消耗猛减!
经过对比分词效果发现好像对效果没什么大的影响,于是果断选择后者。(在经过上网百度、翻阅各个博客后对解答“jieba.posser.cut()
为什么消耗那么多时间?“一问无果后,打算去请教老师同学,有进展将更新在本博评论中)
最后我进而对一些细小的内容进行修改,时间变为:
四、计算模块部分单元测试展示:
在此次作业之前一直没有接触过单元测试,翻阅各个博客知道了unittest
模块。
展示main_test.py
中main_solve()
函数:
def main_solve(orig_position, copy_position, ans_position):
orig = open(orig_position, 'r', encoding='UTF-8')
text1 = orig.read()
orig.close()
copy = open(copy_position, 'r', encoding='UTF-8')
text2 = copy.read()
copy.close()
# 空文本检测
if text1 == '':
raise NowordError
if text2 == '':
raise NowordError
res1, res2 = cut(text1, text2) # 返回第一个文本和第二个文本切词后的结果
corpus = [res1, res2]
matrix, dictionary = word_materix(corpus)
tfidf_matrix = tf_idf(matrix)
sim = str('%.2f' % cos(tfidf_matrix))
ans = open(ans_position, 'w', encoding='UTF-8')
ans.write(sim)
ans.close()
print('查重结果为:', sim)
展示unit_test.py
中部分内容(不全):
# coding:utf-8
import unittest
import main_test
class test_main(unittest.TestCase):
def setUp(self):
print("开始测试:")
def tearDown(self):
print("测试结束")
def test_orig(self):
print("正在测试orig.txt的查重率")
main_test.main_solve('sim_0.8orig.txt', 'sim_0.8orig.txt', 'ans.txt')
'''
def test_nowords(self):
print("正在进行空文本异常检测")
main_test.main_solve('sim_0.8orig.txt', 'sim_0.8orig_nowords.txt', 'ans.txt')
'''
def test_mydata0(self):
print("正在进行mydata_hair的文本相似度检测")
main_test.main_solve('sim_0.8mydata_hair0.txt', 'sim_0.8mydata_hair1.txt', 'ans.txt')
if __name__ == '__main__':
unittest.main()
测试覆盖率截图:
五、计算模块部分异常处理说明
检测输入为空文本文档异常:
得到输出结果:
六、PSP表格
PSP是卡耐基梅隆大学(CMU)的专家们针对软件工程师所提出的一套模型:Personal Software Process (PSP, 个人开发流程,或称个体软件过程)。
PSP.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 50 |
Estimate | 估计这个任务需要多少时间 | 40 | 40 |
Development | 开发 | 540 | 500 |
Analysis | 需求分析 (包括学习新技术) | 400 | 450 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 | 30 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 50 | 60 |
Design | 具体设计 | 60 | 70 |
Coding | 具体编码 | 400 | 450 |
Code Review | 代码复审 | 45 | 40 |
Test | 测试(自我测试,修改代码,提交修改) | 200 | 220 |
Reporting | 报告 | 100 | 90 |
Test Repor | 测试报告 | 100 | 100 |
Size Measurement | 计算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 60 | 45 |
合计 | 2135 | 2195 |
个人总结
不得不说,这次的个人编程让我收获了特别特别特别特别多,把学习python的进度一下子拉了上来;懂得了完成一个项目不仅仅只是码代码,还有单元测试、性能分析、优化等等(惨痛经验告诉我们这些真的很重要!);让我实实在在体会到了第一次博客作业中的提及的熬夜;提升了查找资料的速度与技巧。
最后想要感谢在这次个人编码作业完成过程中被我不断”骚扰“的朋友和同学,十分感谢大家对我的帮助与解答!