github地址:https://github.com/CharlesZhongLE/work1

这个作业属于哪个课程 19级信安2班软件工程
这个作业要求在哪里 作业要求
这个作业的目标 关于论文查重的软件工程

P2P表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60
Estimate 估计这个任务需要多少时间 1800
Development 开发 480
Analysis 需求分析 (包括学习新技术) 420
Design Spec 生成设计文档 80
Design Review 设计复审 40
Coding Standard 代码规范 (为目前的开发制定合适的规范) 20
Design 具体设计 60
Coding 具体编码 300
Code Review 代码复审 20
Test 测试(自我测试,修改代码,提交修改) 20
Reporting 报告 60
Test Report 测试报告 20
Size Measurement 计算工作量 40
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 60
合计 1800

开发环境

编程语言 Java 17
IDE Intellij IDEA 2020.1
项目构建工具 maven
单元测试 JUnit-4.12
性能分析工具 JProfiler 12

背景:设计比较两篇文章相似度的算法

一种方案是先将两篇文章分别进行分词,得到一系列特征向量,然后计算特征向量之间的距离(可以计算它们之间的欧氏距离、海明距离或者夹角余弦等等),从而通过距离的大小来判断两篇文章的相似度。另外一种方案是传统hash,我们考虑为每一个web文档通过hash的方式生成一个指纹(finger print)。

下面,我们来分析下这两种方法。采取第一种方法,若是只比较两篇文章的相似性还好,但如果是海量数据呢,有着数以百万甚至亿万的网页,要求你计算这些网页的相似度。你还会去计算任意两个网页之间的距离或夹角余弦么?想必你不会了。而第二种方案中所说的传统加密方式md5,其设计的目的是为了让整个分布尽可能地均匀,但如果输入内容一旦出现哪怕轻微的变化,hash值就会发生很大的变化。理想当中的hash函数,需要对几乎相同的输入内容,产生相同或者相近的hash值,换言之,hash值的相似程度要能直接反映输入内容的相似程度,故md5等传统hash方法也无法满足我们的需求

Simhash算法

来自于GoogleMoses Charikar发表的一篇论文“detecting near-duplicates for web crawling”中提出了simhash算法,专门用来解决亿万级别的网页的去重任务。simhash作为locality sensitive hash(局部敏感哈希)的一种,其主要思想是降维,将高维的特征向量映射成低维的特征向量,通过两个向量的Hamming Distance来确定文章是否重复或者高度近似。
其中,Hamming Distance,又称汉明距离,在信息论中,两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。也就是说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。例如:1011101 与 1001001 之间的汉明距离是 2。至于我们常说的字符串编辑距离则是一般形式的汉明距离。

如此,通过比较多个文档的SimHash值的海明距离,可以获取它们的相似度。

Simhash算法分为5个步骤:分词、hash、加权、合并、降维

分词:给定一段语句,进行分词,得到有效的特征向量,然后为每一个特征向量设置1-5等5个级别的权重
hash:通过hash函数计算各个特征向量的hash值,hash值为二进制数01组成的n-bit签名
加权:在hash值的基础上,给所有特征向量进行加权,即W = Hash * weight,且遇到1则hash值和权值正相乘,遇到0则hash值和权值负相乘
合并:将上述各个特征向量的加权结果累加,变成只有一个序列串
降维:对于n-bit签名的累加结果,如果大于0则置1,否则置0,从而得到该语句的simhash值,最后我们便可以根据不同语句simhash的海明距离来判断它们的相似度。

如下图所示

本实验流程图

模块设计

1. 模块txtrw

其中的类txtrw包含了两个静态方法:

1、readTxt:读取txt文件

2、writeTxt:写入txt文件

实现:使用文件流的输入输出,将TXT文件以String形式按行读入数组。

2. 模块simhash

其中的类simhash包含了两个静态方法:

1、getHash:传入String,计算出它的hash值,并以字符串形式输出,(使用了MD5获得hash值)

2、getSimHash:传入String,计算出它的simHash值,并以字符串形式输出,(需要调用 getHash 方法)

getSimHash 是核心算法,主要流程如下:

1、分词(使用了外部依赖 hankcs 包提供的接口)

2、获取 hash 值

3、加权、合并

4、降维

3. 模块hamming distance

其中的类hammingdistance包含了两个静态方法:

1、getHammingDistance:输入两个 simHash 值,计算出它们的海明距离 distance

2、getSimilarity:输入两个 simHash 值,调用 getHammingDistance 方法得出海明距离 distance,在由 distance 计算出相似度。

4.maincheck主模块

maincheck 方法的主要流程:

1、从命令行输入的路径名读取对应的文件,将文件的内容转化为对应的字符串
2、由字符串得出对应的 simHash值
3、由 simHash值求出相似度
4、把相似度写入最后的结果文件中
5、退出程序

利用JProfiler性能分析

概览

所有对象的实时内存

单元测试

1、hanmingdistancetest类测试

计算原文本与增加些许文字的文本的汉明距离并输出相似度

代码覆盖率

2、txtrwtest类测试

对于路径存在的读入与写入文件进行测试,再对于路径不存在的文件进行异常测试

代码覆盖率

3、simhashtest类测试

利用txtrw类的方法读入文件并计算之间的汉明距离,从而输出文本相似度

代码覆盖率

4、txtshort类测试

解决文本长度太短,HanLP无法取得关键字的问题,用继承Exception的类ShortStringException抛出异常

代码覆盖率

5、mainchecktest类测试

读取所有文件,分别输出原文件与其余文件的文本相似度

文件生成如图

P2P表格

PSP2.2 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60 120
Estimate 估计这个任务需要多少时间 1800 2400
Development 开发 480 600
Analysis 需求分析 (包括学习新技术) 420 480
Design Spec 生成设计文档 80 80
Design Review 设计复审 40 40
Coding Standard 代码规范 (为目前的开发制定合适的规范) 20 20
Design 具体设计 60 120
Coding 具体编码 300 360
Code Review 代码复审 20 20
Test 测试(自我测试,修改代码,提交修改) 20 20
Reporting 报告 60 120
Test Report 测试报告 20 20
Size Measurement 计算工作量 40 60
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 60 60
合计 1800 2400

总结

这次实验属实不易,一路看来,最烦扰我的是各种出错,什么“无效的源发行版16”、“没有主清单属性”等等各式各样的问题纷至沓来,动一步错一步,在一次次寻找答案的时候也学会了如何解决,万能的CSDN网友以及同学的帮助,非常非常感谢了。收获最大的,是对于各种操作从零到一的熟练使用。编程这块,薄弱的基础还是难以承受压力山大的工程,这也太难啦。

参考与借鉴

https://blog.csdn.net/lengye7/article/details/79789206
https://blog.csdn.net/weixin_44911685/article/details/108785424
https://blog.csdn.net/qq_31702847/article/details/104866713
https://blog.csdn.net/VinsmS/article/details/80858944
https://blog.csdn.net/a294039255/article/details/84863892
https://blog.csdn.net/qq_39007083/article/details/107168551
https://blog.csdn.net/qq_37107280/article/details/73246274

posted on 2021-09-17 23:38  Charles_Z  阅读(63)  评论(0编辑  收藏  举报