【NLP】Python实例:申报项目查重系统设计与实现
Python实例:申报项目查重系统设计与实现
作者:白宁超
2017年5月18日17:51:37
摘要:关于查重系统很多人并不陌生,无论本科还是硕博毕业都不可避免涉及论文查重问题,这也对学术不正之风起到一定纠正作用。单位主要针对科技项目申报审核,传统的方式人力物力比较大,且伴随季度性的繁重工作,效率不高。基于此,单位觉得开发一款可以达到实用的智能查重系统。遍及网络文献,终未得到有价值的参考资料,这个也是自然。首先类似知网,paperpass这样的商业公司其毕业申报专利并进行保密,其他科研单位因发展需要也不会开源。笔者就结合NLP相关知识进行设计一款自主的查重系统,首先采用自然语言处理方法主要提出两个模型:科技项目查重的训练模型和科技项目查重的测试模型。其中训练模型主要对数据的清洗预处理及其规约化处理,测试系统也是主查重系统,对其查重原理和性能进行设计实现。最后将其封装成包,PHP或者Java等语言调用即可。(本文原创编著,转载注明出处:Python实例:申报项目查重系统设计与实现)
1 开发环境部署
硬件环境:普通台式机或者笔记本一台,可以正常连网,配置不作特别要求
软件环境:win7以上系统,本机采用WIN10 64位系统
开发环境:Sublime + Python3.5(Anaconda)
分词工具:先行的分词工具都可以,本文采用结巴分词
PHP调用环境:WampServer(php开发集成环境)
2 查重系统需要分析
背景:科技相关工作者通过计划项目管理平台进行项目申报,这个过程中存在涉嫌造假,修改本人以往项目等一系列违规操作。为了遏制这种现象,开发一款智能的项目查重系统必然不能或缺。
需求:低版本主要控制申报项目的标题和简介查重问题,实现对相似度较高的项目进行查重。用户提交申报项目后,自动审查是否存在违规行为。
解决:1 从服务器中导出今年真实的申报项目作为训练集(目前采用真实项目2400多个),通过对训练数据集的一系列数据清洗,然后进行语料库构建工作。2 采用文本相似度原理对测试文本进行建模,最后通过文本相似算法的实现,完成查重系统。3 PHP调用python查重文件,实现操作。
问题:1 真实语料规模有所限制,伴随语料扩大效果更好。2 文本相似度多种算法比较,包括:欧几里德距离、余弦定理、皮尔逊相关度、曼哈顿距离、Jaccard系数、gensim相似度等,改进版采用合适的相似度算法。3 对同义词、近义词、稀有词、核心词等权重问题的改进 4 后续改进针对整篇文章和主题识别
3 查重系统设计流程
本查重系统设计分为两大步骤:训练模型和测试模型。
训练模型:
1 首先从数据库中导出原始申报项目核心字段数据,其中subject代表项目课题名称,summary代表课题项目简介。

2 通过算法完成语料标记工作,具体算法原理和实现参见下文,效果如下图:

3 对数据进行预处理,其中包括正则匹配、文本分词、停用词处理、字符串操作、规约化数据等,处理后结果如下:

4 采用余弦相似度进行相似算法处理,最后识别结果如下:

5 PHP调用Python算法的运行结果:
当重复率大于阈值时:

当重复率小于阈值时:

