成为新会员获取本项目完整代码与数据资料

加入会员群

一周的评审时间,20多位专家,如何保证公平高效?他想起去年因为一篇涉嫌抄袭的论文漏检,导致整个评审组被质疑。这不是个案,而是当前大规模学术评审面临的普遍困境。面对海量的论文,人工评审不仅耗时耗力,更难以确保标准的一致性和对学术不端行为的精准识别。我们曾在一次项目中,直面这一挑战,最终开发出一套基于多模态数据融合与深度学习的智能筛查系统。本文将完整复现这一项目的技术核心,从PDF文档的自动化信息提取,到内容质量筛查,再到多维度相似性检测,层层递进,手把手教你构建一个能真正落地的学术评审“AI助手”。

本文内容改编自过往客户咨询项目的技术沉淀并且已通过实际业务校验,该项目完整代码与数据已分享至交流社群。阅读原文进群获取完整代码数据及更多最新AI见解、行业洞察,可与900+行业人士交流成长;还提供人工答疑,拆解核心原理、代码逻辑与业务适配思路,帮大家既懂怎么做,也懂为什么这么做;遇代码运行问题,更能享24小时调试支持。

本项目完整代码与数据资料

下载资料(完整代码数据)

文章脉络概览
本文的探索路径如下,我们将从数据准备出发,逐步构建一个完整的智能评审系统:

1. 数据解析与预处理
   ├── PDF文档自动化信息提取 (PyMuPDF, pdfplumber)
   │    ├── 基础信息:页数、字数、标题
   │    ├── 章节信息:摘要、正文、参考文献定位
   │    └── 内容元素:图片、表格统计
   │
2. 内容质量初筛 (NLP)
   ├── 敏感信息检测 (关键词匹配)
   ├── 赛题相关性判断 (TF-IDF + 余弦相似度)
   └── 实质内容评估 (长度 + 相似度联合决策)
   │
3. 多维相似性深度检测
   ├── 文本雷同 (TF-IDF)
   ├── 图片雷同 (pHash + 汉明距离)
   ├── 公式雷同 (OCR + 符号化)
   └── 综合重复率 (加权融合)
   │
4. 复杂场景强化检测 (ResNet50)
   └── 高图片占比论文的深度特征提取与相似度计算

1. 痛点与破局:竞赛论文评审的智能转型之路
在传统的人工评审模式下,一场大型竞赛往往意味着数百乃至上千篇论文的堆积,评审专家需要逐篇阅读、判断,这不仅耗费巨大的时间成本,更难以避免因疲劳或主观偏好带来的标准不一。更棘手的是,一些隐蔽的学术不端行为,如对图片、公式的篡改,仅凭肉眼很难在短时间内发现。
我们的项目正是从这个痛点切入。我们设想,能否开发一套系统,它能像一位不知疲倦的专家助理,先帮我们“看”完所有论文,把结构化的信息、有问题的论文、疑似雷同的部分都标记出来,让评审专家将精力聚焦于论文的创新性和核心价值?答案是肯定的。通过融合自然语言处理、计算机视觉和深度学习技术,我们构建了一个多模态的智能筛查框架。

图1 本文研究思路流程图

2. 数据探索与预处理:奠定分析基石
在让模型“学习”之前,我们必须先“理解”数据。面对数量庞大的PDF文档,第一步是精准地从中提取出我们需要的结构化信息。
2.1 缺失值处理:让数据更完整
原始数据中存在缺失值是常态,比如某些论文可能没有提取到摘要页数。如果不处理,后续的分析就会“断链”。我们采用了分类处理的策略:对于数值型特征(如重复率、字数),用均值或中位数填充;对于文本型特征(如论文标题),用众数填充。这样既保留了数据规模,又保证了结构的完整。

图2 result1.xlsx 缺失数据情况

图3 result2.xlsx 缺失数据情况
经过处理,文本长度类特征的缺失减少了97%,内容相似度特征100%填充,数据可用性提升至99%,为后续分析提供了完整的数据基础。

