论文查重项目

news/2025/9/22 4:03:47/文章来源:https://www.cnblogs.com/kakadomi/p/19099310
这个作业的GitHub地址 https://github.com/kakadomi/kakadomi
这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience/homework/13477
这个作业的目标 <完成 PSP 表格、开发查重代码、测试及性能分析>

一. PSP表格

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



二. 计算模块接口的设计与实现过程

1. 模块接口设计

通过5 个核心函数实现模块化拆分,函数间通过 “参数传递” 形成依赖关系,属于典型的 “管道式” 流程设计。

  • 各个函数作用

    • read_fild : 读取文本文件,处理文件读取异常
    • preprocess_text : 中文分词、过滤空白符,标准化文本格式
    • calculate_similarity : 核心计算:TF-IDF 向量转换 + 余弦相似度计算
    • write_result : 将相似度结果写入result.txt,处理写入异常
    • main : 流程控制:调用其他函数,完成“输入-计算-输出”过程
  • 程序简单流程图

31


2. 算法关键:精准衡量文本相似的核心逻辑

算法通过“特征提取 + 量化计算”,避开传统“逐字比对”的缺陷,重点解决“中文文本如何准确比相似”的问题:

  • TF-IDF向量转换: 通过“词频(TF) × 逆文档频率(IDF)” 给词语加权,自动压低“的、是”等无意义高频词的权重,突出“专业术语、特殊表述”等核心词,避免垃圾词干扰查重结果。
  • 余弦相似度: 将文本转化为向量后,通过计算向量夹角的余弦值衡量相似性。即使两篇文本长度不同(如抄袭文是原文节选),只要核心词分布一致,就能精准识别抄袭关系,比“字符匹配率”更贴合实际需求。

3. 独到设计:适配场景的代码优势

代码围绕 “中文查重” 的需求做了轻量化优化,兼顾易用性和稳定性:

  • 轻量模块化架构:不用类和复杂结构,仅通过 5 个函数实现 “输入→预处理→计算→输出” 全流程,代码量少、逻辑清晰,容易维护和调试,适合小规模查重场景。
  • 精细化异常处理:针对 “文件读取 / 写入” 等高频出错环节,捕获 “文件未找到” 等具体异常,同时用通用异常兜底。既避免程序崩溃,又能明确告知错误原因,方便定位问题。
  • 适配中文:用 jieba 做中文分词(比 Python 内置方法更精准,能正确拆分专业词),同时过滤空格、换行等空白字符,避免因排版差异(如原文多换行、抄袭文无换行)导致的相似度误判。



三. 计算模块接口部分的性能改进

1. 记录改进计算模块性能上所花费的时间

阶段 花费时间(分钟) 主要内容
初始版本 80 完成基本功能,核心算法
第一次性能分析 40 使用Snakeviz性能分析工具,找到主要耗时部分
进行优化 60 主要对文本预处理、相似度计算、批量处理与内存部分进行优化
第二次性能分析 20 验证优化效果,与第一次进行对比
总花费时间 200

2. 第一次性能分析结果

基于Snakeviz性能分析工具,找到主要耗时部分

6

性能瓶颈总结
函数 执行时间 占比 严重程度 问题分析
core_task 0.753s 100% 严重 整体流程耗时集中在核心逻辑
calculate_similarity 0..753s 100% 严重 相似度计算几乎消耗core_task全部时间
preprocess_test 0.743s 98.7% 文本预处理是相似度计算的主要耗时点
jieba.cut 0.735s 97.6% 结巴分词的cut方法以及DAG构建、分词策略是文本预处理的性能瓶颈

3.改进优化

分词优化:

  • @lru_cache 缓存重复文本的分词结果,避免了相同文本多次调用 jieba.cut
  • 预编译正则 PUNCT_RE 加速了文本清洗,减少了无效分词的开销
import re  
from functools import lru_cache  # 预编译更严格的标点/无效字符正则(覆盖更多干扰符号,减少分词负担)
# 匹配非中文、非字母、非数字、非空格的字符
PUNCT_RE = re.compile(r'[^\w\s\u4e00-\u9fa5]', re.UNICODE)  # 缓存重复文本的分词结果(增大缓存容量,适配更多重复文本场景)
@lru_cache(maxsize=1024)  # 缓存容量提升至1024
def preprocess_text(text):"""优化后:更高效的文本清洗→分词→过滤,减少重复计算和中间开销"""# 步骤1:清洗文本(移除更多无效字符,让分词只处理有效内容)text = PUNCT_RE.sub('', text).strip()  if not text:  # 空文本直接返回,避免后续无效操作return ''# 步骤2:结巴分词(禁用HMM模式,减少动态规划开销,适合非新词主导的文本)# cut_all=False:精准模式;HMM=False:禁用隐马尔可夫模型(加速分词)words = jieba.cut(text, cut_all=False, HMM=False)  # 步骤3:过滤空白字符并拼接(减少内存临时结构)return ' '.join(word for word in words if word.strip())

