个人项目
这个作业属于哪个课程 | 课程链接 |
---|---|
这个作业要求在哪里 | 作业要求 |
这个作业的目标 | 完成论文查重代码上传到github上,完成github项目编写 |
github链接
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ---- | ---- |
Estimate | 估计这个任务需要多少时间 | 410 | 390 |
Development | 开发 | ---- | ---- |
Analysis | 需求分析 (包括学习新技术) | 120 | 100 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 | 30 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 40 | 40 |
Design | 具体设计 | 30 | 30 |
· Coding | 具体编码 | 60 | 60 |
· Code Review | 代码复审 | 30 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 30 | 30 |
Reporting | 报告 | ---- | ---- |
Test Repor | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 10 | 10 |
---- | 合计 | 410 | 390 |
2.1计算模块接口的设计与实现过程
我实现了两种论文查重算法,一种是基于词频向量的余弦距离算法,一种是simhash算法
余弦距离算法
包含一个主函数,一个filter函数,以及一个calc_similarity函数
calc_similarity函数用于实现对两个论文进行进行词频向量的转换以及余弦距离的计算,我们使用gensim自带的doc2bow进行转换,然后使用自带的similarity函数进行计算
filter函数我们使用了jieba分词进行cut,然后用re.match将标点符号空格分段去掉
余弦距离算法流程:
simhash算法
包含一个主函数,一个simhash类
simhash先计算字符串的simhash值,再用hammingDis计算两段hash值的距离
simhash程序流程:
2.2关键函数的分析与实现
simhash算法
在实现和学习算法的过程中,我参考研究了以下文章:
在simhash中处理一个文本的步骤如下:
第一步,分词:
对文本进行分词操作,同时需要我们同时返回当前词组在文本内容中的权重。
第二步,计算hash:
对于每一个得到的词组做hash,将词语表示为到01表示的bit位,需要保证每个hash结果的位数相同,如图中所示,使用的是8bit。
第三步,加权
根据每个词组对应的权重,对hash值做加权计算(bit为1则取为1做乘积,bit为0则取为-1做乘积),如上图中,
10011111与权重2加权得到[2 -2 -2 2 2 2 2 2];
01001011与权重1加权得到[-1 1 -1 -1 1 -1 1 1];
01001011与权重4加权后得到[-4 4 -4 -4 4 -4 4 4];
第三步,纵向相加:
将上述得到的加权向量结果,进行纵向相加实现降维,如上述所示,得到[-3 3 -7 -3 7 -3 7 7]。
第四步,归一化:
将最终降维向量,对于每一位大于0则取为1,否则取为0,这样就能得到最终的simhash的指纹签名[0 1 0 0 1 0 1 1]
第五步,相似度比较:
通过上面的步骤,我们可以利用SimHash算法为每一个网页生成一个向量指纹,在simhash中,判断2篇文本的相似性使用的是汉明距离。在在经验数据上,我们多认为两个文本的汉明距离<=3的话则认定是相似的。
基于词频向量的余弦距离算法
假设有两个句子A,B
句子A:我喜欢吃苹果,不喜欢吃榴莲
句子B:我不喜欢吃苹果,也不喜欢吃榴莲。
第一步,分词。
句子A:我/喜欢/吃/苹果,不/喜欢/吃/榴莲。
句子B:我/不/喜欢/吃/苹果,也/不/喜欢/吃/榴莲
实现:通过python的jieba分词实现,即通过查询内置的词典进行分词
第二步,列出所有的词。
我,喜欢,吃,苹果,榴莲,不,也。
第三步,计算词频。
句子A:我 1,喜欢 2,吃 2,苹果 1,榴莲 1,不 1,也 0。
句子B:我 1,喜欢 2,吃 2,苹果 1,榴莲 1,不 2,也 1。
第四步,写出词频向量。
句子A:[1, 2, 2, 1, 1, 1, 0]
句子B:[1, 2, 2, 1, 1, 2, 1]
第五步,计算余弦距离
我们可以把它们想象成空间中的两条线段,都是从原点([0, 0, ...])出发,指向不同的方向。两条线段之间形成一个夹角,如果夹角为0度,意味着方向相同、线段重合;如果夹角为90度,意味着形成直角,方向完全不相似;如果夹角为180度,意味着方向正好相反。因此,我们可以通过夹角的大小,来判断向量的相似程度。夹角越小,就代表越相似。
以上内容参考自:TF-IDF与余弦相似性的应用(二):找出相似文章
3. 计算模块接口部分的性能改进
simhash
耗时:
基于词频向量的余弦距离算法
耗时:
4.计算模块部分单元测试展示
simhash
punc = './ <>_ - - = ", 。,?!“”:‘’@#¥% … &×()——+【】{};;● &~| \s:'
real_txt=open(sys.argv[1],encoding='utf8')
string1=''
string2=''
copy_txt=open(sys.argv[2],encoding='utf8')
real_txt=real_txt.read()
copy_txt=copy_txt.read()
print(copy_txt)
real_txt = re.sub(r'[^\w]+', '',real_txt)
seg=jieba.cut(real_txt)
string1=string1.join(seg)
line1 = re.sub(r"[{}]+".format(punc), "", string1)
copy_txt = re.sub(r'[^\w]+', '',copy_txt)
seg=jieba.cut(copy_txt)
string2=string2.join(seg)
line2 = re.sub(r"[{}]+".format(punc), "", string2)
print(line2)
keyWord = jieba.analyse.extract_tags(
'|'.join(content), topK=10, withWeight=True, allowPOS=())
print(keyWord)
keyList = []
for feature, weight in keyWord:
weight = int(weight * 10)
feature = self.string_hash(feature)
temp = []
for i in feature:
if(i == '1'):
temp.append(weight)
else:
temp.append(-weight)
# print(temp)
keyList.append(temp)
list1 = np.sum(np.array(keyList), axis=0)
print(list1)
if(keyList==[]): #编码读不出来
return '00'
simhash = ''
for i in list1:
if(i > 0):
simhash = simhash + '1'
else:
simhash = simhash + '0'
return simhash
基于词频向量的余弦距离算法
real_txt=open(sys.argv[1],encoding='utf8')
copy_txt=open(sys.argv[2],encoding='utf8')
str1=real_txt.read()
str2=copy_txt.read()
print(str2)
text1 = filter(str1)
text2 = filter(str2)
print(text2)
sim=calc_similarity(text1,text2)
def calc_similarity(text1,text2):
texts=[text1,text2]
dictionary = gensim.corpora.Dictionary(texts)
print(dictionary)
corpus = [dictionary.doc2bow(text) for text in texts]
print(corpus)
similarity = gensim.similarities.Similarity('-Similarity-index', corpus, num_features=len(dictionary))
test_corpus_1 = dictionary.doc2bow(text1)
cosine_sim = similarity[test_corpus_1][1]
return cosine_sim
代码覆盖率截图
5.模块部分异常处理说明
assert len(sys.argv)==4,"输入不符合规范,缺少文件目录"
assert os.path.exists(sys.argv[1]),"原文文件不存在,请检查文件目录是否正确"
assert os.path.exists(sys.argv[1]),"抄袭文件不存在,请检查文件目录是否正确"
6.项目程序功能测试
基于词频向量的余弦距离算法
simhash