图4 对 result1.xlsx 数据进行缺失值处理前后对比
2.2 异常值处理:剔除“噪音”
异常值就像是数据中的“噪音”,会干扰模型的判断。比如,一篇论文的总字数如果达到3万多字,明显偏离了大部分论文的分布,这就是一个异常值。我们使用四分位距(IQR)方法来识别并处理这些异常值。

图5 部分数据异常值情况
IQR 异常值判定公式为:下限 = Q1 – k × IQR,上限 = Q3 + k × IQR。通过这个方法,我们可以将极端值替换为上下限值,使数据分布更紧凑,避免模型被极端值“带偏”。

图6 部分数据异常值处理情况
2.3 数据标准化:统一“度量衡”
不同的指标有不同的量纲,比如“总字数”是千级,“参考文献页数”是十级。如果直接使用,大范围的特征会主导模型,导致分析结果失真。因此,我们使用Z-score标准化,将所有特征转换到同一数量级。标准化公式为:x_scaled = (x – μ) / σ,其中μ是均值,σ是标准差。


图7 部分标准化结果

3. 自动化信息提取:让机器“读懂”PDF
我们利用Python生态中的PyMuPDF和pdfplumber库,搭建了一个多层级的信息提取框架。PyMuPDF擅长处理PDF的底层结构,可以快速定位文本块、图像和矢量图形;而pdfplumber则更专注于文本布局分析和表格提取。两者结合,优势互补。

图8 论文结构组成
以下是我们针对单个PDF文件进行信息提取的核心代码(经过优化和注释):

# 导入必要的库
import os
import re
import pandas as pd
import pdfplumber
import fitz  # PyMuPDF
from collections import defaultdict
import logging

# 配置日志,方便追踪处理过程
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
logger = logging.getLogger(__name__)

def extract_pdf_info(pdf_file_path, mapping_team_id):
    """从单个PDF文件中提取所有预定义的统计信息"""
    # 使用defaultdict,对于未定义的键会返回0,方便后续累加
    paper_stats = defaultdict(int)
    try:
        # ----- 第一层:用PyMuPDF获取基础信息和图片数 -----
        with fitz.open(pdf_file_path) as pdf_document:
            paper_stats["论文总页数"] = len(pdf_document)
            # 统计所有页面中的图片数量
            image_count = 0
            for page in pdf_document:
                image_count += len(page.get_images())
            paper_stats["正文图片数"] = image_count

        # ----- 第二层:用pdfplumber提取文本和表格,进行细粒度分析 -----
        with pdfplumber.open(pdf_file_path) as pdf_file:
            full_text = ""  # 存储全文
            paragraph_list = []  # 存储所有段落
            table_list = []  # 存储所有表格
            for pdf_page in pdf_file.pages:
                page_text = pdf_page.extract_text() or ""
                full_text += page_text
                # 按两个换行符分割段落,这是一个粗略但有效的段落识别方法
                paragraph_list.extend([p.strip() for p in page_text.split('\n\n') if p.strip()])
                # 提取当前页的所有表格
                table_list.extend(pdf_page.extract_tables())

            # 计算总字数,调用自定义函数
            paper_stats["论文总字数"] = count_chinese_and_english_words(full_text)
            paper_stats["正文表格数"] = len(table_list)

        # ----- 后续:标题提取、章节检测与统计 -----
        paper_stats["论文标题"] = extract_title_from_text(full_text)
        # ... (此处省略了章节检测、参考文献统计等详细代码,以保持简洁)
        # 章节检测的具体实现涉及复杂的正则匹配和位置判断,是确保统计准确性的关键
        # 我们会根据“摘要”、“目录”、“参考文献”等关键词,定位各个部分的起止位置
        # 并基于此,计算出摘要字数、正文页数、参考文献数量等关键指标

        # 从文件名中提取加密号,并关联参赛队号
        match_team = re.search(r"A\d+", os.path.basename(pdf_file_path))
        if match_team:
            paper_stats["参赛队号"] = mapping_team_id.get(match_team.group(), "未知")

        return dict(paper_stats)
    except Exception as error:
        logger.error(f"处理文件 {pdf_file_path} 时出错: {str(error)}")
        return None