4 科技项目查重训练模型
1 针对路径进行配置,其中源语料为datas.txt,标记处理后保存到同目录下的flagdatas.txt中
2 对原始语料进行标记和简单清洗,之所以采用标记,一方面便于序列化展示,另一方面区分项目名称和简介。
3 保存标记后的语料并统计处理结果
4 对标记数据进行分词处理。本文采用的结巴分词,分词后可以采用两种情况的处理,其一是不带词性标记的处理方式,直接将分词结果与停用词词典进行比对,去除停用词。其二是采用带有词性标注的分词结果,我们然后采用词典和去除词性的方式进行预处理,其中诸如虚词,助词等可以根据业务需求去除。而相对于名词、动词等主要词性,可以通过增加权重的方式进行处理。最终保村分词结果。作为训练语料库即对比语料库。
具体预处理源码如下:
# 1 针对语料路径进行配置
path="../CheckRepeat/database/OrigCorpus/datas.txt" # 训练语料库
flagpath="../CheckRepeat/database/OrigCorpus/flagdatas.txt" # 语料标记 # 2 对原始语料进行标记和简单清洗
listset="" # 标记后的语料集合
i,j=1,1
with open(path,'r',encoding='utf-8') as f:
for rline in f.readlines():
line = rline.strip().replace(" ","")
if "summary" in line :
listset +="\n"+str(i)+"_"+line
i+=1 # 简介打标签
elif "subject" not in line:
listset +=line
elif "subject" in line:
listset +="\n"+str(j)+"_"+line
j+=1 # 项目题目打标签 # 3 保存标记后语料并统计标记结果
with open(flagpath,'w',encoding='utf-8') as f1:
f1.write(listset.strip())
print("="*70)
print("项目共计标题:"+str(len(listset.split("subject"))-1))
print("项目共计简介:"+str(len(listset.split("summary"))-1))
print("-"*70) # 4 对标记数据进行分词处理
cutpath="../CheckRepeat/database/OrigCorpus/cutdatas.txt" # 保存分词后的结果
cutword(flagpath,cutpath)
其执行2405条数据的性能如下:具体分析发现启动分词工具耗时1.2秒左右,其余耗时量主要是停用词比对时,两个矩阵计算造成的,这个问题可以通过算法改进,缩短耗时。

5 科技项目查重实现(测试)系统
1 接收项目文件(项目名称/项目简介)进行预处理操作,其实这个过程跟模型训练时的预处理算法是一致的。
2 将训练阶段处理后的数据进行处理,分割出项目名称/项目简介,分布存放在两个list中。
3 判断参数是否为空,如果不为空将对应的参数放入验证查重结果。
4 以测试数据和训练的每条数据的词项构建文本向量,通过文本向量的夹角即判断文本相似度,并反馈出结果。本文采用的是python自带的difflib模块进行处理,difflib是python提供的比较序列(string list)差异的模块。实现了三个类:1>SequenceMatcher 任意类型序列的比较 (可以比较字符串)2>Differ 对字符串进行比较3>HtmlDiff 将比较结果输出为html格式.理由是其相对比较成熟,本项目的处理量并不大。倘若处理G级或P级规模的数据,可以考虑使用google的gensim相似度算法,大大提高处理速度,幸运的是该算法也是python自带的一个模块。当然对其原理的理解,建议还是自己实现下。
5 对查重后的结果进行处理,可以保存到本地,也可以直接输出,由于本项目主要提供php调用,切php调用执行py文件之后,对输出结果不能换行处理,所以本项目添加一些html标签和css样式。
查重实现核心源码如下:
def checkfun(namestr):
subject={} # 记录查重结果,键值对,原句+重复率
summary={}
# 找到对比库的历史数据
checkpath ="../CheckRepeat/database/OrigCorpus/cutdatas.txt" # 数据库中对比项目语料库
with open(checkpath,"r",encoding="utf-8") as f:
checklist=[line[:] for line in f.readlines()]
subjectname=[sub for sub in checklist if "subject" in sub] # 项目名称
summaryname=[summ for summ in checklist if "summary" in summ] # 项目简介 if "subject" in namestr:
# 进行项目名称验证操作
for rline in subjectname:
line = ''.join(str(rline).split(' ')[:])
subp = difflib.SequenceMatcher(None,namestr.split('\n')[].replace('subject',''),line).ratio()
subject[line]=float('%.4f'%(subp))
if "summary" in namestr:
# 进行项目简介验证操作
for rline in summaryname:
line = ''.join(str(rline).split(' ')[:])
sump = difflib.SequenceMatcher(None,namestr.split('\n')[].replace('summary',''),line).ratio()
summary[line]=float('%.4f'%(sump)) # 打印检测结果
outreslut=""
sort1=sorted(subject.items(),key=lambda e:e[],reverse=True) #排序
outreslut +="项目名称:"+"*"*+"["+namestr.split('\n')[].replace('subject','') + "]"+"*"*+"的查重结果如下:\n\n"
for item in sort1[:]:
if item[] >= 0.5:
outreslut += "与项目库中\t[<span style=\"color:red\">"+item[].replace("\n",'')+"</span>]\t的相似率最高:<span style=\"color:red\">"+str(item[]) +"</span>\n"
else:
outreslut += "<span style=\"color:green\">没有查出重复的项目简介</span>\n" sort2=sorted(summary.items(),key=lambda e:e[],reverse=True) #排序
outreslut += "\n\n项目简介:"+"*"*+"["+namestr.split('\n')[].replace('summary','') + "]"+"*"*+"的查重结果如下:\n\n"
for item in sort2[:]:
if item[] >= 0.5:
outreslut += "与项目库中\t[<span style=\"color:red\">"+item[].replace("\n",'')+"</span>]\t的相似率最高:<span style=\"color:red\">"+str(item[]) +"</span>\n"
else:
outreslut += "<span style=\"color:green\">没有查出重复的项目简介</span>\n" # 写到文件里面
with open("../CheckRepeat/database/DealCorpus/checkout.txt",'w',encoding='utf-8') as f:
f.write(outreslut)
print(outreslut)
其运行结果如下:

6 PHP调用Python查重系统
1 php调用主要是$program变量下的语句,原理是:
python.exe的绝对路径,空格,调用py的主文件绝对路径,空格,参数1,空格,参数2
2 py文件通过sys相关参数进行接收,sys.argv[0]是py文本名,所以1-n对应你传入的参数如下:
# subject = sys.argv[1]
# summary = sys.argv[2]
3 exec($program,$result,$N)其执行py程序并返回一条字符串,返回结果保存在$result中。$N代表执行是否成功,成功返回1
4 shell_exec($program) 返回py文件所有语句的输出
5 php与py之间存在乱码问题,可以通过mb_convert_encoding ($output,"UTF-8", "GBK")解决
<?php
$name=mb_convert_encoding($_POST['projectname'], "GBK","UTF-8");
$sumb=mb_convert_encoding($_POST['projectsumb'], "GBK","UTF-8");
$program="D:/Users/Administrator/Anaconda3/python E:/pythonSource/CheckArticle/CheckRepeat/checkIndex.py ".$name." ".$sumb.""; #注意使用绝对路径.$name."".$sumb
$output = nl2br(shell_exec($program));
// $program1="D:/Users/Administrator/Anaconda3/python ../CheckRepeat/test.py ".$name." ".$sumb.""; #注意使用绝对路径.$name."".$sumb
// $result1 = shell_exec($program1);
echo mb_convert_encoding ($output,"UTF-8", "GBK");
// if ($output!=null){
// print_r(nl2br(file_get_contents('../CheckRepeat/database/DealCorpus/checkout.txt')));
// }
?>
7 参考文献:
[1] TF-IDF与余弦相似性的应用:http://www.ruanyifeng.com/blog/2013/03/tf-idf.html
[2] 海量数据相似度计算之simhash短文本查找:http://www.lanceyan.com/tag/simhash
[3] 用TF特征向量和simhash指纹计算中文文本的相似度:https://github.com/zyymax/text-similarity
[4] gensim文档相似度判断:http://kekefund.com/2016/05/27/gensim-similarity/
[5] python文本相似度计算:http://www.jianshu.com/p/edf666d3995f
[6] 如何计算两个文档的相似度:https://flystarhe.github.io/2016/08/30/document-similarity/
[7] gensim文档相似度判断:http://kekefund.com/2016/05/27/gensim-similarity/
【NLP】Python实例:申报项目查重系统设计与实现的更多相关文章
- python简单实现论文查重(软工第一次项目作业)
前言 软件工程 https://edu.cnblogs.com/campus/gdgy/informationsecurity1812 作业要求 https://edu.cnblogs.com/cam ...
- 【NLP】Python实例:基于文本相似度对申报项目进行查重设计
Python实例:申报项目查重系统设计与实现 作者:白宁超 2017年5月18日17:51:37 摘要:关于查重系统很多人并不陌生,无论本科还是硕博毕业都不可避免涉及论文查重问题,这也对学术不正之风起 ...
- 在PHP项目中使用Standford Moss代码查重系统
Standford Moss 系统是斯坦福大学大名鼎鼎的代码查重系统,它可以查出哪些同学提交的代码是抄袭别人的,从而将提交结果拒之门外.它对一切希望使用该系统的人都是开放的,那么在PHP的项目中如何使 ...
- python 手把手教你基于搜索引擎实现文章查重
前言 文章抄袭在互联网中普遍存在,很多博主都收受其烦.近几年随着互联网的发展,抄袭等不道德行为在互联网上愈演愈烈,甚至复制.黏贴后发布标原创屡见不鲜,部分抄袭后的文章甚至标记了一些联系方式从而使读者获 ...
- (转)Python实例手册
原文地址:http://hi.baidu.com/quanzhou722/item/cf4471f8e23d3149932af2a7 实在是太好的资料了,不得不转 python实例手册 #encodi ...
- 【实习记】2014-09-01从复杂到简单:一行命令区间查重+长整型在awk中的bug
9月1号,导出sql文件后,想到了awk,但很复杂.想到了用sed前期处理+python排序比较的区间查重法.编写加调试用了约3小时. 9月2号,编写C代码的sql语句过程中,发现排序可以交m ...
- (转载)myeclipse项目名称重命名
myeclipse项目名称重命名 实例1 今天晚上在做一个jsp唱片显示的实例,myeclipse项目名称原本想写music结果写成了musci.这就需要项目名称的重命名,单纯的使用 “重构--> ...
- 使用docker安装部署Spark集群来训练CNN(含Python实例)
使用docker安装部署Spark集群来训练CNN(含Python实例) http://blog.csdn.net/cyh_24/article/details/49683221 实验室有4台神服务器 ...
- 团队作业1——团队展示&博客作业查重系统
团队展示: 1.队名:六个核桃 2.队员学号: 王婧(201421123065).柯怡芳(201421123067组长).陈艺菡(201421123068). 钱惠(201421123071).尼玛( ...
随机推荐
- 从以往子类化跟踪MouseLeave深入讨论VB6的自定义Hook类
一.关于起因 之前发过一篇博文,是关于VB6中跟踪鼠标移出事件的示例(http://www.cnblogs.com/alexywt/p/5891827.html) 随着业务状况的不断发展,提出了更多的 ...
- Java并发编程:如何创建进程?
转载自:http://www.cnblogs.com/dolphin0520/p/3913517.html 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程 ...
- Framework7初始化
/** * Framework7初始化 * 需引用jQuery */ /*---------------------------函数---------------------------*/ /** ...
- 使用VS2015将解决方案同步更新到Github上
如今开源已经是一种趋势与潮流了,今天就来谈一谈如何将利用VS将我们的解决方案同步更新到Github上. 第一步:登录自己的Github账号(没有的自行注册). 我的Github登录后的界面: 第二步: ...
- 免费视频播放器videojs中文教程
Video.js是一款web视频播放器,支持html5和flash两种播放方式.更多关于video.js的介绍,可以访问官方网站介绍,我之前也写过一篇关于video.js的使用心得,有兴趣的可以点这里 ...
- 严格模式下的javascript
arguments: ECMA5移除了实参对象(arguments),在非严格模式下函数里的arguments只是一个标识符,在严格模式下它变成了保留字.严格模式下无法使用arguments作为形参名 ...
- 关于MYSQL存储中文问题
最近在学习MYSQL时遇到了不能存储中文的问题,在网上找了很多类似的方法,最后都失败了(失败原因:修改完my.cnf文件后mysql server重新启动失败),濒临崩溃的时候重装了下mysql(Ub ...
- 【模板】二分图最大权完美匹配KM算法
hdu2255模板题 KM是什么意思,详见百度百科. 总之知道它可以求二分图最大权完美匹配就可以了,时间复杂度为O(n^3). 给张图. 二分图有了边权,求最大匹配下的最大权值. 所以该怎么做呢?对啊 ...
- struts2 之 【struts2简介,struts2开发步骤,struts2详细配置,struts2执行流程】
入门框架学习避免不了的问题: 1. 什么是框架? 简单的说,框架就是模板,模子,模型.就是一个可重用的半成品. 2. 如何学习框架? 学习框架其实就是学习规则,使用框架就是遵循框架的规则,框架是可变的 ...
- VS2015下OpenGL库的配置
写在前面: 最近要用到OpenGL,光是在VS2015下配置就费了很大的劲,现在将我的成果直接贡献给大家,希望能为需要在VS2015下配置OpenGL的读者省去一些麻烦. 正文: 资源地址1:http ...