ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Bi-LSTM + Attention 从原理到实战:PyTorch 实现与课程设计指南

Bi-LSTM + Attention 从原理到实战:PyTorch 实现与课程设计指南 简介这是一份基于Python的深度学习课程作业完整方案面向计算机、人工智能等专业学生和初学深度学习的小白用于文本分类/意图识别课程设计或答辩演示。项目以Bi-LSTMAttention为核心涵盖数据处理、模型构建、训练评估与结果可视化全套源代码并附课程论文、配套数据集、答辩PPT和模型权重拿到后可直接运行复现实验结果。资源包共25个文件压缩后约6.71MB其中9个py脚本负责数据统计、数据加载、模型训练与可视化2个pt文件保存模型权重9个txt记录训练/验证损失与准确率变化另含README、PDF论文和PPTX答辩演示方便对照说明快速上手。已有160人学习浏览适合完成课设作业、入门LSTM注意力机制也可在此基础上扩展其他分类任务对运行不熟的初学者下载后可联系作者获取答疑或远程指导。1. 毕业设计的“全家桶”Bi-LSTM Attention 为什么是课程作业的默认答案如果你是计算机或人工智能相关专业的学生大概率在某个学期末见过这个标题Python 深度学习课程作业Bi-LSTM Attention 源代码、文档、数据集、PPT、论文、模型全打包。刚看到时你可能觉得它是个“代做广告”但作为带过不少学生跑课设的人我得说一句公道话——Bi-LSTM Attention 几乎是课程作业的“黄金组合”模型结构不复杂、原理讲得清楚、效果比普通 RNN/LSTM 好一截而且代码公开资料多踩坑答案也全。这也是为什么每年这时候总有学生拿着类似标题的资源来找我救火。这个“全家桶”方案能解决的核心问题很实际你只有两周到一个月的时间需要交代码、交文档、交 PPT还要能现场讲清楚模型在干什么。Bi-LSTM 负责捕捉上下文信息Attention 负责告诉模型“哪些词更重要”两者一拼就是一篇能写 30 页以上的课程设计。适合的人群也很清晰——正在选课设题目、或者已经选了文本分类 / 情感分析这类任务但不知道怎么落地的人。唯一要提醒的是拿到这份资源只是开始跑通和讲明白才是真本事别指望文件解压就等于作业完成。2. 先吃透原理再动手Bi-LSTM 为什么需要 Attention以及它们各自解决什么问题2.1 从 LSTM 门控机制说起为什么长文本里普通 RNN 会“失忆”很多初学者直接拿 Bi-LSTM 的代码跑发现效果不错但说不出为什么。咱们先垫一层地基RNN 处理序列数据时理论上能记住前面所有信息但实际训练中梯度在反向传播时会逐层衰减导致网络只能记住近处的内容这就是所谓的“长期依赖”问题。LSTM 的改进思路是引入门控机制——输入门、遗忘门、输出门——让网络学会主动决定“哪些信息要记住、哪些要扔掉”。当 t 时刻的输入进来时遗忘门根据当前输入和上一时刻的输出计算一个 0 到 1 之间的值决定上一时刻的记忆细胞要保留多少输入门决定新信息写入多少输出门决定当前状态的输出。这套机制有效缓解了梯度消失让 LSTM 能处理比普通 RNN 长得多的序列。问题在于标准的 LSTM 是单向的。以情感分析为例“这家餐厅虽然环境不错但服务态度极差”这句话里“虽然”和“但”之间的转折关系决定了情感极性是负面的。单向 LSTM 处理这句话时模型在读到“不错”时并不知道后面有转折只能带着“正面”的印象继续编码直到看到“差”才修正。这种信息传递的单向性在自然语言处理里是致命的——一句话的意思往往由前后的上下文共同决定。这也是为什么在处理这类任务时很少有人直接用单向 LSTM。2.2 双向只是拼接吗Bi-LSTM 的两种输出方式与特征拼接Bi-LSTM 的架构理解起来很简单一个 LSTM 按原序列顺序从左往右读另一个 LSTM 按逆序从右往左读每个时间步将两个方向得到的隐状态拼接。注意这里说的是“拼接”而不是“相加”——前向和后向的隐状态维度各为 hidden_size拼接后变成 2 × hidden_size后续 Attention 层拿到的是包含前后语境的完整向量。常见做法是将两个方向最后的隐状态拼接成句向量或者把每个位置的前向隐状态拼接后作为 Attention 的输入。对于分类任务我一般取每个位置拼接后的完整序列交给 Attention对于序列标注任务则直接使用整条序列。很多人在这一步犯糊涂双向 RNN 的梯度计算和训练复杂度与单向相比几乎翻倍这是有代价的。也因此如果你的数据集非常短比如每条样本只有四五个词双向带来的提升可能并不明显。一个实用的经验规则当序列平均长度超过 15 个词时双向结构带来的收益足以抵消训练时间的翻倍短文本任务则可以先跑单向 LSTM 作为 baseline看看差距再决定是否升级。此外Bi-LSTM 的输出不一定要全部送入 Attention——如果你的任务只需要整个句子的表示也可以只拼接两个方向的最终隐状态这相当于把 Attention 层去掉直接接全连接分类器。但这样一来模型少了一个重要的可解释层论文里能分析的内容也会少。2.3 Attention 加在哪从“加权求和”到 Decoder 场景的延伸理解学生最常问的一句话是Attention 到底放在哪层答案是放在 Bi-LSTM 输出之后、分类器之前。Attention 做的事情用一句话概括就是“对序列中每个位置的隐状态进行加权求和权重由模型自己学出来”。更具体地说Attention 层的输入是 Bi-LSTM 的所有时间步输出形状为 [batch_size, seq_len, 2 × hidden_size]它会通过一个可学习打分函数计算每个时间步的分数再用 softmax 归一化成权重。这些权重乘以对应位置的隐状态后求和得到整个序列的加权表示。这个最终向量就是全连接分类器的输入。在课程作业这个层面你用到的是最常见的加性 Attention——如 Bahdanau Attention 般的做法。把 Bi-LSTM 每个位置的隐状态 h_i 与一个可学习的向量 u 做点乘再经 tanh 激活后得到每个位置的注意力得分最后用 softmax 得到权重。如果你的论文写到了机器翻译或 Seq2Seq 场景需要理解另一种用法Decoder 侧在生成每个词时会拿当前的隐状态Query去和 Encoder 的所有隐状态Key计算相似度得到针对当前时刻的上下文向量。这个机制和分类任务中的“全局池化式 Attention”有一个本质差异分类任务权重是静态的Decoder 里权重是动态的、每步都不同。写论文时遇到“A generic attention module for a decoder in seq2seq pytorch”这类搜法千万别把它和课程作业里用的 Attention 混为一谈。2.4 用一张表理清三种结构的关系很多同学把 Bi-LSTM 和 Attention 当成两个并列的研究对象其实它们是串行关系。我习惯用一张表来解释它们在各自位置上做了什么模块输入输出解决的问题词嵌入层词索引序列 [batch, seq_len]词向量 [batch, seq_len, embedding_dim]把离散的单词 ID 映射成稠密向量Bi-LSTM词向量序列每个位置的前向后向隐状态 [batch, seq_len, 2×hidden]捕捉双向上下文语义Attention全部时间步的隐状态加权求和后的句向量 [batch, 2×hidden]让模型关注对分类更关键的信息全连接Softmax句向量类别概率分布实现最终的分类决策理解表格里每一行“输入和输出”的形状变化比死记公式有用得多。因为代码里出现频率最高的报错就是维度不匹配——打印每一层的输出形状是调试深度学习模型的基本功。在深度学习框架里你调试时最常用的工具就是打印张量形状至少在 PyTorch 里你可以直接 print 中间变量的 shape 来定位问题。3. 把 Bi-LSTM Attention 跑通环境准备、数据集处理和最小可运行代码3.1 环境踩坑Python 版本、NumPy 版本和 PyTorch 的三角关系先说环境。标题里的 python 是基础但绝大多数新手栽在版本组合上。PyTorch 官方对 Python 版本有明确要求PyTorch 2.x 支持 Python 3.8 到 3.12但这不代表你把 Python 装到最新版就万事大吉。我见过太多学生把 Python 装到 3.13然后用 pip 安装 PyTorch 时发现找不到预编译包最后只能降级重装。课程作业场景下我一般建议直接用 Anaconda 建一个独立环境指定 Python 3.9 或 3.10这两个版本对所有常用库的兼容性最稳妥。# 创建虚拟环境并指定 Python 版本 conda create -n bilstm_attention python3.9 -y # 激活环境 conda activate bilstm_attention # 安装 PyTorchCPU 版够课程作业用不必装 CUDA pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu # 安装其他依赖 pip install numpy pandas scikit-learn matplotlib jieba这段命令用 conda 建了独立环境避免和系统 Python 冲突。PyTorch 的 CPU 版本整个安装包体积在 200MB 左右但对课程作业这个规模的数据集来说完全够用——CPU 跑一个 LSTM 分类任务每秒能处理几千个短句训练一轮不过几秒到几十秒。如果租用 GPU 服务器则另说。需要特别注意的是 numpy 版本PyTorch 2.x 要求 numpy 1.22 以上Anaconda 默认带的旧版本会报 “np.float_ was removed” 一类的错误所以这里安装命令里显式指定了 numpy 和 scikit-learn。3.2 数据集处理短文本分类用什么、长文本可能遇到的问题课程作业的数据集选择非常灵活。最常见的是中文评论情感二分类正面/负面、新闻主题分类、或者英文的 IMDb 影评。如果标题里的“数据集”对应的是一个压缩包打开后通常是 CSV 或 Excel 格式里面至少有两列一列是文本内容一列是标签。处理流程固定读取文件 - 分词中文用 jieba英文直接按空格切- 构建词表 - 将文本转成索引序列 - 统一长度padding- 划分训练集和验证集。import pandas as pd import jieba from collections import Counter import torch from torch.utils.data import Dataset, DataLoader # 读取 CSV 数据 df pd.read_csv(data/comment.csv) # 假设列名为 text 和 label # 中文分词 df[tokens] df[text].apply(lambda x: list(jieba.cut(x))) # 构建词表保留出现频率最高的 5000 个词 vocab {pad: 0, unk: 1} counter Counter() df[tokens].apply(counter.update) for word, freq in counter.most_common(5000): vocab[word] len(vocab) # 文本转索引序列 df[ids] df[tokens].apply( lambda tokens: [vocab.get(w, vocab[unk]) for w in tokens] ) # 统一序列长度截断或补零 max_len 64 df[ids] df[ids].apply( lambda ids: ids[:max_len] [0] * (max_len - len(ids)) if len(ids) max_len else ids[:max_len] )这段代码里词表只保留前 5000 个高频词低频词统一映射成unk这是控制模型规模的关键。max_len设为 64 是经验值短文本场景几乎能覆盖所有样本如果你用的是长文档数据比如新闻正文建议先统计一下句子长度分布再决定。直接用固定 64 会导致长文本被大量截断信息丢失严重。养成打印长度分布的习惯df[tokens].str.len().describe()能看到均值、最大值和分位数这是定位数据问题的第一步。3.3 模型结构写一个 60 行不到的 Bi-LSTM Attention 类数据准备好后模型本身并不长。PyTorch 里继承 nn.Module 写一个类即可。import torch import torch.nn as nn import torch.nn.functional as F class BiLSTMAttention(nn.Module): def __init__(self, vocab_size, embedding_dim, hidden_size, num_labels): super().__init__() self.embedding nn.Embedding(vocab_size, embedding_dim, padding_idx0) self.lstm nn.LSTM( embedding_dim, hidden_size, num_layers2, batch_firstTrue, bidirectionalTrue, dropout0.3 # 使用多层 LSTM 时需要设置 dropout ) # Attention 可学习参数 self.attn_weight nn.Parameter(torch.randn(hidden_size * 2)) self.classifier nn.Linear(hidden_size * 2, num_labels) def forward(self, x): # x: [batch_size, seq_len] embedded self.embedding(x) # [batch, seq_len, embedding_dim] lstm_out, _ self.lstm(embedded) # [batch, seq_len, hidden_size * 2] # 加性 Attention attn_logits torch.tanh(lstm_out) self.attn_weight # [batch, seq_len] attn_weights F.softmax(attn_logits, dim1) # 每个位置的权重 # 加权求和得到句向量 context torch.sum(lstm_out * attn_weights.unsqueeze(-1), dim1) logits self.classifier(context) return logits这段代码有几个关键点需要说明。padding_idx0 表示词表里索引 0 对应的pad不会参与梯度更新这是避免 padding 部分干扰训练的标准做法。nn.LSTM 的 num_layers2 代表堆叠两层双向 LSTM此时需要设置 dropout 防止过拟合——高层 LSTM 的输出会以 0.3 的概率随机丢弃。Attention 的实现用的是加性打分也即每个位置先过 tanh 激活再与向量 attn_weight 做点积形状上特意把 attn_weights 扩展了一维实现对每个隐状态向量的加权。这种实现方式比 QKV 形式的 Attention 更直观也更好向答辩老师解释。3.4 训练循环损失函数、优化器和 30 行代码跑通全流程加工数据、定义模型之后训练代码的基本框架如下。我这里用了交叉熵损失和 Adam 优化器。epochs 设为 10batch_size 设为 32这是课程作业里最稳的一组默认参数。from torch.utils.data import TensorDataset, DataLoader import numpy as np # 准备训练数据 X torch.tensor(np.array(df[ids].tolist())) y torch.tensor(df[label].tolist()) # 划分训练集和验证集 total len(X) train_num int(total * 0.8) train_dataset TensorDataset(X[:train_num], y[:train_num]) val_dataset TensorDataset(X[train_num:], y[train_num:]) train_loader DataLoader(train_dataset, batch_size32, shuffleTrue) val_loader DataLoader(val_dataset, batch_size32, shuffleFalse) device torch.device(cuda if torch.cuda.is_available() else cpu) model BiLSTMAttention(len(vocab), embedding_dim128, hidden_size128, num_labels2).to(device) loss_fn nn.CrossEntropyLoss() optimizer torch.optim.Adam(model.parameters(), lr1e-3) for epoch in range(10): model.train() total_loss 0 for batch_x, batch_y in train_loader: batch_x, batch_y batch_x.to(device), batch_y.to(device) logits model(batch_x) loss loss_fn(logits, batch_y) optimizer.zero_grad() loss.backward() optimizer.step() total_loss loss.item() # 验证 model.eval() correct 0 total 0 with torch.no_grad(): for batch_x, batch_y in val_loader: batch_x, batch_y batch_x.to(device), batch_y.to(device) logits model(batch_x) preds logits.argmax(dim-1) correct (preds batch_y).sum().item() total batch_y.size(0) print(fEpoch {epoch 1}, Loss: {total_loss / len(train_loader):.4f}, Acc: {correct / total:.4f})Embedding 维度设为 128、隐藏层设为 128是性价比最高的组合。如果你用的是 GPU 资源可以把这两个参数翻倍到 256准确率可能提升 1-2 个百分点但在 CPU 机器上训练时间会翻近四倍不太值得。学习率固定用 1e-3Adam 优化器对这个学习率不敏感属于典型的“最稳妥起点”。发现训练不收敛时先从学习率打印机到 5e-4比调整任何其他参数都管用。4. 课程设计论文怎么写从结构搭建到论证逻辑的完整模板4.1 论文结构章节顺序和每章内容分配论文部分不能只是“写代码 贴结果”需要足够的文字把原理讲透也要有思路的推演过程。课程作业的论文一般要求 5000 到 8000 字章节安排可以按七章展开绪论背景和意义、相关技术、总体设计、模型设计、实验与结果分析、总结与展望。前两章重在文献综述第三四章要与代码对应第五章要放实验数据。如果你拿到的是现成的论文材料注意检查它是否包含“章节、图、表、参考文献”四件套——课程答辩老师抽查时主要看参考文献是否规范。文献综述部分不用写得像硕士论文那样气势磅礴两到三段即可覆盖第一段讲传统词向量方法和 RNN 的不足第二段讲 LSTM 的改进和双向化第三段讲 Attention 机制的出现和应用。如果在“rnn vs lstm”这类早期论文中找不到合适的引用可以用两篇基础文献代替一篇是 Hochreiter 与 Schmidhuber 的 LSTM 原始论文另一篇是 Bahdanau 等人关于注意力机制的论文。对于课程作业级的论文这两篇已经足够撑起理论框架。4.2 实验设计与写进论文的指标实验部分要强调对照实验。不要只展示 Bi-LSTM Attention 的最终结果老师更希望看到中间过程。常见的做法是至少设计三组对比单层 LSTM、Bi-LSTM不加 Attention、Bi-LSTM Attention。三组模型用相同的数据、词表、参数设置仅改变模型结构。这样才能论证 Attention 的增量提升到底来自哪里。下表是一个典型的实验结果展示模板模型准确率精确率召回率F1 值LSTM78.2%76.9%77.5%77.2%Bi-LSTM81.5%80.9%81.3%81.1%Bi-LSTM Attention85.4%85.3%84.1%84.7%这类结果表格体现了对比实验设计的价值。准确率之外还要展示精确率、召回率和 F1 值因为分类任务中数据类别可能不平衡——比如你的正负样本比例是 7:3 而不是 5:5。只看准确率完全无法发现模型对少数类失效的问题。如果你实在没有时间跑三组实验可以保留一组已经跑好的结果但至少要详细解释评估指标的计算方法。4.3 用 Attention 权重做可视化一张图让论文立增深度这是让课程设计论文“看起来很有深度”的常用技巧。从任意一条样本中取出 Attention 层的 attn_weights打印出权重最高的几个词用 matplotlib 画一张柱状图或热力图展示模型重点关注了哪些词。这个可视化不仅展示效果好还能验证模型是否学对了——比如情感分析里模型应该关注“好”“差”“喜欢”这类词而不是“的”“了”等停用词。import matplotlib.pyplot as plt def visualize_attention(model, text, vocab, tokenizer): # 分词并转索引 tokens list(tokenizer(text))[:64] ids [vocab.get(w, vocab[unk]) for w in tokens] ids ids [0] * (64 - len(ids)) x torch.tensor([ids]).to(device) model.eval() with torch.no_grad(): embeds model.embedding(x) lstm_out, _ model.lstm(embeds) attn_logits torch.tanh(lstm_out) model.attn_weight attn_weights F.softmax(attn_logits, dim1).squeeze(0).cpu().numpy() # 只取前 20 个有效词 tokens [t for t in tokens if t ! pad] attn_weights attn_weights[:len(tokens)] plt.figure(figsize(8, 4)) plt.bar(range(len(tokens)), attn_weights) plt.xticks(range(len(tokens)), tokens, rotation60) plt.tight_layout() plt.show()这段代码从已训练好的模型中取出注意力权重打印出模型对每个词的关注度。答辩时这张图几乎可以回答所有“模型有没有学到东西”的提问——你直接指出“模型把注意力集中在情感词上”比任何量化指标都更有说服力。这也是为什么我每次做课设都建议学生至少跑一张这个图。5. 避坑与排查我的训练过程全在报错80% 的问题都出在这五个地方5.1 维度不匹配Tensor 的 shape 全跟着 batch_first 走现象forward 里某个张量运算直接报 “Expected size X, got Y”或者 matmul 报维度不匹配。原因PyTorch 的 nn.LSTM 默认输入形状是 [seq_len, batch_size, embedding_dim]但 DataLoader 输出的是 [batch_size, seq_len]。如果你创建 LSTM 时没写 batch_firstTrue那 forward 接收到的张量要经过 transpose 才能送去 LSTM很多人两种写法混用代码能过就对不上了。解决要么全部用 batch_firstTrue要么统一先 x x.transpose(0, 1)。我个人强烈建议前者因为它让所有后续操作Attention、分类器都能直接沿用 batch 在第一维的逻辑。改完以后打印模型每一步的 shape 并和设计表格比对。5.2 效果很差准确率在 50% 左右原地踏步标注反了或标签不均衡现象训练几轮后准确率一直徘徊在 50% 上下loss 能下降但 Acc 纹丝不动。原因最常见的就是标签映射反了。CSV 文件里 label 列是字符串“正面”“负面”你直接 .map({正面: 1, 负面: 0}) 时写反了或者 label 原本是 1 和 2你没减 1 导致变成了二分类标签偏移。另一个常见原因是数据不均衡——90% 的样本是正类那么一直预测正类也能获得 90% 准确率这时需要打印每类别的精确率和召回率来观察。解决先用一行命令检查分布df[label].value_counts()确保标签的数值范围是 0 到 num_labels-1 且正负样本比例在合理范围内。如果比例极端如 9:1不要盲目使用原始准确率改用加权 F1 分数或混淆矩阵评估模型。5.3 验证集比训练集还高忘记切换 eval 模式或数据泄漏现象验证集准确率高于训练集 5 个百分点以上这看起来是“天选模型”但事出反常必有妖。原因最常见的是 forward 里使用了 dropout 或 BatchNorm训练时只调了 model.train()验证时忘了 model.eval()导致验证时丢弃和归一化行为与训练不一致。另一个更隐蔽的原因是数据划分前做了全量标准化或词表构建——用全量文本构建词表本身没问题但如果做了词频统计并过滤低频词这一步在划分前和划分后是不一样的。解决训练循环里把 model.eval() 和 with torch.no_grad() 一起用。同时检查数据划分逻辑先划分再预处理任何基于全体样本统计的操作比如标准化、词表筛选、缺失值填补都只允许在训练集上进行。这是新手最容易犯的隐蔽错误。5.4 显存内存溢出或训练奇慢无比序列长度和模型宽度没控制住现象跑第一个 epoch 就内存溢出或者一个 epoch 要跑十几分钟。原因max_len 设置过大比如 512加上 hidden_size 256 加上 batch_size 64在 CPU 机器上内存和计算量都可能爆表。另一个常见的低级原因是词表太大——你用了全部词汇而不是截断Embedding 层的参数量直接到了几百万。解决尝试验证集把 max_len 减到 64 或 128batch_size 减到 16。先用一小批数据比如 100 条试跑确认内存和时间消耗正常后再全量训练。深度学习训练的首要经验是不要在第一次全量跑时就把参数调到最大这相当于在没有任何资源评估的情况下上线生产环境。5.5 复现不了别人的结果随机种子固定了吗现象同一个数据集、同一个模型别人准确率 85%你跑出来 80%自己换个时间再跑结果又不一样。原因深度学习训练过程涉及权重随机初始化、数据随机打乱、dropout 随机丢弃等多个随机源。不设置随机种子每次训练结果都会不同。课程作业里这不算事故但写论文里“实验结果”部分如果连自己都无法复现答辩被老师抓到就会很难看。解决在代码开头固定所有随机种子只是常规做法。import random import numpy as np import torch seed 42 random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed_all(seed)固定种子确保了数据打乱顺序和权重初始化方式一致也可以保证论文实验可复现。答辩时如果有人质疑你的结果直接说“固定了所有随机源”比辩解逻辑要硬气得多。这个习惯建议长期保留不只是课程作业——任何深度学习的实验代码都应该默认带上这段。6. 把代码写成毕业设计的样子模块化重写、答辩准备和验收清单前面跑通的代码是单文件脚本能完成训练和预测但作为课程设计的代码交付物这远远不够。课程设计的代码评审通常会看重几个维度代码是否能直接运行、是否有清晰目录结构、是否有注释和 README、模型是否保存并可加载。我建议你把单文件拆成几个模块data_loader.py 负责数据读取与预处理、model.py 放模型结构、train.py 放训练循环、predict.py 放推理脚本、main.py 串联全流程。拆分之后代码行数看似变多了但答辩演示和后续维护都更方便。模型保存和加载自然也要做。PyTorch 里最稳妥的保存方式是同时保存 state_dict 和整个模型类定义这样可以在未知环境中重新实例化并加载权重。注意不要只保存整个 model 对象因为如果代码文件和训练环境不一致加载时会报错。正确做法是# 保存 torch.save(model.state_dict(), saved_model/bilstm_attention.pt) # 加载 model BiLSTMAttention(len(vocab), embedding_dim128, hidden_size128, num_labels2) model.load_state_dict(torch.load(saved_model/bilstm_attention.pt)) model.eval()这里加载模型的代码要求你不能改词表大小、embedding_dim、hidden_size 等参数否则加载会报维度错。这也是答辩时最容易翻车的点——改完模型参数忘了重新训练直接加载旧权重。把它列入你的检查清单每次修改模型结构后清空 saved_model 目录再重新训练。Attention 权重的可视化脚本也要保留在项目里并用单独文件保存。答辩现场的节奏通常是先用 PPT 讲背景和模型结构然后现场运行预测脚本演示几个实例最后展示一张注意力可视化图。这三步做完基本就能证明代码是自己跑通的了。最后说一个血泪经验把所有代码和结果在一个干净环境里完整跑一遍从 conda create 到最后预测期间不使用任何已安装的依赖之外的东西。这个环境甚至可以是刚装好的另一台电脑这样能避免“在我电脑上能跑”的尴尬。如果整个过程能 30 分钟内顺完答辩演示就不会出大问题。这条经验是我带课设这些年踩坑最多的地方写在这里希望帮到你。本文还有配套的精品资源点击获取
返回列表