def count_chinese_and_english_words(input_text):
    """一个改进的字数统计函数,分别统计中文字符和英文单词"""
    # 匹配所有中文字符 (Unicode范围 \u4e00-\u9fa5)
    chinese_chars = re.findall(r'[\u4e00-\u9fa5]', input_text)
    # 匹配所有英文单词 (由字母组成)
    english_words = re.findall(r'\b[a-zA-Z]+\b', input_text)
    return len(chinese_chars) + len(english_words)

def extract_title_from_text(input_text):
    """优化后的标题提取逻辑,能更好地处理学术论文的复杂标题"""
    # 对文本进行预处理,去除开头可能存在的特殊符号,并转为小写以匹配
    cleaned_text = re.sub(r'^[\W_]+', '', input_text).lower()
    # 寻找“摘要”或“Abstract”的位置,标题通常出现在它之前
    abstract_pos = re.search(r'\s*摘\s*\s*要\s*|Abstract', cleaned_text, re.IGNORECASE)
    # 定义标题的正则模式,允许数字、中文、英文、冒号、破折号等
    title_pattern = r'^(\d*\s*[\u4e00-\u9fa5a-zA-Z0-9\s:—-]+)(?:\n|$)'

    if abstract_pos:
        candidate_area = cleaned_text[:abstract_pos.start()].strip()
        lines = candidate_area.split('\n')
        for line in lines:
            line = line.strip()
            match = re.search(title_pattern, line)
            if match:
                potential_title = match.group(1).strip()
                # 确保提取的不是“摘要”本身
                if not re.search(r'摘\s*要|Abstract', potential_title, re.IGNORECASE):
                    return potential_title.capitalize()
    # 如果没找到摘要,则从文本开头的前800个字符中寻找标题
    else:
        candidate_area = cleaned_text[:800].strip()
        lines = candidate_area.split('\n')
        for line in lines:
            line = line.strip()
            match = re.search(title_pattern, line)
            if match:
                potential_title = match.group(1).strip()
                if not re.search(r'摘\s*要|Abstract', potential_title, re.IGNORECASE):
                    return potential_title.capitalize()
    return "无标题"

# 批量处理逻辑 (使用多进程)
# 为了提升处理效率,我们使用了进程池,可以并行处理多个PDF文件
# ... (此处省略了多进程批量处理的具体实现,这部分代码会调用上面的extract_pdf_info函数)
# 最终,所有提取的信息会被整理成一个DataFrame,并保存为result1.xlsx文件

通过上述方法,我们能够高效地从几百篇PDF中提取出结构化的数据,例如论文总页数、总字数、标题、摘要字数、正文图片数等。这些数据被保存在 result1.xlsx 中,为后续的分析提供了坚实的数据基础。

图9 正文字数与总字数关系分析
对样本数据的统计分析表明(如图10所示),处理结果保存在 result1.xlsx 文件中,可直接用于后续分析。研究论文的页数分布(如图10所示),呈现显著的右偏态特征,集中趋势表现为算术平均值为22.8页,而离散程度分析显示,超过76%的样本集中分布于0-15页区间。

图10 论文页数分布直方图

图11 result1.xlsx 结果图

