这个作业属于哪个课程 | 计科23级12班 |
---|---|
这个作业要求在哪里 | 个人项目 |
这个作业的目标 | 设计并实现论文查重算法,实现原文与抄袭版论文的相似度计算,并输出重复率。使用 PSP 表格记录开发时间,进行单元测试、性能分析与优化,掌握 GitHub 项目管理与提交方法。 |
✨ github链接:https://github.com/Wangyio-2/Wangyio-2/tree/main/3223004344
1.PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 35 | 30 |
· Estimate | 估计这个任务需要多少时间 | 35 | 30 |
Development | 开发 | 400 | 520 |
· Analysis | 需求分析 (包括学习新技术) | 70 | 80 |
· Design Spec | 生成设计文档 | 45 | 40 |
· Design Review | 设计复审 | 30 | 25 |
· Coding Standard | 代码规范 (制定开发规范) | 15 | 15 |
· Design | 具体设计 | 40 | 45 |
· Coding | 具体编码 | 120 | 150 |
· Code Review | 代码复审 | 35 | 35 |
· Test | 测试 (自我测试,修改代码,提交修改) | 45 | 130 |
Reporting | 报告 | 120 | 200 |
· Test Report | 测试报告 | 70 | 90 |
· Size Measurement | 计算工作量 | 15 | 15 |
· Postmortem | 事后总结,并提出过程改进计划 | 35 | 95 |
Total | 合计 | 555 | 750 |
2.计算模块接口的设计与实现过程
1. 模块与函数组织
文件处理模块
read_file(file_path)
- 功能:读取文本内容,返回字符串;支持文件不存在时容错处理。
write_result(file_path, orig_path, plag_path, similarity)
- 功能:输出结果文件,包含原文文件路径、抄袭版文件路径及重复率;每个抄袭版文件独立输出。
文本预处理模块
preprocess(text, use_stopwords=True)
- 功能:将文本小写化、分词,可按需过滤停用词和数字;输出标准化词列表,为相似度计算提供输入。
相似度计算模块
lcs_ratio(seq1, seq2)
- 功能:基于最长公共子序列(LCS)计算词序相似度。
cosine_similarity(tokens1, tokens2)
- 功能:基于词频向量计算余弦相似度,衡量词汇覆盖率。
hybrid_similarity(orig_text, plag_text)
- 功能:核心算法接口,融合 LCS 与余弦相似度,加权输出最终重复率百分比;结合停用词优化和完整分词实现顺序与词频兼顾。
控制与批量处理模块
process_file_pair(orig_path, plag_path, ans_path)
- 功能:单组文件处理流程,包括读取文件 → 相似度计算 → 写入结果 → 输出日志。
main()
- 功能:程序入口,解析命令行参数或批量文件列表,调用
process_file_pair()
完成单组或批量查重任务。
- 功能:程序入口,解析命令行参数或批量文件列表,调用
2. 函数调用关系与计算流程

- 控制模块 (
main
、process_file_pair
)- 负责调度整个查重流程,支持单组和批量处理。
- 文件模块 (
read_file
、write_result
)- 处理数据输入输出和日志管理。
- 算法模块 (
hybrid_similarity
)- 内部调用 LCS 与余弦相似度,输出最终重复率。
算法关键点与独到之处
-
高精度混合相似度算法
- 使用 最长公共子序列(LCS) 捕捉词序信息,能够反映文本改写、增删和段落重排等变化。
- 使用 余弦相似度 衡量词频覆盖率,顺序无关,能够检测文字替换或词序调整的抄袭。
- 加权融合公式:
兼顾词序与词频,提升查重精度。最终相似度 = 0.6 * 余弦相似度 + 0.4 * LCS相似度
-
停用词优化策略
- LCS 相似度使用去停用词列表
orig_tokens_stop
与plag_tokens_stop
,减少高频功能词对匹配结果的干扰。 - 余弦相似度使用完整分词
orig_tokens_full
与plag_tokens_full
,保证词频统计完整。
- LCS 相似度使用去停用词列表
-
模块化设计与接口规范
- 文本预处理:
preprocess()
提供统一接口,控制停用词过滤和数字处理。 - 相似度计算:
lcs_ratio(seq1, seq2)
:计算最长公共子序列比例,衡量词序相似度。cosine_similarity(tokens1, tokens2)
:通过词频向量计算余弦相似度。
- 文件处理:
read_file(file_path)
:读取文本并去除首尾空白,支持文件不存在时容错。write_result(file_path, orig_path, plag_path, similarity)
:输出结果文件,包含原文、抄袭版路径和重复率。
- 控制与批量处理:
process_file_pair(orig_path, plag_path, ans_path)
:单组文件处理流程,包括读取文件、计算相似度、写入结果。main()
:解析命令行或批量文件列表,循环调用process_file_pair()
。
- 文本预处理:
-
批量处理与输出格式化
- 支持批量处理多组论文查重,自动循环调用查重算法。
- 每个抄袭文件生成独立结果文件,包含原文路径、抄袭版路径及重复率。
- 输出日志清晰,便于管理和统计。
-
容错与健壮性
- 文件不存在或为空时自动跳过,保证批量处理不中断。
- 错误和异常被及时捕获并输出提示,提高系统稳定性。
- 代码可直接运行也可以接受命令行传参。
3.代码分析与优化
分析工具与方法
在本项目中,为了保证代码质量和可维护性,我采用了三类主流的 Python 代码分析与优化工具:
-
Flake8
- 用于检查代码风格是否符合 PEP8 规范(空格、缩进、行长度、函数定义之间的空行数等)。
- 能发现常见的低级错误和不规范写法。
-
pylint
- 提供更严格的静态分析,检查变量命名、未使用的导入、潜在逻辑错误等。
- 会给出综合评分,便于跟踪代码质量的改进。
-
mypy(可选)
- 静态类型检查工具,确保函数参数、返回值类型符合预期,减少运行时错误。
在本次分析中,主要使用 Flake8 进行代码风格检查,并结合 pylint 验证整体质量评分。
优化前后性能分析
1. 优化目标
在初版实现中,性能瓶颈主要集中在以下三个环节:
- 分词(
jieba.lcut
):每次调用成本较高,而在hybrid_similarity
中被重复调用 4 次。 - 余弦相似度(
tokens.count()
):通过在词汇表上循环调用count()
构造词频向量,复杂度为 O(n²)。 - 最长公共子序列(LCS):基于
SequenceMatcher
,对长文本效率较低。
优化目标是减少冗余分词、降低余弦相似度计算复杂度,并为 LCS 留下进一步优化空间。
2. 优化方法
-
分词优化
引入tokenize(text)
,在一次分词的基础上生成 停用词过滤版和完整分词版,避免重复调用jieba.lcut
。 -
余弦相似度优化
用Counter
代替list.count
,将复杂度从 O(n²) 降至 O(n)。 -
接口保持一致
优化仅在函数内部完成,hybrid_similarity(orig_text, plag_text)
对外接口保持不变,便于替换和测试。
3. 实验方法
使用 Python cProfile 和 time.perf_counter() 对比优化前后运行时间,测试文件为 orig.txt
与 orig_0.8_dis_15.txt
,长度约数千字。
5. 结论
- 分词优化:显著减少了重复调用,节省约一半分词时间;
- 余弦相似度优化:将时间复杂度从 O(n²) 降低到 O(n),大幅提升效率;
- 总体性能:整体运行速度提升约 50%,在批量文件处理场景下效果尤为明显;
- 未来优化方向:针对
SequenceMatcher
替换为 动态规划 LCS 或 启发式比对算法,以进一步提升性能。