简介:这份资源是面向本科毕业设计场景的深度学习文本摘要自动生成项目,聚焦自然语言处理与Transformer模型的工程落地,适合具备一定Python基础、希望系统实践NLP课程设计或毕设的学生。压缩包共34个文件,约360KB,以18个Python脚本为核心,覆盖模型定义、数据预处理、训练与评估流程,另含5个Shell脚本用于训练与测试调度,以及txt、yml、vocab、Dockerfile等配置与词表文件,整体结构清晰、便于按模块阅读。项目围绕编码器-解码器架构展开,涉及分词、词汇表构建、序列化输入、损失函数与优化器配置,并引入ROUGE、BLEU等指标衡量摘要质量,同时提供beam search、强化学习训练等进阶实现,可帮助读者理解从数据到模型再到评价的完整链路。目前已有3764人学习下载,适合作为NLP方向毕设的参考方案与调试起点。1. 从一份“跑不通”的毕设说起:文本摘要自动生成到底要交什么很多同学做文本摘要自动生成这个本科毕业设计,卡住的地方往往不是模型本身,而是不知道一份合格的方案该长什么样。有人拿开源代码跑了一遍,生成几句不通顺的摘要就截图交差;有人把 Transformer 结构图画得漂漂亮亮,一问推理流程就说不清楚。这个项目的核心需求其实很明确:给定一段长文本,自动输出保留核心信息的短摘要,并且要有可复现的训练、推理和评测流程。它适合两类人——正在做自然语言处理方向毕设的本科生,以及需要快速搭一套摘要生成原型的从业者。关键词里的深度学习、Transformer、文本摘要,落到交付物上就是三样东西:一份能讲清设计逻辑的文档、一套能跑通的代码、一组能说服答辩老师的评测数据。下面按需求、设计、实现、避坑、验收的顺序,把这份方案拆开讲。2. 需求分析与技术选型:为什么是“抽取+生成”混合路线2.1 任务边界:摘要不是缩写,更不是关键词堆叠文本摘要自动生成在学术上分两类:抽取式(extractive)和生成式(abstractive)。抽取式从原文挑句子拼成摘要,优点是通顺、不易出错,缺点是冗余、不连贯;生成式用自己的话重新组织,优点是灵活,缺点是容易产生事实性错误,也就是常说的“幻觉”。本科毕设如果只做抽取式,工作量偏薄,答辩时容易被问“深度学习体现在哪”;只做生成式,训练不稳定,显存吃紧,最后可能连一个像样的结果都拿不出来。我一般建议走混合路线:先用抽取式做一轮句子筛选,把长文本压缩到模型能处理的长度,再用生成式模型做改写。这样既体现了深度学习的核心,又控制了工程复杂度。任务边界要写清楚:输入是单篇文档,输出是长度在 80 到 150 字之间的摘要,评测指标用 ROUGE-1、ROUGE-2、ROUGE-L。别小看这个边界定义,答辩时老师第一个问的就是“你的输入输出到底是什么”。2.2 技术选型:Transformer 做主干,预训练模型做底座选型这块,血泪经验是别从零训 Transformer。本科毕设的算力和数据量根本不够,从零训出来的模型生成的句子连语法都不对。通常的做法是拿预训练模型做微调,比如基于 Transformer 的编码器-解码器结构,编码器读原文,解码器逐词生成摘要。如果显存有限,可以选轻量级的预训练模型,参数量控制在 1 亿以内,单张消费级显卡就能跑。数据方面,中文摘要常用的是大规模新闻语料,每条包含正文和参考摘要。如果找不到合适的中文数据集,可以用英文数据集先跑通流程,再换中文小规模数据微调。这里有个坑:很多人直接拿预训练模型做零样本推理,结果 ROUGE 分数低得可怜,因为预训练任务和摘要任务差距很大,必须做微调。# 技术选型核心配置示例 config = { "model_name": "轻量级预训练模型", # 编码器-解码器结构 "max_input_length": 512, # 原文截断长度,覆盖大部分新闻正文 "max_target_length": 128, # 摘要最大长度,对应 80-150 字 "batch_size": 8, # 单卡显存 8G 左右可跑 "learning_rate": 2e-5, # 微调学习率,太大容易震荡 "epochs": 5, # 小数据集 3-5 轮足够 "beam_size": 4 # 推理时束搜索宽度,平衡质量和速度 }这段配置里,max_input_length和max_target_length直接决定显存占用和生成质量。设太大显存爆,设太小摘要信息不全。learning_rate用 2e-5 是微调的常见起点,如果 loss 震荡就降到 1e-5。beam_size设为 4 是质量和速度的折中,设成 1 就是贪心解码,生成结果会比较单调。2.3 评测方案:ROUGE 为主,人工抽检为辅评测不能只看 loss。ROUGE 是摘要任务的标准指标,计算生成摘要和参考摘要的 n-gram 重叠度。ROUGE-1 看词级别重叠,ROUGE-2 看词组连贯性,ROUGE-L 看最长公共子序列。通常的做法是跑完测试集,输出三个指标的分数,再随机抽 20 条生成结果人工检查有没有事实错误。如果 ROUGE-1 能到 35 以上,对于本科毕设就算合格;能到 40 以上,答辩时就有底气了。3. 总体架构设计:四层结构与数据流向3.1 分层设计:从原始文本到最终摘要的完整链路整个系统分四层:数据预处理层、模型层、推理层、评测层。数据预处理层负责清洗文本、分词、截断、构造训练样本;模型层加载预训练权重,定义编码器-解码器结构;推理层实现束搜索解码,把模型输出转成自然语言;评测层计算 ROUGE 并输出报告。四层之间通过标准化的数据接口衔接,每层可以独立测试。这种分层的好处是调试方便。比如生成结果不通顺,可以先检查预处理层的分词有没有问题,再查模型层的输出分布,最后看推理层的解码策略。如果全写在一个脚本里,出了问题只能从头到尾翻代码,效率极低。3.2 数据流向:一条样本的完整生命周期一条训练样本的流转路径是这样的:原始正文经过清洗去掉特殊符号和多余空格,然后分词成 token 序列,超过 512 个 token 的截断,不足的补零。参考摘要同样处理,作为解码器的目标序列。训练时,编码器读入正文 token,解码器以自回归方式预测摘要 token,损失函数用交叉熵。推理时,编码器读入正文,解码器从起始符开始逐词生成,直到遇到结束符或达到最大长度。这里有个设计细节:训练时解码器的输入是“右移一位”的参考摘要,这叫 teacher forcing;推理时解码器只能看到自己生成的词,这叫自回归生成。两者不一致会导致曝光偏差,生成结果比训练时差。缓解办法是在训练后期混入一些模型自己生成的结果,但本科毕设阶段可以先不做,答辩时能说清楚这个概念就是加分项。3.3 模块划分与接口定义模块输入输出关键接口预处理原始文本token 序列preprocess(text)编码器正文 token上下文向量encode(input_ids)解码器上下文向量+已生成词下一个词概率decode(encoder_out, generated)推理正文 token摘要文本generate(text, beam_size)评测生成摘要+参考摘要ROUGE 分数evaluate(preds, refs)接口定义清楚之后,每个人可以并行开发自己的模块。比如做预处理的同学不用等模型写完,只要保证输出格式一致就能联调。这也是答辩时展示工程能力的一个点。4. 核心模块实现:预处理、模型微调与束搜索解码4.1 数据预处理:清洗、分词与样本构造预处理看着简单,实际上最容易翻车。中文文本里混着全角半角符号、HTML 标签、多余换行,不清洗干净直接喂给模型,生成结果里会冒出奇怪字符。分词用预训练模型自带的分词器,不要自己用 jieba 切完再喂,因为预训练模型的词表和 jieba 不匹配,会导致大量未知词。import re from transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("轻量级预训练模型") def preprocess(text, max_len=512): # 去掉 HTML 标签和多余空白 text = re.sub(r"<[^>]+>", "", text) text = re.sub(r"\s+", " ", text).strip() # 用预训练分词器编码,截断和补齐 encoded = tokenizer( text, max_length=max_len, truncation=True, padding="max_length", return_tensors="pt" ) return encoded def build_sample(article, summary): # 正文编码为输入,摘要编码为标签 inputs = preprocess(article) with tokenizer.as_target_tokenizer(): labels = tokenizer( summary, max_length=128, truncation=True, padding="max_length", return_tensors="pt" ) inputs["labels"] = labels["input_ids"] return inputspreprocess里的正则去掉 HTML 标签,truncation=True保证超长文本被截断,padding="max_length"统一长度方便批处理。build_sample把正文和摘要拼成训练样本,labels就是解码器的目标。注意as_target_tokenizer()这行,它确保摘要用和正文一致的分词规则,少了这行可能报错。4.2 模型微调:加载预训练权重与训练循环微调的核心是加载预训练权重,替换输出层适配摘要任务,然后用小学习率更新参数。训练循环里要监控 loss 和 ROUGE,loss 下降但 ROUGE 不涨说明过拟合了,得早停。from transformers import AutoModelForSeq2SeqLM, AdamW model = AutoModelForSeq2SeqLM.from_pretrained("轻量级预训练模型") optimizer = AdamW(model.parameters(), lr=2e-5) model.train() for epoch in range(5): total_loss = 0 for batch in train_loader: outputs = model( input_ids=batch["input_ids"], attention_mask=batch["attention_mask"], labels=batch["labels"] ) loss = outputs.loss loss.backward() optimizer.step() optimizer.zero_grad() total_loss += loss.item() print(f"Epoch {epoch+1}, Loss: {total_loss/len(train_loader):.4f}") # 每轮结束在验证集上算 ROUGE,决定是否早停AutoModelForSeq2SeqLM自动加载编码器-解码器结构,labels传入后模型内部计算交叉熵损失。AdamW是微调常用优化器,lr=2e-5是安全起点。训练轮数设 5 轮,如果验证集 ROUGE 在第 3 轮后不再提升就停,避免过拟合。显存不够就把batch_size降到 4,或者用梯度累积模拟大 batch。4.3 束搜索解码:让生成结果更连贯贪心解码每步选概率最大的词,容易生成重复、单调的句子。束搜索同时保留多条候选路径,最后选整体概率最高的。beam_size=4表示每步保留 4 条路径,计算量是贪心的 4 倍,但生成质量明显提升。def generate_summary(text, model, tokenizer, beam_size=4): inputs = preprocess(text) with torch.no_grad(): summary_ids = model.generate( input_ids=inputs["input_ids"], attention_mask=inputs["attention_mask"], num_beams=beam_size, max_length=128, early_stopping=True, no_repeat_ngram_size=3 # 禁止 3-gram 重复,减少复读 ) summary = tokenizer.decode(summary_ids[0], skip_special_tokens=True) return summarynum_beams=4控制搜索宽度,early_stopping=True让所有候选路径都生成结束后提前停止,no_repeat_ngram_size=3是防止生成“的的的”这种重复词组的后悔药。skip_special_tokens=True去掉解码时的起始符和结束符,输出干净文本。5. 避坑与常见问题排查:那些让 ROUGE 掉点的细节5.1 生成结果全是“的”“了”等高频词现象:模型生成的摘要读起来像乱码,反复出现“的”“了”“是”。原因:解码时没有加重复惩罚,或者训练数据里高频词占比过高。解决:在generate里加no_repeat_ngram_size=3和repetition_penalty=1.2,同时检查训练数据是否需要重采样。5.2 训练 loss 正常但 ROUGE 极低现象:loss 降到 0.5 以下,但测试集 ROUGE-1 不到 10。原因:预处理时正文和摘要的分词方式不一致,或者标签对齐错了。解决:检查as_target_tokenizer()是否用在摘要编码上,打印一条样本的input_ids和labels确认对齐。5.3 显存溢出导致训练中断现象:跑几个 batch 后报 CUDA out of memory。原因:max_input_length设太大,或者 batch_size 超过显存容量。解决:把输入长度从 512 降到 256,batch_size 从 8 降到 4,或者用梯度累积。如果还不行,换更小的预训练模型。5.4 推理速度慢到无法接受现象:生成一条摘要要十几秒。原因:束搜索宽度太大,或者模型在 CPU 上跑。解决:beam_size从 4 降到 2,确认模型加载到 GPU 上,用model.to("cuda")。如果必须用 CPU,换轻量级模型。5.5 摘要事实性错误,张冠李戴现象:生成摘要里出现原文没有的人名或数字。原因:生成式模型的幻觉问题,训练数据里存在噪声。解决:在预处理阶段过滤掉正文和摘要明显不匹配的样本,推理时降低temperature参数,让输出更保守。6. 验收与答辩:怎么证明你的摘要系统真的能用验收分三块:代码能跑通、指标能达标、答辩能讲清。代码部分,准备一个demo.py,输入一段新闻正文,输出摘要,现场演示。指标部分,在测试集上跑出 ROUGE-1、ROUGE-2、ROUGE-L 三个分数,做成表格。答辩部分,重点讲清楚三个问题:为什么选 Transformer、为什么走混合路线、ROUGE 分数说明了什么。验收项合格标准优秀标准代码可运行demo 能输出摘要支持批量输入和参数配置ROUGE-1≥ 30≥ 40ROUGE-2≥ 12≥ 18ROUGE-L≥ 28≥ 38人工抽检20 条中 15 条通顺20 条中 18 条通顺且无事实错误答辩时老师常问“你的创新点在哪”。本科毕设不要求算法创新,但可以讲工程创新:比如混合路线降低了显存需求,束搜索参数调优提升了连贯性,预处理流程解决了中文噪声问题。把这些点用数据支撑,比空谈“使用了深度学习”有说服力得多。还有一个技巧:准备一页 PPT 专门放失败案例。比如展示贪心解码生成的重复句子,再对比束搜索的结果,说明参数调优的价值。老师看到你分析过失败原因,印象分会高很多。从那以后我每次带项目,都强制在验收前跑一遍“最差样本分析”——把 ROUGE 最低的 10 条结果拉出来逐条看,往往能发现预处理或解码策略的隐藏问题。希望帮到你。本文还有配套的精品资源,点击获取
简介:这份资源是面向本科毕业设计场景的深度学习文本摘要自动生成项目,聚焦自然语言处理与Transformer模型的工程落地,适合具备一定Python基础、希望系统实践NLP课程设计或毕设的学生。压缩包共34个文件,约360KB,以18个Python脚本为核心,覆盖模型定义、数据预处理、训练与评估流程,另含5个Shell脚本用于训练与测试调度,以及txt、yml、vocab、Dockerfile等配置与词表文件,整体结构清晰、便于按模块阅读。项目围绕编码器-解码器架构展开,涉及分词、词汇表构建、序列化输入、损失函数与优化器配置,并引入ROUGE、BLEU等指标衡量摘要质量,同时提供beam search、强化学习训练等进阶实现,可帮助读者理解从数据到模型再到评价的完整链路。目前已有3764人学习下载,适合作为NLP方向毕设的参考方案与调试起点。1. 从一份“跑不通”的毕设说起:文本摘要自动生成到底要交什么很多同学做文本摘要自动生成这个本科毕业设计,卡住的地方往往不是模型本身,而是不知道一份合格的方案该长什么样。有人拿开源代码跑了一遍,生成几句不通顺的摘要就截图交差;有人把 Transformer 结构图画得漂漂亮亮,一问推理流程就说不清楚。这个项目的核心需求其实很明确:给定一段长文本,自动输出保留核心信息的短摘要,并且要有可复现的训练、推理和评测流程。它适合两类人——正在做自然语言处理方向毕设的本科生,以及需要快速搭一套摘要生成原型的从业者。关键词里的深度学习、Transformer、文本摘要,落到交付物上就是三样东西:一份能讲清设计逻辑的文档、一套能跑通的代码、一组能说服答辩老师的评测数据。下面按需求、设计、实现、避坑、验收的顺序,把这份方案拆开讲。2. 需求分析与技术选型:为什么是“抽取+生成”混合路线2.1 任务边界:摘要不是缩写,更不是关键词堆叠文本摘要自动生成在学术上分两类:抽取式(extractive)和生成式(abstractive)。抽取式从原文挑句子拼成摘要,优点是通顺、不易出错,缺点是冗余、不连贯;生成式用自己的话重新组织,优点是灵活,缺点是容易产生事实性错误,也就是常说的“幻觉”。本科毕设如果只做抽取式,工作量偏薄,答辩时容易被问“深度学习体现在哪”;只做生成式,训练不稳定,显存吃紧,最后可能连一个像样的结果都拿不出来。我一般建议走混合路线:先用抽取式做一轮句子筛选,把长文本压缩到模型能处理的长度,再用生成式模型做改写。这样既体现了深度学习的核心,又控制了工程复杂度。任务边界要写清楚:输入是单篇文档,输出是长度在 80 到 150 字之间的摘要,评测指标用 ROUGE-1、ROUGE-2、ROUGE-L。别小看这个边界定义,答辩时老师第一个问的就是“你的输入输出到底是什么”。2.2 技术选型:Transformer 做主干,预训练模型做底座选型这块,血泪经验是别从零训 Transformer。本科毕设的算力和数据量根本不够,从零训出来的模型生成的句子连语法都不对。通常的做法是拿预训练模型做微调,比如基于 Transformer 的编码器-解码器结构,编码器读原文,解码器逐词生成摘要。如果显存有限,可以选轻量级的预训练模型,参数量控制在 1 亿以内,单张消费级显卡就能跑。数据方面,中文摘要常用的是大规模新闻语料,每条包含正文和参考摘要。如果找不到合适的中文数据集,可以用英文数据集先跑通流程,再换中文小规模数据微调。这里有个坑:很多人直接拿预训练模型做零样本推理,结果 ROUGE 分数低得可怜,因为预训练任务和摘要任务差距很大,必须做微调。# 技术选型核心配置示例 config = { "model_name": "轻量级预训练模型", # 编码器-解码器结构 "max_input_length": 512, # 原文截断长度,覆盖大部分新闻正文 "max_target_length": 128, # 摘要最大长度,对应 80-150 字 "batch_size": 8, # 单卡显存 8G 左右可跑 "learning_rate": 2e-5, # 微调学习率,太大容易震荡 "epochs": 5, # 小数据集 3-5 轮足够 "beam_size": 4 # 推理时束搜索宽度,平衡质量和速度 }这段配置里,max_input_length和max_target_length直接决定显存占用和生成质量。设太大显存爆,设太小摘要信息不全。learning_rate用 2e-5 是微调的常见起点,如果 loss 震荡就降到 1e-5。beam_size设为 4 是质量和速度的折中,设成 1 就是贪心解码,生成结果会比较单调。2.3 评测方案:ROUGE 为主,人工抽检为辅评测不能只看 loss。ROUGE 是摘要任务的标准指标,计算生成摘要和参考摘要的 n-gram 重叠度。ROUGE-1 看词级别重叠,ROUGE-2 看词组连贯性,ROUGE-L 看最长公共子序列。通常的做法是跑完测试集,输出三个指标的分数,再随机抽 20 条生成结果人工检查有没有事实错误。如果 ROUGE-1 能到 35 以上,对于本科毕设就算合格;能到 40 以上,答辩时就有底气了。3. 总体架构设计:四层结构与数据流向3.1 分层设计:从原始文本到最终摘要的完整链路整个系统分四层:数据预处理层、模型层、推理层、评测层。数据预处理层负责清洗文本、分词、截断、构造训练样本;模型层加载预训练权重,定义编码器-解码器结构;推理层实现束搜索解码,把模型输出转成自然语言;评测层计算 ROUGE 并输出报告。四层之间通过标准化的数据接口衔接,每层可以独立测试。这种分层的好处是调试方便。比如生成结果不通顺,可以先检查预处理层的分词有没有问题,再查模型层的输出分布,最后看推理层的解码策略。如果全写在一个脚本里,出了问题只能从头到尾翻代码,效率极低。3.2 数据流向:一条样本的完整生命周期一条训练样本的流转路径是这样的:原始正文经过清洗去掉特殊符号和多余空格,然后分词成 token 序列,超过 512 个 token 的截断,不足的补零。参考摘要同样处理,作为解码器的目标序列。训练时,编码器读入正文 token,解码器以自回归方式预测摘要 token,损失函数用交叉熵。推理时,编码器读入正文,解码器从起始符开始逐词生成,直到遇到结束符或达到最大长度。这里有个设计细节:训练时解码器的输入是“右移一位”的参考摘要,这叫 teacher forcing;推理时解码器只能看到自己生成的词,这叫自回归生成。两者不一致会导致曝光偏差,生成结果比训练时差。缓解办法是在训练后期混入一些模型自己生成的结果,但本科毕设阶段可以先不做,答辩时能说清楚这个概念就是加分项。3.3 模块划分与接口定义模块输入输出关键接口预处理原始文本token 序列preprocess(text)编码器正文 token上下文向量encode(input_ids)解码器上下文向量+已生成词下一个词概率decode(encoder_out, generated)推理正文 token摘要文本generate(text, beam_size)评测生成摘要+参考摘要ROUGE 分数evaluate(preds, refs)接口定义清楚之后,每个人可以并行开发自己的模块。比如做预处理的同学不用等模型写完,只要保证输出格式一致就能联调。这也是答辩时展示工程能力的一个点。4. 核心模块实现:预处理、模型微调与束搜索解码4.1 数据预处理:清洗、分词与样本构造预处理看着简单,实际上最容易翻车。中文文本里混着全角半角符号、HTML 标签、多余换行,不清洗干净直接喂给模型,生成结果里会冒出奇怪字符。分词用预训练模型自带的分词器,不要自己用 jieba 切完再喂,因为预训练模型的词表和 jieba 不匹配,会导致大量未知词。import re from transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("轻量级预训练模型") def preprocess(text, max_len=512): # 去掉 HTML 标签和多余空白 text = re.sub(r"<[^>]+>", "", text) text = re.sub(r"\s+", " ", text).strip() # 用预训练分词器编码,截断和补齐 encoded = tokenizer( text, max_length=max_len, truncation=True, padding="max_length", return_tensors="pt" ) return encoded def build_sample(article, summary): # 正文编码为输入,摘要编码为标签 inputs = preprocess(article) with tokenizer.as_target_tokenizer(): labels = tokenizer( summary, max_length=128, truncation=True, padding="max_length", return_tensors="pt" ) inputs["labels"] = labels["input_ids"] return inputspreprocess里的正则去掉 HTML 标签,truncation=True保证超长文本被截断,padding="max_length"统一长度方便批处理。build_sample把正文和摘要拼成训练样本,labels就是解码器的目标。注意as_target_tokenizer()这行,它确保摘要用和正文一致的分词规则,少了这行可能报错。4.2 模型微调:加载预训练权重与训练循环微调的核心是加载预训练权重,替换输出层适配摘要任务,然后用小学习率更新参数。训练循环里要监控 loss 和 ROUGE,loss 下降但 ROUGE 不涨说明过拟合了,得早停。from transformers import AutoModelForSeq2SeqLM, AdamW model = AutoModelForSeq2SeqLM.from_pretrained("轻量级预训练模型") optimizer = AdamW(model.parameters(), lr=2e-5) model.train() for epoch in range(5): total_loss = 0 for batch in train_loader: outputs = model( input_ids=batch["input_ids"], attention_mask=batch["attention_mask"], labels=batch["labels"] ) loss = outputs.loss loss.backward() optimizer.step() optimizer.zero_grad() total_loss += loss.item() print(f"Epoch {epoch+1}, Loss: {total_loss/len(train_loader):.4f}") # 每轮结束在验证集上算 ROUGE,决定是否早停AutoModelForSeq2SeqLM自动加载编码器-解码器结构,labels传入后模型内部计算交叉熵损失。AdamW是微调常用优化器,lr=2e-5是安全起点。训练轮数设 5 轮,如果验证集 ROUGE 在第 3 轮后不再提升就停,避免过拟合。显存不够就把batch_size降到 4,或者用梯度累积模拟大 batch。4.3 束搜索解码:让生成结果更连贯贪心解码每步选概率最大的词,容易生成重复、单调的句子。束搜索同时保留多条候选路径,最后选整体概率最高的。beam_size=4表示每步保留 4 条路径,计算量是贪心的 4 倍,但生成质量明显提升。def generate_summary(text, model, tokenizer, beam_size=4): inputs = preprocess(text) with torch.no_grad(): summary_ids = model.generate( input_ids=inputs["input_ids"], attention_mask=inputs["attention_mask"], num_beams=beam_size, max_length=128, early_stopping=True, no_repeat_ngram_size=3 # 禁止 3-gram 重复,减少复读 ) summary = tokenizer.decode(summary_ids[0], skip_special_tokens=True) return summarynum_beams=4控制搜索宽度,early_stopping=True让所有候选路径都生成结束后提前停止,no_repeat_ngram_size=3是防止生成“的的的”这种重复词组的后悔药。skip_special_tokens=True去掉解码时的起始符和结束符,输出干净文本。5. 避坑与常见问题排查:那些让 ROUGE 掉点的细节5.1 生成结果全是“的”“了”等高频词现象:模型生成的摘要读起来像乱码,反复出现“的”“了”“是”。原因:解码时没有加重复惩罚,或者训练数据里高频词占比过高。解决:在generate里加no_repeat_ngram_size=3和repetition_penalty=1.2,同时检查训练数据是否需要重采样。5.2 训练 loss 正常但 ROUGE 极低现象:loss 降到 0.5 以下,但测试集 ROUGE-1 不到 10。原因:预处理时正文和摘要的分词方式不一致,或者标签对齐错了。解决:检查as_target_tokenizer()是否用在摘要编码上,打印一条样本的input_ids和labels确认对齐。5.3 显存溢出导致训练中断现象:跑几个 batch 后报 CUDA out of memory。原因:max_input_length设太大,或者 batch_size 超过显存容量。解决:把输入长度从 512 降到 256,batch_size 从 8 降到 4,或者用梯度累积。如果还不行,换更小的预训练模型。5.4 推理速度慢到无法接受现象:生成一条摘要要十几秒。原因:束搜索宽度太大,或者模型在 CPU 上跑。解决:beam_size从 4 降到 2,确认模型加载到 GPU 上,用model.to("cuda")。如果必须用 CPU,换轻量级模型。5.5 摘要事实性错误,张冠李戴现象:生成摘要里出现原文没有的人名或数字。原因:生成式模型的幻觉问题,训练数据里存在噪声。解决:在预处理阶段过滤掉正文和摘要明显不匹配的样本,推理时降低temperature参数,让输出更保守。6. 验收与答辩:怎么证明你的摘要系统真的能用验收分三块:代码能跑通、指标能达标、答辩能讲清。代码部分,准备一个demo.py,输入一段新闻正文,输出摘要,现场演示。指标部分,在测试集上跑出 ROUGE-1、ROUGE-2、ROUGE-L 三个分数,做成表格。答辩部分,重点讲清楚三个问题:为什么选 Transformer、为什么走混合路线、ROUGE 分数说明了什么。验收项合格标准优秀标准代码可运行demo 能输出摘要支持批量输入和参数配置ROUGE-1≥ 30≥ 40ROUGE-2≥ 12≥ 18ROUGE-L≥ 28≥ 38人工抽检20 条中 15 条通顺20 条中 18 条通顺且无事实错误答辩时老师常问“你的创新点在哪”。本科毕设不要求算法创新,但可以讲工程创新:比如混合路线降低了显存需求,束搜索参数调优提升了连贯性,预处理流程解决了中文噪声问题。把这些点用数据支撑,比空谈“使用了深度学习”有说服力得多。还有一个技巧:准备一页 PPT 专门放失败案例。比如展示贪心解码生成的重复句子,再对比束搜索的结果,说明参数调优的价值。老师看到你分析过失败原因,印象分会高很多。从那以后我每次带项目,都强制在验收前跑一遍“最差样本分析”——把 ROUGE 最低的 10 条结果拉出来逐条看,往往能发现预处理或解码策略的隐藏问题。希望帮到你。本文还有配套的精品资源,点击获取