4. 内容质量初筛:构建第一道防线
在了解论文的基本信息后,下一步是快速筛选出那些明显存在问题的论文,例如泄露个人信息、与赛题无关或缺乏实质内容。这就像是在一场大型招聘中,先用简历筛选器过滤掉明显不符合要求的申请者。
图12 筛选流程效果图
4.1 三合一筛查模型
我们设计了一个包含三个子模块的筛查模型:
1. 参赛队信息泄露检测:通过提取附件中的“学校名”、“指导老师”、“队员”等信息构建关键词库,然后检查论文文本中是否包含这些敏感词。
2. 赛题相关性判断:利用TF-IDF算法将赛题文本和论文文本都转化为向量,然后计算两者之间的余弦相似度。相似度过低,则判定为与赛题无关。
3. 无实质内容识别:如果一篇论文与赛题相似度极高(可能只是复制了赛题),但文本长度又非常短,则很可能是一篇没有自己思考和实质性内容的“空壳”论文。
这三大模块联合决策,任何一个模块给出“阳性”结果,这篇论文就会被标记为“需人工复核”。我们使用的TF-IDF模型,其核心思想是:如果一个词在一篇文档中出现频率高(TF高),但在整个文档集合中出现频率低(IDF高),那么这个词对这篇文档来说就很重要。通过计算文档向量的夹角余弦值,我们可以量化两篇文档的相似度。公式如下:
TF-IDF 权重 = 词频 × log(总文档数 / (包含该词的文档数 + 1))
余弦相似度 = (向量A · 向量B) / (||向量A|| × ||向量B||)
其中,||向量A|| 表示向量的长度。

图13 New TF-IDF 算法实现流程
4.2 筛查结果与洞察
通过这个模型,我们对697篇论文进行了筛查。

图14 提取关键词量

图15 特征词的向量空间个数
结果显示,有44篇论文(占比67.7%)被判定为无实质内容,9篇(占比13.8%)与赛题无关,12篇(占比18.5%)存在信息泄露风险。

图16 数据质量指标计数

图17 数据质量指标占比
这表明,我们的初筛模型能够有效降低人工评审的工作量,将专家的人力集中在真正有潜力、有价值的论文上。

相关技术图片

DeepSeek、LangGraph和Python融合LSTM、RF、XGBoost、LR多模型预测NFLX股票涨跌|附完整代码数据

本文介绍了多模型融合预测股票涨跌的完整代码与案例,结合DeepSeek、LangGraph等技术框架,提供完整的代码数据资源。

探索观点

阅读原文进群获取完整内容及更多AI见解、行业洞察,与900+行业人士交流成长。


5. 多维度相似性检测:揪出隐蔽的学术不端

如果说初筛是“粗滤”,那么相似性检测就是“精加工”。我们不仅要看文本,还要看图片和公式,因为学术不端行为往往发生在这些容易被忽视的角落。

5.1 文本、图片、公式的三重奏

  • 文本重复:我们再次使用TF-IDF和余弦相似度,计算每篇论文与其他所有论文的相似度,取最高值作为其文本重复率。
  • 图片雷同检测:这里我们使用感知哈希算法(pHash)。其原理是先将图片缩小、灰度化,然后进行离散余弦变换,得到一个代表图片主要特征的哈希值。通过比较两幅图片哈希值的汉明距离(即对应位不同的数量),来判断图片是否相似。如果距离很小(≤2),则判定为雷同。

图18 像素值与均值比较

  • 公式雷同检测:对于图片形式的公式,我们先用Tesseract OCR技术将其识别为LaTeX表达式,然后使用SymPy库将其转化为标准化的数学符号表达式,最后通过比对表达式结构树来判断公式是否雷同。

5.2 综合重复率

我们将文本、图片、公式三个维度的检测结果进行加权融合,得到综合重复率。根据对实际数据的大量测试和业务经验,我们设定文本重复率权重为60%,图片为30%,公式为10%,公式为:综合重复率 = 0.6 × R文本 + 0.3 × R图片 + 0.1 × R公式

从结果来看,有45.7%的论文综合重复率在0-10%之间,78.3%的论文控制在20%以下。但仍有21.7%的论文重复率超过20%,其中约11.1%超过30%。这个分布为设置预警阈值提供了重要依据。

图19 雷同公式次数最多的 5 支参赛队

图20 论文重复率分布特征

阅读原文进群获取完整内容及更多AI见解、行业洞察,与900+行业人士交流成长。


6. 深度学习强化:ResNet50攻克高图片占比论文

我们发现,有些论文,特别是那些以图表、仿真结果图为主的论文,图片占比极高。传统的pHash算法在处理这类论文时,可能会因为图片的局部细微修改(如颜色变换、微调)而产生误判。因此,我们引入了在图像识别领域表现出色的ResNet50卷积神经网络。

6.1 为什么是ResNet50?

