
简介这份资源是《Deep Learning with PyTorch》的官方样本PDF面向希望入门PyTorch与深度学习实践的开发者、学生及研究人员帮助读者在正式购书前了解全书结构与核心内容。压缩包内仅含1个PDF文件大小约399KB属于轻量级样章文档便于快速浏览与试读。目前已有138人学习下载可作为评估是否深入学习的参考。样章内容涵盖深度学习模型训练的基础要素包括数据收集、训练循环实现、使用tqdm报告训练进度以及通过数据预处理提升模型性能同时包含一个回归模型构建项目涉及数据集描述、模型搭建与训练过程并演示如何收集训练统计信息以判断超参数调整方向。此外还介绍了DataLoader与Dataset类的用法帮助读者理解数据迭代与批处理机制。整体而言该样本适合作为PyTorch实战入门的预览材料能帮助读者快速把握从数据准备到模型训练的关键流程与项目组织方式。1. 从一份样本说起PyTorch 深度学习项目到底该怎么上手很多人第一次拿到深度学习资料翻两页就被线性代数、概率论、反向传播公式劝退觉得不啃完数学就没法写代码。这份《Deep Learning with PyTorch》样本走的是另一条路先让你把模型跑起来再回头补理论。它围绕 PyTorch 展开覆盖张量操作、自动求导、多层感知机、训练循环、DataLoader 与 Dataset、回归与分类项目、CNN 与 LSTM 等进阶模型最后落到模型保存、学习率调度、超参数搜索这些工程化技巧。适合已经会一点 Python、想用 PyTorch 做完整项目但不知道从哪下手的开发者。样本本身只给了目录和前言但目录结构已经把整条学习路径摊开了照着这条路径搭环境、写代码比零散搜教程高效得多。2. 环境搭建与项目骨架把 PyTorch 跑起来的第一公里2.1 依赖选型与安装策略这个项目场景下核心依赖就三个Python、PyTorch、NumPy。样本里明确提到所有教程都能在普通 CPU 工作站上完成GPU 不是必须的但后面 CNN、LSTM 部分用 GPU 会快很多。我一般会先建一个独立虚拟环境避免和系统里其他项目的包打架。# 创建虚拟环境Python 3.9 以上都行 python -m venv pytorch-env source pytorch-env/bin/activate # Windows 用 pytorch-env\Scripts\activate # 安装 CPU 版本 PyTorch最稳不挑机器 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu # 如果你有 NVIDIA 显卡换成对应 CUDA 版本的命令 # pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 # 补上科学计算和进度条依赖 pip install numpy scikit-learn tqdm matplotlib这里有个参数值得说--index-url指定 PyTorch 官方 wheel 源比默认 PyPI 拿到的版本更匹配你的系统。torchvision和torchaudio分别是视觉和音频扩展样本里 CNN 和 LeNet5 那几章会用到。tqdm是训练进度条样本专门有一节讲怎么用它报告训练进度别省。scikit-learn用于数据预处理和网格搜索样本里“Use PyTorch Deep Learning Models with scikit-learn”和“Optimize Hyperparameters with Grid Search”两节都依赖它。装完之后验证一下这一步别跳过我见过太多人装完直接写代码结果报错找半天import torch import numpy as np print(PyTorch 版本:, torch.__version__) print(CUDA 是否可用:, torch.cuda.is_available()) print(张量测试:, torch.tensor([1.0, 2.0, 3.0]).sum())如果torch.cuda.is_available()返回False但你确实有显卡大概率是装成了 CPU 版本回退到上一步换 CUDA 源重装。没有显卡也不影响样本里所有代码 CPU 都能跑只是慢一点。2.2 目录结构规划样本没有给完整项目代码但目录里列出的章节类型很清晰Lessons课程、Projects项目、Recipes代码配方。我一般会按这个逻辑组织自己的工程目录方便后面二次开发时快速定位pytorch-deep-learning/ ├── data/ # 数据集存放 │ ├── raw/ # 原始数据 │ └── processed/ # 预处理后的数据 ├── notebooks/ # 探索性实验 │ ├── 01_tensor_basics.ipynb │ ├── 02_autograd.ipynb │ └── 03_first_network.ipynb ├── src/ # 可复用代码 │ ├── datasets.py # Dataset 类定义 │ ├── models.py # 模型定义 │ ├── train.py # 训练循环 │ └── utils.py # 工具函数 ├── projects/ # 完整项目 │ ├── regression/ │ ├── binary_classification/ │ └── multiclass_classification/ ├── checkpoints/ # 模型保存 └── requirements.txt这个结构的好处是notebooks里随便造验证想法src里沉淀稳定代码projects里做端到端复现。样本里“Project: Building a Regression Model in PyTorch”这种章节就对应projects/regression/目录里面放data.py、model.py、train.py三个文件各司其职。2.3 第一个可运行脚本张量与自动求导在进入模型之前先把 PyTorch 的两个地基打牢张量操作和 autograd。样本 Part 1 专门讲了这两块我把它压缩成一个可运行脚本你复制就能跑import torch # 1. 张量创建与基本运算 x torch.tensor([[1.0, 2.0], [3.0, 4.0]]) y torch.ones(2, 2) print(加法:\n, x y) print(矩阵乘法:\n, x y) print(形状:, x.shape, 数据类型:, x.dtype) # 2. 自动求导这是 PyTorch 区别于 NumPy 的核心 w torch.tensor([2.0], requires_gradTrue) b torch.tensor([1.0], requires_gradTrue) x_data torch.tensor([3.0]) y_true torch.tensor([10.0]) # 前向y w * x b y_pred w * x_data b loss (y_pred - y_true) ** 2 # 反向自动算梯度 loss.backward() print(w 的梯度:, w.grad) # d(loss)/dw 2*(y_pred-y_true)*x 2*(7-10)*3 -18 print(b 的梯度:, b.grad) # d(loss)/db 2*(y_pred-y_true) -6关键点在requires_gradTrue它告诉 PyTorch 这个张量需要追踪计算历史。loss.backward()一调用整条计算链上的梯度自动算好存在.grad属性里。样本里“Using Autograd in PyTorch to Solve a Regression Problem”一节就是拿这个机制直接优化参数不写神经网络也能做回归。参数说明w和b是待优化参数x_data是输入特征y_true是标签loss是均方误差。梯度值可以手算验证确认 autograd 没算错。3. 核心模块拆解训练循环、DataLoader 与模型构建3.1 训练循环的五个必备元素样本第 8 章“Creating a Training Loop for Your Models”把训练循环拆得很细。一个完整的 PyTorch 训练循环不管模型多复杂骨架都是这五步前向传播、计算损失、清空梯度、反向传播、更新参数。我把它写成一个可复用的函数import torch import torch.nn as nn from tqdm import tqdm def train_one_epoch(model, dataloader, criterion, optimizer, device): model.train() # 切换到训练模式影响 Dropout 和 BatchNorm total_loss 0.0 correct 0 total 0 # tqdm 包住 dataloader实时显示进度 progress_bar tqdm(dataloader, descTraining, leaveFalse) for inputs, targets in progress_bar: inputs, targets inputs.to(device), targets.to(device) # 1. 清空上一轮梯度不清会累加这是新手最常见的翻车点 optimizer.zero_grad() # 2. 前向传播 outputs model(inputs) # 3. 计算损失 loss criterion(outputs, targets) # 4. 反向传播 loss.backward() # 5. 更新参数 optimizer.step() # 统计信息 total_loss loss.item() * inputs.size(0) _, predicted outputs.max(1) correct predicted.eq(targets).sum().item() total targets.size(0) # 更新进度条后缀显示当前 loss progress_bar.set_postfix(lossloss.item()) avg_loss total_loss / total accuracy correct / total return avg_loss, accuracy逐段说明model.train()不是可选项Dropout 层在训练时要随机丢弃神经元评估时要关闭这个开关控制行为。optimizer.zero_grad()必须放在前向之前PyTorch 默认梯度累加忘了清就是血泪经验。loss.item()把单元素张量转成 Python 浮点数避免显存里堆积计算图。tqdm的set_postfix能在进度条右侧实时显示 loss样本里专门讲了这招调试时非常直观。device参数让同一份代码在 CPU 和 GPU 之间切换不用改逻辑。3.2 DataLoader 与 Dataset数据管道的正确打开方式样本第 18 章专门讲 DataLoader 和 Dataset。很多新手直接把整个数据集塞进模型数据量一大就内存爆炸。正确做法是继承Dataset类实现__len__和__getitem__再交给DataLoader做批处理和打乱from torch.utils.data import Dataset, DataLoader import numpy as np class TabularDataset(Dataset): 适用于表格数据的通用 Dataset样本里回归和分类项目都能用 def __init__(self, features, labels, transformNone): # 转成 float32PyTorch 默认 float32不转后面会报类型错误 self.features torch.tensor(features, dtypetorch.float32) # 回归用 float32分类用 long self.labels torch.tensor(labels, dtypetorch.float32) self.transform transform def __len__(self): return len(self.labels) def __getitem__(self, idx): x self.features[idx] y self.labels[idx] if self.transform: x self.transform(x) return x, y # 模拟一份数据 np.random.seed(42) X np.random.randn(1000, 10).astype(np.float32) y (X.sum(axis1) np.random.randn(1000) * 0.1).astype(np.float32) dataset TabularDataset(X, y) dataloader DataLoader( dataset, batch_size32, # 批大小太大显存不够太小训练不稳 shuffleTrue, # 训练集必须打乱否则模型学到顺序偏差 num_workers0, # Windows 下建议 0Linux 可以设 2-4 drop_lastFalse # 最后一批不足 batch_size 时是否丢弃 ) # 验证一下 for batch_x, batch_y in dataloader: print(批次特征形状:, batch_x.shape, 批次标签形状:, batch_y.shape) break参数逐个说batch_size是最重要的超参数之一样本里回归项目用的就是小批量。shuffleTrue只在训练集开验证集和测试集要关掉保证评估结果可复现。num_workers控制加载数据的子进程数Windows 上设大于 0 有时会卡死设 0 最稳。drop_last在数据量不能被 batch_size 整除时决定要不要丢掉最后一批分类任务里如果 BatchNorm 对批次大小敏感建议设 True。3.3 模型定义从 MLP 到 CNN 的模块化写法样本从多层感知机讲到 CNN、LSTM模型定义方式一脉相承。我习惯用nn.Module子类把层定义在__init__前向逻辑写在forwardimport torch.nn as nn class MLP(nn.Module): 多层感知机样本 Part 2 的核心模型 def __init__(self, input_dim, hidden_dim64, output_dim1): super().__init__() self.net nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.ReLU(), # 激活函数样本有专门一节讲 nn.Dropout(0.2), # 正则化防止过拟合 nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, output_dim) ) def forward(self, x): return self.net(x) class SimpleCNN(nn.Module): 简单卷积网络对应样本 Part 4 的 CNN 章节 def __init__(self, num_classes10): super().__init__() self.features nn.Sequential( nn.Conv2d(1, 32, kernel_size3, padding1), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(32, 64, kernel_size3, padding1), nn.ReLU(), nn.MaxPool2d(2) ) self.classifier nn.Sequential( nn.Flatten(), nn.Linear(64 * 7 * 7, 128), nn.ReLU(), nn.Dropout(0.5), nn.Linear(128, num_classes) ) def forward(self, x): x self.features(x) return self.classifier(x) # 实例化测试 mlp MLP(input_dim10, output_dim1) print(MLP 参数量:, sum(p.numel() for p in mlp.parameters())) cnn SimpleCNN(num_classes10) print(CNN 参数量:, sum(p.numel() for p in cnn.parameters()))nn.Sequential适合线性堆叠的层写起来清爽。nn.Dropout(0.2)里的 0.2 是丢弃概率样本里“Using Dropout Regularization”一节建议从 0.2 到 0.5 之间试。nn.Flatten()把卷积输出的多维特征拉平接全连接层。参数量统计用p.numel()能快速判断模型大小样本里“Visualizing a PyTorch Model”一节也提到类似检查手段。4. 避坑与排查训练不收敛时先查这五件事4.1 损失不下降梯度全是 None现象训练几个 epochloss 纹丝不动打印w.grad发现是None。 原因参数没有设置requires_gradTrue或者被torch.no_grad()包住了。 解决检查模型参数是否默认需要梯度nn.Module里的参数默认是 True但手动创建的张量要显式设置。另外确认训练循环没有误加with torch.no_grad():。4.2 显存爆炸batch_size 调小也没用现象跑几个 batch 就 OOM减小 batch_size 只能多撑几步。 原因loss.item()忘了加或者把带计算图的张量存进了列表计算图一直不释放。 解决统计 loss 时用loss.item()转成 Python 浮点数需要保存预测结果时用.detach().cpu().numpy()切断计算图。样本里“Collecting Statistics During Training”一节专门强调过这个细节。4.3 验证集准确率远低于训练集现象训练集准确率 99%验证集只有 60%差距巨大。 原因过拟合模型把训练数据背下来了。 解决加 Dropout、加 L2 正则优化器的weight_decay参数、早停样本里“Managing Training Process with Checkpoints and Early Stopping”一节有完整方案。另外检查数据预处理有没有在训练集和验证集上分别做标准化参数必须从训练集算出来再应用到验证集否则就是数据泄露。4.4 DataLoader 的 num_workers 在 Windows 上报错现象Linux 上跑得好好的Windows 上num_workers4直接抛异常。 原因Windows 的多进程启动方式和 Linux 不同PyTorch 的 DataLoader 在 Windows 上需要if __name__ __main__:保护。 解决把训练代码包进if __name__ __main__:或者干脆设num_workers0。样本里没特别强调平台差异但这是实际开发中必踩的坑。4.5 模型保存后加载结果对不上现象训练完保存模型重新加载后预测结果和保存前不一致。 原因保存时只存了state_dict加载时模型结构没对齐或者保存了整个模型对象但设备从 GPU 换到了 CPU。 解决推荐只保存state_dict加载时先实例化同样的模型结构再load_state_dict。跨设备加载用map_location# 保存 torch.save(model.state_dict(), checkpoints/model.pth) # 加载 model MLP(input_dim10, output_dim1) model.load_state_dict(torch.load(checkpoints/model.pth, map_locationcpu)) model.eval() # 别忘了切评估模式样本里“Save and Load Your PyTorch Models”一节讲的就是这套流程map_location是跨设备加载的关键参数。5. 二次开发与改造把样本目录变成你自己的项目模板样本给的是目录和思路真正要落地成自己的项目得做三件事把训练循环抽成可配置的模块、把数据管道和模型解耦、把超参数搜索接进来。先说训练循环的改造。上面那个train_one_epoch只做了训练实际项目还需要验证和早停。我一般会写一个Trainer类把优化器、调度器、检查点路径都作为参数传进去class Trainer: def __init__(self, model, train_loader, val_loader, criterion, optimizer, schedulerNone, devicecpu, checkpoint_dircheckpoints): self.model model.to(device) self.train_loader train_loader self.val_loader val_loader self.criterion criterion self.optimizer optimizer self.scheduler scheduler self.device device self.checkpoint_dir checkpoint_dir self.best_val_loss float(inf) self.patience_counter 0 def fit(self, epochs, patience5): for epoch in range(epochs): train_loss, train_acc self._train_epoch() val_loss, val_acc self._validate() if self.scheduler: self.scheduler.step(val_loss) # ReduceLROnPlateau 需要传指标 print(fEpoch {epoch1}: train_loss{train_loss:.4f} fval_loss{val_loss:.4f} val_acc{val_acc:.4f}) # 早停逻辑 if val_loss self.best_val_loss: self.best_val_loss val_loss self.patience_counter 0 torch.save(self.model.state_dict(), f{self.checkpoint_dir}/best_model.pth) else: self.patience_counter 1 if self.patience_counter patience: print(f早停触发在第 {epoch1} 轮停止) break这个类把样本里分散在多个章节的技巧串起来了训练循环、验证评估、学习率调度、检查点保存、早停。scheduler.step(val_loss)对应样本里“Using Learning Rate Schedule”一节ReduceLROnPlateau在验证损失不降时自动降学习率。patience参数控制早停的容忍轮数样本里“Early Stopping”一节建议从 5 到 10 开始试。再说超参数搜索。样本里“Optimize Hyperparameters with Grid Search”一节用的是 scikit-learn 的GridSearchCV包装 PyTorch 模型。实际改造时我建议先用小范围网格搜出大致区间再用随机搜索细化from sklearn.model_selection import ParameterGrid param_grid { hidden_dim: [32, 64, 128], lr: [1e-3, 1e-4], dropout: [0.2, 0.5] } best_score float(inf) best_params None for params in ParameterGrid(param_grid): model MLP(input_dim10, hidden_dimparams[hidden_dim], output_dim1) optimizer torch.optim.Adam(model.parameters(), lrparams[lr]) # 这里把 dropout 动态设进去实际项目建议作为模型构造参数 trainer Trainer(model, train_loader, val_loader, nn.MSELoss(), optimizer) trainer.fit(epochs20, patience3) if trainer.best_val_loss best_score: best_score trainer.best_val_loss best_params params print(f新最优: {params}, val_loss{best_score:.4f}) print(最终最优参数:, best_params)这段代码把模型构建、训练、评估、参数选择串成一条流水线。ParameterGrid做笛卡尔积每个组合训一次记录验证损失最低的那组。实际跑的时候建议把结果写进 CSV方便后面分析哪个参数影响最大。最后说一个我自己的习惯每次改完模型结构或训练逻辑先在一个极小的子集上跑通确认 loss 能降、梯度能回传、保存加载没问题再上全量数据。这个习惯帮我省了无数次等半小时才发现参数写错的时间。从那以后我每次动训练循环都强制走一遍“小数据冒烟测试 → 全量训练 → 检查点验证”的流程希望帮到你。本文还有配套的精品资源点击获取