当前位置: 首页 > news >正文

别只刷题了!用Python和PyTorch复现那些‘经典’的深度学习期末考题(附代码)

别只刷题了!用Python和PyTorch复现那些‘经典’的深度学习期末考题(附代码)

深度学习理论考试总让人头疼——公式推导、参数计算、概念辨析,稍不留神就会陷入"纸上谈兵"的困境。但换个角度想,这些试题本质上是检验我们对核心算法的理解程度。与其死记硬背,不如打开Jupyter Notebook,用代码将这些抽象问题具象化。本文将带你用PyTorch重新演绎五类经典考题,从反向传播实现到LSTM结构拆解,让理论在代码中"活"起来。

1. 反向传播的代码解剖

考试要求推导三层网络梯度?PyTorch的自动微分机制能让我们直观验证计算结果。先构建一个无激活函数的简易网络:

import torch # 试题参数初始化 x = torch.tensor([1.0], requires_grad=True) w1 = torch.tensor([0.5], requires_grad=True) w2 = torch.tensor([0.3], requires_grad=True) w3 = torch.tensor([0.2], requires_grad=True) # 前向传播 y = x * w1 * w2 * w3 print(f"前向输出值: {y.item()}") # 输出: 0.03

现在模拟考题要求计算梯度:

# 设置损失梯度为1.0 y.backward(torch.tensor([1.0])) print(f"dL/dw1: {w1.grad.item()}") # 0.06 (w2*w3*x) print(f"dL/dw2: {w2.grad.item()}") # 0.1 (w1*w3*x) print(f"dL/dw3: {w3.grad.item()}") # 0.15 (w1*w2*x)

对比手工计算:

  • $\frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial w_1} = 1.0 \times (w_2 w_3 x) = 0.3 \times 0.2 \times 1 = 0.06$

关键发现:通过.grad属性可以直接验证梯度计算是否正确。实践中建议用torch.autograd.grad()函数更灵活地获取特定梯度:

dy_dw1 = torch.autograd.grad(outputs=y, inputs=w1, retain_graph=True)[0]

2. 卷积网络参数实战

考试常见的卷积参数计算题,用PyTorch的nn.Conv2d可以直观验证。题目给出:

  • 输入尺寸:32×32×3
  • 卷积核:10个5×5,stride=1, padding=0
import torch.nn as nn conv = nn.Conv2d(in_channels=3, out_channels=10, kernel_size=5, stride=1, padding=0) input = torch.randn(1, 3, 32, 32) # batch=1 output = conv(input) print(f"输出特征图尺寸: {output.shape[2:]}") # torch.Size([1, 10, 28, 28])

参数数量计算:

  • 每个5×5卷积核有$5 \times 5 \times 3 = 75$个权重
  • 10个卷积核共$75 \times 10 = 750$权重参数
  • 每个卷积核1个偏置,共$10$个偏置参数
  • 总计$750 + 10 = 760$个可训练参数

提示:使用sum(p.numel() for p in conv.parameters())可自动统计参数总量

添加池化层验证:

pool = nn.MaxPool2d(kernel_size=2, stride=2) pool_output = pool(output) print(f"池化后尺寸: {pool_output.shape[2:]}") # torch.Size([1, 10, 14, 14])

3. Word2Vec模型对比实现

CBOW和Skip-gram的结构差异常出现在简答题中。下面用PyTorch实现两者的核心区别:

class CBOW(nn.Module): def __init__(self, vocab_size, embedding_dim): super().__init__() self.embeddings = nn.Embedding(vocab_size, embedding_dim) self.linear = nn.Linear(embedding_dim, vocab_size) def forward(self, context): # context: [batch, 2*window_size] embeds = self.embeddings(context).mean(dim=1) # 上下文词向量平均 return self.linear(embeds) class SkipGram(nn.Module): def __init__(self, vocab_size, embedding_dim): super().__init__() self.embeddings = nn.Embedding(vocab_size, embedding_dim) self.linear = nn.Linear(embedding_dim, vocab_size) def forward(self, target): # target: [batch, 1] embeds = self.embeddings(target).squeeze(1) return self.linear(embeds)

架构对比表

特性CBOWSkip-gram
输入上下文词索引目标词索引
输出目标词概率分布上下文词概率分布
计算效率适合高频词适合低频词
数学本质上下文词向量的均值预测目标词目标词向量预测上下文词分布

负采样实现示例:

# 负采样损失函数 neg_loss = -torch.log(torch.sigmoid(pos_score)) - \ torch.sum(torch.log(torch.sigmoid(-neg_scores)))

4. LSTM长期依赖解决方案

用代码揭示LSTM如何解决RNN的梯度消失问题。关键在门控机制:

class CustomLSTMCell(nn.Module): def __init__(self, input_size, hidden_size): super().__init__() # 输入门、遗忘门、输出门、候选记忆 self.gates = nn.Linear(input_size + hidden_size, 4*hidden_size) def forward(self, x, hc): h, c = hc gates = self.gates(torch.cat([x, h], dim=1)) i, f, o, g = gates.chunk(4, 1) # 拆分为四个部分 i, f, o = torch.sigmoid(i), torch.sigmoid(f), torch.sigmoid(o) g = torch.tanh(g) new_c = f * c + i * g # 记忆更新公式 new_h = o * torch.tanh(new_c) return new_h, new_c