相似度计算优化:
全局复用 TfidfVectorizer 避免重复初始化,限制最大特征数减少矩阵计算量,速度提升约 15%。

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np# 全局复用向量器(避免重复初始化的开销)
tfidf_vectorizer = TfidfVectorizer(token_pattern=r"(?u)\b\w+\b",  # 匹配分词后的词语min_df=1,  # 最小词频(减少稀疏矩阵计算量)max_features=10000  # 限制最大特征数(加速转换)
)def calculate_similarity(original_text: str, plagiarized_text: str) -> float:"""优化后的相似度计算:复用向量器+减少中间变量"""# 1. 预处理(复用优化后的分词函数)orig_words = preprocess_text(original_text)plag_words = preprocess_text(plagiarized_text)# 2. 转换为字符串(适配TfidfVectorizer输入格式)orig_str = ' '.join(orig_words) if orig_words else ''plag_str = ' '.join(plag_words) if plag_words else ''# 3. 批量转换+计算相似度(减少函数调用次数)tfidf_matrix = tfidf_vectorizer.fit_transform([orig_str, plag_str])# 4. 直接计算余弦相似度(避免额外的矩阵切片开销)return cosine_similarity(tfidf_matrix[0], tfidf_matrix[1])[0][0]

批量处理与内存优化:
将多组文本一次性输入模型,减少 50% 以上的重复拟合开销,适合需要批量查重的场景。

def batch_calculate_similarity(text_pairs: list) -> list:"""批量计算多组文本的相似度text_pairs: 格式为 [(原文1, 疑似抄袭文1), (原文2, 疑似抄袭文2), ...]"""# 1. 批量预处理(减少循环内函数调用)orig_texts = []plag_texts = []for orig, plag in text_pairs:orig_words = preprocess_text(orig)plag_words = preprocess_text(plag)orig_texts.append(' '.join(orig_words) if orig_words else '')plag_texts.append(' '.join(plag_words) if plag_words else '')# 2. 一次性构建TF-IDF矩阵(减少重复拟合开销)all_texts = orig_texts + plag_textstfidf_matrix = tfidf_vectorizer.fit_transform(all_texts)n = len(orig_texts)  # 区分原文与抄袭文的索引# 3. 批量计算相似度(用numpy向量操作加速)similarities = []for i in range(n):# 直接通过矩阵索引计算,避免重复切片sim = cosine_similarity(tfidf_matrix[i], tfidf_matrix[i + n])[0][0]similarities.append(round(sim, 4))  # 保留4位小数return similarities

4. 第二次性能分析

基于Snakeviz性能分析工具

3


优化后性能分析

函数 优化前耗时 优化后耗时 变化说明
core_task 0.753s 0.189s 总耗时减少约75%,优化效果显著
calculate_similarity 0.753s 1.888s 该函数耗时占比从99.9%降至接近99.5%,且绝对耗时减少约75%
preprocess_text 0.743s 0.177s 耗时减少约76%,文本预处理环节加速明显
jieba.cut 0.735s 0.169s 分词环节总开销减少约77%



四. 计算模块部分单元测试展示

单元测试示例:文本查重核心功能

  1. 测试函数:test_preprocess_with_punctuation
  • 测试目标:验证包含多种标点符号的文本预处理(分词及标点去除)功能。
  • 构造测试数据思路:使用包含感叹号、省略号、逗号、分号、问号、引号等多种标点的中文文本,覆盖常见标点使用场景,以检验文本清洗和分词的准确性。
  • 测试代码:
def test_preprocess_with_punctuation(self):"""测试包含多种标点符号的文本处理"""text = "你好!这是一个测试...包含逗号,分号;问号?还有引号'\"。"result = preprocess_text(text)# 预期分词结果(需与本地jieba实际分词匹配)self.assertEqual(result, "你好 这是 一个 测试 包含 逗号 分 号 问号 还有 引号")

2.测试函数:test_similarity_identical_text

  • 测试目标:验证完全相同文本的相似度计算功能。
  • 构造测试数据思路:使用两段完全相同的中文文本,检验相似度计算是否能返回接近 1.0 的结果,确保函数对完全相同文本的识别准确性。
  • 测试代码:
def test_similarity_identical_text(self):"""测试完全相同的文本(相似度应为1.0)"""text1 = "机器学习是人工智能的一个分支,研究计算机能从数据中学习。"text2 = "机器学习是人工智能的一个分支,研究计算机能从数据中学习。"similarity = calculate_similarity(text1, text2)self.assertAlmostEqual(similarity, 1.0, places=2)