ResNet(残差网络)解决了深度网络训练中梯度消失的难题,使得网络可以做到很深而不退化。ResNet50作为其经典变种,通过“残差块”和“瓶颈结构”的设计,在保证强大特征提取能力的同时,有效控制了计算量。它的核心是让网络学习输入和输出之间的“残差”F(x),而不是直接学习完整的映射H(x),这使得网络更容易优化。

残差块的计算可以简化为:Output = Activation( Conv2( Conv1(Input) ) + Input )

简单来说,它允许信息通过“跳跃连接”直接从浅层传到深层,既保留了原始信息,又让网络专注于学习微小的差异。对于高图片占比论文,ResNet50能提取出比pHash更深层次的视觉特征,从而更准确地判断图片的相似度,特别是对经过高级篡改的图片。

图21 Tesseract 基本组成框

图22 Tesseract OCR 处理流程图

图23 残差神经网络算法实现图

6.2 效果提升

我们将ResNet50的特征与之前的文本、图片哈希特征融合,形成了多模态特征融合模型。实验结果显示,与只使用文本和pHash的单一模态方法相比,新模型在高相似论文检出率上提升了6.4%,综合重复率计算也更精确(整体分布更合理,极端值减少)。

统计指标原始检测优化后检测变化解读
均值0.2540.187-26.38%,判定更严格,减少误判
中位数0.2350.172-26.81%,整体相似度水平下降
标准差0.1520.124-18.42%,评分更稳定,极端值减少
最大值1.0000.801-19.90%,完全雷同的极端情况被有效识别和修正

图24 重复率分布对比

图25 重复率累积分布对比

阅读原文进群获取完整内容及更多AI见解、行业洞察,与900+行业人士交流成长。


7. 模型检验与学术合规指南

为了确保模型在真实场景下的可靠性,我们还进行了鲁棒性分析和误差分析。例如,当调整文本分割的规则时,统计出的段落数变化了12%,但核心的语义特征(如段落平均句子数)波动很小,这说明模型对格式变化具有较强的稳定性。同时,通过对比人工抽检结果,我们量化了不同工具在字符识别、图片漏检等方面的误差率,并针对性地进行了优化。

7.1 权重调整的灵敏度分析

如图26所示,当图片权重为30%时,综合重复率为0.1877;当图片权重提升至50%时,综合重复率上升至0.2046,上升幅度约为9%,体现了图片权重增加对综合重复率的直接影响。图片权重为30%和50%时,排名均为73,波动幅度为0%,远小于5%。这表明尽管图片权重调整使综合重复率上升,但对论文的排名影响极小,说明权重调整对结果排序的影响在可控范围内。

图26 跨模态重复率计算权重调整的灵敏度分析

7.2 工具链优化提升数据精度

数据提取误差量化通过人工抽查与基准对比,评估数据解析工具的准确性。如图27所示,pdfplumber对多栏排版文本的字符识别准确率为97.2%,主要误差源于公式图片误判(占比2.8%);pymupdf的图片漏检率为4.8%,集中于分辨率<50px的嵌入式图标。公式检测中,正则表达式对嵌套结构的识别误差率为11.5%,引入Tesseract OCR后误差率降至3.2%,表明工具链优化可显著提升数据提取精度。

图27 工具链优化提升数据提

7.3 参数调整对统计指标的影响

通过模拟论文格式变化,验证模型对数据噪声的抗干扰能力,经统计,在100篇样本中,当段落分割规则从“连续2个换行符”调整为“连续1个换行符”时,段落数由150个增至168个,增幅为12%,而段落平均句子数波动仅3.5%。如图28所示,这表明文本结构指标对格式变化具有较强的稳定性,核心语义特征未受显著影响。

图28 参数调整对统计指标的影响

7.4 学术写作合规与风险规避(必读!)

对于正在撰写毕业论文的同学,将本文的方法应用于自己的研究时,请注意以下几点,以确保学术合规并顺利通过答辩:

1. AI使用合规边界:
根据教育部《高等学校学术规范指南》,人工智能生成内容(AIGC)可作为辅助研究工具,但严禁将其直接用于论文的撰写或抄袭。本文提供的代码和数据,旨在帮助你复现研究过程,验证方法有效性。在论文中,你必须清晰地说明:

  • 使用目的:为何选用此方法(例如,为了提高相似性检测的效率与覆盖面)。
  • 使用方式:如何调整和适配你的数据。
  • 核心贡献你的工作是对模型的改进、集成,还是对结果的创新性解读? 这是区分“工具使用”和“学术贡献”的关键。

2. 机器学习方法难度分级与解释:

  • 本科论文: 建议聚焦于基础特征工程+传统机器学习模型(如TF-IDF、余弦相似度)。重点在于清晰地解释模型的数学原理、参数设置的理由,并结合具体案例解读结果
  • 硕士论文: 鼓励探索多模态特征融合深度学习模型(如ResNet50)。你的核心价值体现在模型的创新性组合、针对特定问题(如高图片占比论文)的优化、以及对模型决策过程的可解释性分析

3. 论文级实证结果解读:

  • 不要只罗列数字。例如,在分析重复率分布时,不能只说“45.7%的论文重复率在0-10%之间”。要深入解释:“这表明,在本次所分析的数据集中,绝大多数论文保持了良好的原创性,仅有少数论文存在较高相似度,这印证了模型筛选机制的合理性。”
  • 结合图表讲“故事”。每一张图都是你论证的一部分。如上文的重复率分布图,它不仅展示了数据分布,还揭示了“长尾现象”,为设置合理的“重复率阈值”提供了数据支撑。

4. 稳健性检验(论文答辩高频考点):

  • 定义:检验模型在不同数据子集或不同参数设置下,结论是否稳定。
  • 如何做:文中展示的“图片权重灵敏度分析”就是一种稳健性检验。答辩时,你可以自信地说:“我们通过调整融合权重,发现虽然综合重复率会随之变化,但论文的相对排序高度稳定,这证明了我们的评估体系是稳健的,结论不依赖于某个特定参数的偶然选择。”

5. 变量设计的合理性:

  • 问题:为什么选择这些特征?为什么给文本、图片、公式分配这些权重?
  • 标准答案“特征的选取基于对论文评审业务逻辑的深入理解。文本是论文的主体,因此赋予最高权重;图片和公式是技术创新的重要载体,且篡改行为隐蔽,因此将其纳入,权重参考了专家经验和大量实验测试的结果,旨在找到最符合学术直觉的平衡点。”

6. 代码可复现性与查重优化:

  • 代码附录:附录中的代码必须干净、有注释。我们提供的代码已经经过学术化注释和变量名重构,你可放心放入论文附录。
  • 查重优化:对方法描述部分,切忌照搬原文。应用“用自己的话,把技术原理讲给一位懂技术的朋友听”的方式去复述。多结合你的具体业务场景(比如,将“论文”替换为你的“课题数据”),多举例,多加入你的分析和思考。本文的叙述方式就是一个很好的范本。

8. 总结与展望

我们构建的这套智能评审系统,如同一位经验丰富的“数字侦探”,能够高效、精准地完成论文的基础信息统计、质量筛查和多维度相似性检测。它通过规则与学习相结合的策略,将复杂的评审问题拆解为一系列可计算的子任务,并在关键环节引入深度学习(ResNet50),显著提升了检测的准确性。

未来的工作,我们可以向更深层次的语义理解和更智能的跨领域适配迈进。例如,引入BERT等预训练模型来理解文本的深层含义,而不是仅仅依赖关键词匹配;或者设计一个能够根据不同学科、不同竞赛类型自动调整参数和规则的“动态智能体”。技术的演进永无止境,而我们的目标始终是让技术更好地服务于学术的公平与创新。

阅读原文进群获取完整代码数据及更多最新AI见解、行业洞察,可与900+行业人士交流成长;还提供人工答疑,拆解核心原理、代码逻辑与业务适配思路,帮大家既懂怎么做,也懂为什么这么做;遇代码运行问题,更能享24小时试支持。

封面