门控机制解析

  1. 遗忘门($f_t$)控制历史记忆保留量
  2. 输入门($i_t$)调节新记忆的写入比例
  3. 候选记忆($\tilde{C}_t$)存储当前时间步的新信息
  4. 输出门($o_t$)决定隐藏状态的输出比例

可视化门控信号变化:

plt.plot(forget_gate_history, label='Forget Gate') plt.plot(input_gate_history, label='Input Gate') plt.legend()

5. Attention机制代码演绎

Seq2Seq的注意力改进方案,通过代码展示其工作原理:

class Attention(nn.Module): def __init__(self, enc_dim, dec_dim): super().__init__() self.attn = nn.Linear(enc_dim + dec_dim, dec_dim) self.v = nn.Parameter(torch.rand(dec_dim)) def forward(self, hidden, encoder_outputs): # hidden: [1, batch, dec_dim] # encoder_outputs: [seq_len, batch, enc_dim] seq_len = encoder_outputs.shape[0] hidden = hidden.repeat(seq_len, 1, 1) # 沿序列维度复制 energy = torch.tanh(self.attn(torch.cat((hidden, encoder_outputs), dim=2))) energy = energy.permute(1, 2, 0) # [batch, dec_dim, seq_len] v = self.v.repeat(encoder_outputs.size(1), 1).unsqueeze(1) attention = torch.bmm(v, energy).squeeze(1) # [batch, seq_len] return torch.softmax(attention, dim=1)

注意力计算流程

  1. 将解码器隐藏状态与所有编码器输出拼接
  2. 通过全连接层和tanh激活计算能量值
  3. 使用可学习参数$v$计算注意力分数
  4. 应用softmax归一化得到注意力权重

对比传统Seq2Seq与Attention的效果差异:

# 传统Seq2Seq output, hidden = decoder(input, hidden) # 加入Attention后 attn_weights = attention(hidden, encoder_outputs) context = torch.bmm(attn_weights.unsqueeze(1), encoder_outputs.transpose(0, 1)) output, hidden = decoder(input, torch.cat((context, hidden), dim=2))
http://www.jsqmd.com/news/618320/

相关文章:

  • MeteorSeed隙
  • OpenClaw自动化测试:gemma-3-12b-it验证100个任务指令的准确率
  • 如何构建毫秒级响应的大规模在线游戏:ET框架的预测同步技术终极指南
  • (十五)32天GPU测试从入门到精通-图像分类模型性能对比day13
  • 从Shell命令到C程序:拆解`system(“ls -l“)`,看execve和fork如何幕后协作
  • 别再只用命令行!Claude Code接入VSCode和PyCharm,这些技巧让你爽到飞起!
  • 从手机拍照到自动驾驶:聊聊低光图像数据集(BDD-100k、DPDE、LSRW)背后的真实应用场景
  • ROS 2环境下的YOLO视觉感知系统:从2D检测到3D定位的完整指南
  • 终极Mac桌面歌词神器:LyricsX让你的音乐体验更完美
  • 计算机软件的作用
  • 【数据结构】环形队列(循环队列)实战:从原理到C语言高效实现
  • 用ESP32-S3和SenseVoice,手把手教你打造一个能听懂中文的离线语音助手(附完整代码)
  • 如何在5分钟内彻底优化Windows系统性能?Winhance中文版终极指南
  • 重庆雅田实业(集团)有限公司:高新区老旧房改造宅基地改造公司电话 - LYL仔仔
  • Google CEO执掌十年后的一次坦率对话
  • 深入解析rewriteBatchedStatements:如何通过SQL重写提升MySQL批处理性能
  • LeetCode 1356. 根据数字二进制下1的数目排序 超详细技术解析(Python)
  • D3KeyHelper:暗黑3智能按键助手,彻底告别手部疲劳的游戏效率神器
  • 别再只收邮件了!用飞书收Zabbix告警的3个实战技巧与消息模板优化
  • 避坑指南:在Windows上用Anaconda配置YOLOv11+ByteTrack环境,解决OpenCV和CUDA版本冲突
  • Adafruit GFX Library:嵌入式图形渲染的终极解决方案
  • 2026年东莞苏州分板机生产厂家排名,靠谱品牌推荐哪家 - mypinpai
  • 3步破解Realtek 8192FU无线网卡Linux兼容性难题
  • 电机控制(一)——FOC算法
  • 5分钟高效字幕解决方案:VideoSrt智能语音识别工具
  • 当AI学会“自己干活”:电商行业迎来智能体协同新时代
  • 基建狂魔的“安全前置”:地下管线探测/电缆探测服务如何成为新工地开工标配 - 品牌推荐大师
  • Layui弹出层layer怎么设置不显示遮罩层但禁止操作底部
  • 高效排版新选择:华中科技大学毕业论文LaTeX模板完整指南
  • 华为Hi1822 16G FC光纤卡驱动安装全攻略(CentOS7.6实测避坑指南)