3.测试函数:test_preprocess_mixed_languages

  • 测试目标:验证中英日韩混合文本的预处理(核心内容保留)功能。
  • 构造测试数据思路:使用包含中文、英文、日文、韩文的混合文本,其中包含英文专有名词、数字等,检验函数对多语言文本的兼容性,确保核心的中文和英文内容能被正确保留。
  • 测试代码:
def test_preprocess_mixed_languages(self):"""测试中英日韩混合文本处理(只校验核心内容保留)"""text = "C语言是1972年由Bell Labs开发的;日本語の文字も含む;한국어도 포함된다."result = preprocess_text(text)self.assertIn("C语言", result)self.assertIn("1972", result)self.assertIn("Bell", result)self.assertIn("Labs", result)

单元测试覆盖率图:
其中,单元测试得到的测试覆盖率为98%。

4



五. 计算模块部分异常处理说明

1.文件读取异常

设计目标:确保程序在文件操作失败时能够退出并提供明确的错误信息。
对应场景:处理文件不存在、权限不足、编码错误等文件读取问题。

import unittest
import os
from main import read_fileclass TestFileOperations(unittest.TestCase):def test_read_file_not_exist(self):"""测试读取不存在文件时的异常处理错误场景:尝试读取不存在的文件"""non_existent_file = "non_existent.txt"with self.assertRaises(Exception):read_file(non_existent_file)

2.空文本处理异常

设计目标:确保空文本参与相似度计算时能返回合理结果(如相似度为 0)
对应场景:处理空文本或全标点符号文本的情况,避免在计算相似度时出现异常。

import unittest
from main import calculate_similarityclass TestSimilarityCalculation(unittest.TestCase):def test_calculate_similarity_empty(self):"""测试空文本的相似度计算错误场景:两篇文本均为空"""similarity = calculate_similarity("", "")self.assertEqual(similarity, 0.0)def test_calculate_similarity_mixed_empty(self):"""测试一个空文本和一个正常文本的相似度计算错误场景:其中一篇文本为空"""similarity = calculate_similarity("这是正常文本内容。", "")self.assertEqual(similarity, 0.0)

3.命令行参数异常

设计目标: 提供清晰的使用说明,引导用户正确使用程序。
对应场景:处理命令行参数数量不正确的情况,当用户提供的参数数量不符合要求时。

import unittest
import subprocess
import sys
from main import mainclass TestCommandLineArguments(unittest.TestCase):def test_main_wrong_arguments(self):"""测试命令行参数错误的情况错误场景:用户提供的命令行参数数量不足"""cmd = [sys.executable, 'main.py', 'only_one_argument.txt']result = subprocess.run(cmd, capture_output=True, text=True)self.assertNotEqual(result.returncode, 0)error_output = result.stderr + result.stdoutself.assertIn("使用方法", error_output)



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/909173.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我的第一个程序Hello,World!成功运行!

遇到了很多很多问题*JDK vs JRE,傻傻分不清,JDK才包含编译器javacOracle官网下载困难,转向下载Zulu OpenJDK(www.azul.com)配置环境变量后命令依然无效,在命令行输入javac -version不是内部或外部命令未输入完整路径…

Day05-1-C:\Users\Lenovo\Desktop\note\code\JavaSE\Basic\src\com\David\scanner-Demo01~05(简易计算器)

