个人项目
个人项目
作业课程 | 软件工程 |
---|---|
作业要求 | 作业要求 |
作业任务 | 设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。 |
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | 600 | 480 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 90 | 60 |
· Design Spec | · 生成设计文档 | 20 | 20 |
· Design Review | · 设计复审 | 10 | 10 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 20 |
· Design | · 具体设计 | 60 | 40 |
· Coding | · 具体编码 | 180 | 120 |
· Code Review | · 代码复审 | 60 | 30 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 90 |
Reporting | 报告 | ||
· Test Repor | · 测试报告 | 90 | 60 |
· Size Measurement | · 计算工作量 | 10 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
· 合计 | 630 | 480 |
接口的设计与实现过程
流程图:
项目目录:
说明:
- SimHash算法简介:SimHash算法是Google在2007年发表的论文《Detecting Near-Duplicates for Web Crawling》中提到的一种指纹生成算法,被应用在Google搜索引擎网页去重的工作之中。
简单的说,SimHash算法主要的工作就是将文本进行降维,生成一个SimHash值,也就是论文中所提及的“指纹”,通过对不同文本的SimHash值进而比较海明距离,从而判断两个文本的相似度。这个算法主要有以下几个步骤:- 分词:对给定的一段文本进行分词,产生n个特征词,并赋予每个特征词一个权重。比如一段文本为“中国科大计算机系的学生的能力怎么样”,产生的特征词就应该是“中国科大”、“计算机系”、“的”、“学生”、“能力”、“怎么样”,然后对这些词分别赋予权重,假设有1-5五个分类,分词之后以上五个词便会各有一个权重,比如中国科大(4)、计算机系(3)、的(1)、学生(4)、能力(5)、怎么样(3)。
其中,数字越大,代表特征词在句子中的重要性就越高。这样,我们就得到了一个文本的分词的词向量和每个词向量对应的权重 - 求哈希值:通过哈希函数对每一个词的向量进行映射,产生一个n位二进制字符串。
- 加权:hash二进制串中为1的乘以该特征词的分词权重,二进制串中为0的乘以该特征词的分词权重后取负,继而得到权重向量
- 合并:计算出文本分词的每个向量之后,将所有词向量的权重向量相累加,得到一个新权重向量
- 降维:对于前面合并后得到的文本的权重向量,大于0的位置1,小于等于0的位置0,就可以得到该文本的SimHash值。
- 海明距离:简单的说,海明距离可以理解为,两个二进制串之间相同位置不同的个数。举个例子,[1,1,1,0,0,0]和[1,1,1,1,1,1]的海明距离就是3。
- 分词:对给定的一段文本进行分词,产生n个特征词,并赋予每个特征词一个权重。比如一段文本为“中国科大计算机系的学生的能力怎么样”,产生的特征词就应该是“中国科大”、“计算机系”、“的”、“学生”、“能力”、“怎么样”,然后对这些词分别赋予权重,假设有1-5五个分类,分词之后以上五个词便会各有一个权重,比如中国科大(4)、计算机系(3)、的(1)、学生(4)、能力(5)、怎么样(3)。
参考资料:https://blog.csdn.net/Daverain/article/details/80919418
-
主类:DuplicateCheck.java 用于启动整个项目
-
工具类:
- CalculateUtils:用于将字节数组转换成二进制字符串,求哈希值和SimHash值等
- HammingUtils:用于计算汉明距离和相似度
- IOUtils:用于读写文件
-
测试类
-
外部依赖:
-
汉语言处理包,用于对文本进行分词、处理停用词等
用于Java的官方文档:https://github.com/hankcs/HanLP/tree/1.x -
Junit,用于单元测试
-
计算模块接口部分部分的性能改进
实时内存分析图
调用树
方法的性能情况
可以看到消耗最大的方法是getSimHash,原因是在求simHash时需要通过循环进行哈希值的补位、加权合并和降维,同时也要调用jdk API中开销较大的charAt()方法,同时从实时内存分析图中可以看出占用内存较大的是导入的HanLP语言处理包,故逻辑方面没有什么可以优化的点。
计算模块部分单元测试展示
测试每个工具类中的方法(传入的都是常规且合法的数据,异常处理会在下面说明)
CalculateUtils
HammingUtils
IOUtils
主类测试
测试乱序对于汉明距离的影响
测试结果
覆盖率
计算模块部分异常处理说明
无效路径
用于测试的字符串过短
这里捕捉异常主要是为了检查jdk版本是否匹配的问题
部署jar包后通过命令行测试