package com.David.scanner; import java.util.Scanner; public class Demo01 { public static void main(String[] args) { //创建一个扫描对象,用于接受键盘数据‘ Scanner scanner = new Scanner(System.in); Syst…

Day05-C:\Users\Lenovo\Desktop\note\code\JavaSE\Basic\src\com\David\struct-ifDemo01~03+shunxuDemo

Scanner Java.util.scanner Scanner s = new Scanner(System.in); Next一定要读取到有效字符才结束 对输入有效字符前的空白,next()方法会自动将其去掉 只有输入有效字符后才将其后面输入的空白作为分隔符或结束符 ne…

JS历理 优化login.js脚本2

const infoList = [];// 收集链接相关信息 const currentUrl = window.location.href || "未知链接"; const originUrl = window.location.origin || "未知源地址"; const pathname = window.loca…

Codeforces Round 1052 (Div. 2)

A. Equal Occurrences 题意:求\(a\)的一个最长子序列,使得每个数出现的次数相同。 记录每个数出现的次数,排序后从小到大枚举出现次数,那么比它多的数都可以选。点击查看代码 #include <bits/stdc++.h>using…

PatternMatcher-Pytorch

import os import torch import torch.nn as nn import torch._inductor.pattern_matcher as pm from torch._higher_order_ops.auto_functionalize import auto_functionalized from torch._inductor.compile_fx impo…

uboot启动流程

1、整个流程BootROM(MaskROM) → TPL(可选) → VPL(可选) → SPL → U-Boot proper* (main U-Boot)(*表示必须要的阶段) BootROM(1、用户不可写 2、10KB量级 3、执行速度快, 和SRAM接近) TPL(Tertiary Program…

内存泄漏

内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 内存泄漏缺陷具有隐蔽性、积累性的特征,比其他内存非法…

Context Engineering

很多人容易小看“prompt engineering”,认为这样的工作只是“调用大模型”而已。事实上随着时代的发展,“调用大模型”完成任务已经悄然成为了软件工程的新范式。相比之下, 传统软件工程只能完成由人事先编写的精确…

ios在wifi模式下设置http代理

1.使用概述 此模式在使用wifi的情况下进行使用,不需要安装任何app 2.打开手机的wifi设置a.打开wifi b.打开当前wifi(点击i) 滑倒最下面,[配置代理],设置为手动,点击进去修改为手动然后设置服务器,端口,用户,密码等这五…

面试官问:请画出 MySQL 架构图!这种变态问题都能问的出来

面试官问:请画出 MySQL 架构图!这种变态问题都能问的出来MySQL架构详解:从面试题到核心组件解析 MySQL架构主要分为四层:1)连接层负责连接管理;2)服务层处理SQL解析优化;3)存储引擎层(InnoDB/MyISAM等)实现数据存…

基于协方差交叉(CI)的多传感器融合算法matlab仿真,对比单传感器和SCC融合

1.程序功能描述 基于协方差交叉(CI)的多传感器融合算法matlab仿真,对比单传感器和SCC融合。对比速度估计误差RMSE指标,位置估计误差RMSE指标,等概率密度椭圆。 2.测试软件版本以及运行结果展示MATLAB2022A版本运…

github/网盘/公众号信息收集

(1)github信息收集 基于域名,邮箱,公司名称,备案号,个人名称,电话号码,qq号码 去百度上搜索资产,获取网站,然后在gihub上进行搜索 xxx.edu passwd 或者使用工具 http://github.com/obheda12/GitDorker/tree/…

AtCoder Regular Contest 206 (Div. 2) 部分题解

A B C D 题解AtCoder Regular Contest 206 (Div. 2) 部分题解 A - Range Replace 我们发现,若 \(a_i=a_{i+1}\) 则将操作左端点放在 \(i\) 和 \(i+1\) 是等价的,为了不重复,我们强制所有操作左端点都要放在 \(i\) 使…

Grafana 和 Openssh 高危漏洞修复

本次漏洞扫描,扫描到的高危漏洞涉及Grafana和Openssh,其中Grafana发现漏洞有(CVE-2023-3128、CVE-2022-23498、CVE-2023-4822、CVE-2024-1442),Openssh的漏洞有(CVE-2023-38408、CVE-2020-15778、CVE-2020-12062…

学习日报(补发)

时间:600min 搏客量:1 内容: 一、今日核心工作 今日的主要工作是成功在 Hadoop 集群环境中启动 Hive Metastore 服务,为后续的数据仓库操作和 HiveServer2 连接提供元数据管理支持。 二、工作执行详情 在 node1 节…

Influxdb 得模糊查询总结

InfluxDB 模糊查询完整总结与示例(修正版) 📊 查询方式全面总结(InfluxQL) 1. 精确匹配(最佳性能) -- 单值精确匹配 WHERE routername = NJ-MAIPU-1-- 多值精确匹配(使用OR) WHERE routername = NJ-MAIPU-1 …

多表关系和多表查询

多表关系和多表查询 1.0 一对多 表与表之间也存在关系,有一对一,一对多,多对多三种,比如部门表中的一个部门,对应着员工表中的多个员工 ,这就是一对多的关系,我们将多的一方称作子表,比如上面的员工表,一的一…

【反比例函数】【做题笔记】【图形存在性】题目合集

【反比例函数】【做题笔记】【图形存在性】题目合集 1.(2023 秋盐城月考) 如图,点 \(A\) 在双曲线 \(y=\frac{k}{x} \ (k \neq 0)\) 的第一象限的图象上,\(AB\) 垂直于 \(y\) 轴于点 \(B\),点 \(C\) 在 \(x\) 轴的…

20250920 嘉定江桥---江苏吴江区太湖 往返160KM骑行小记

20250920 嘉定江桥<--->江苏吴江区太湖 往返160KM骑行小记历时14小时, 完成了这次160km的骑行, 解锁新地标太湖, 也创造了我的个人单次骑行距离的纪录.从嘉定江桥出发, 沿北青公路向西骑行26KM直到尽头, 就可以出…