尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

PyTorch深度学习实战:从环境搭建到模型部署全流程指南

PyTorch深度学习实战:从环境搭建到模型部署全流程指南 1. 从“Hello World”到实战为什么PyTorch是深度学习的首选如果你刚开始接触深度学习或者从TensorFlow、Keras等其他框架转过来面对PyTorch时可能会有一种感觉它好像更“程序员友好”。这种感觉是对的。PyTorch的设计哲学从一开始就与Python的“动态性”和“直观性”深度绑定。它不像一些早期框架那样需要你先定义一个静态的计算图然后再往里面喂数据。在PyTorch里你可以像写普通的Python代码一样用for循环、if条件语句来动态构建你的神经网络每一步的计算结果都是立即可见的Tensor。这种“动态图”Eager Execution模式极大地降低了调试和实验的门槛。你可以随时打印出中间变量的值随时中断随时修改整个过程就像在用NumPy做科学计算一样自然流畅。这不仅仅是语法糖。这种设计直接影响了整个深度学习研究和开发的迭代速度。研究者可以快速验证一个新想法开发者可以更直观地理解模型的数据流向。当你的模型在某个batch上出现NaN非数值时你可以轻松地定位到是哪个操作、哪一层出了问题而不是面对一个编译好的、黑盒般的静态图束手无策。当然PyTorch也提供了torch.jit或TorchScript将动态图转换为静态图以优化部署性能但这“先动态后静态”的路径给了开发者最大的灵活性。所以当我们谈论PyTorch实战时我们谈论的不仅仅是一个工具库更是一种以实验和迭代为核心的现代深度学习工作流。2. 环境搭建避开版本依赖的“隐形坑”动手之前环境是第一个拦路虎。网上教程千篇一律的conda install pytorch命令背后藏着无数新手踩过的坑。核心矛盾在于PyTorch版本、CUDA版本、Python版本以及你的显卡驱动这四者必须严格匹配。一个版本对不上轻则无法调用GPU重则直接安装失败。2.1 官方安装命令的“正确打开方式”最可靠的方法永远是访问PyTorch官网的“Get Started”页面。这里提供了一个交互式选择器你需要根据你的系统Windows/Linux/macOS、包管理工具Conda/Pip、CUDA版本或选择CPU以及语言Python来生成对应的安装命令。比如对于一台装有NVIDIA显卡驱动版本支持CUDA 11.8的Linux系统使用Conda安装命令可能长这样conda install pytorch torchvision torchaudio pytorch-cuda11.8 -c pytorch -c nvidia这条命令的精髓在于pytorch-cuda11.8它确保了PyTorch及其相关的计算库如torchvision都编译链接到了CUDA 11.8的运行时库。直接使用conda install pytorch而不指定CUDA版本conda可能会给你安装一个CPU版本或一个不匹配的CUDA版本。对于使用Pip的用户命令类似pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118这里的cu118就指明了CUDA 11.8的版本。一个关键细节使用Pip安装时务必确认你的Python环境是64位的并且Pip版本足够新。在Windows上32位的Python环境是绝对无法安装PyTorch GPU版本的。2.2 验证安装不仅仅是“import torch”安装完成后很多教程会让你运行import torch不报错就认为成功了。这远远不够。一个完整的验证流程至少应该包括以下几步导入与版本检查import torch print(torch.__version__) # 查看PyTorch版本 print(torch.version.cuda) # 查看PyTorch编译时对应的CUDA版本如果安装了GPU版GPU可用性检查print(torch.cuda.is_available()) # 输出True才是成功 if torch.cuda.is_available(): print(torch.cuda.get_device_name(0)) # 打印你的显卡型号例如‘NVIDIA GeForce RTX 4090’ print(torch.cuda.device_count()) # 打印可用GPU数量如果torch.cuda.is_available()返回False但你的机器确实有NVIDIA显卡问题大概率出在版本不匹配上。首先在终端运行nvidia-smi查看你的显卡驱动版本以及它支持的最高CUDA版本在右上角显示例如“CUDA Version: 12.4”。这个“最高”版本很重要你的PyTorch CUDA版本如11.8必须小于等于这个值。驱动版本过低是最常见的原因。简单的张量计算测试# 在CPU上创建一个张量 x torch.rand(5, 3) print(x) # 在GPU上创建一个张量如果可用 if torch.cuda.is_available(): y torch.rand(5, 3).cuda() print(y) # 进行一个GPU上的计算 z y * 2 print(z)这一步是为了确保基本的计算功能正常并且数据能在CPU和GPU之间正确移动通过.cuda()方法。注意关于Anaconda环境。强烈建议为每个深度学习项目创建独立的conda环境。这能完美隔离不同项目对库版本的冲突需求。命令很简单conda create -n pytorch_env python3.9然后激活环境conda activate pytorch_env再在这个环境里安装PyTorch。这能避免把你base环境的包管理搞得一团糟。3. 核心数据结构深入理解Tensor与AutogradPyTorch的两大基石是Tensor张量和Autograd自动微分。理解了它们就理解了PyTorch一半的精髓。3.1 Tensor不只是多维数组Tensor可以看作是多维数组是PyTorch中存储和变换数据的主要工具。它和NumPy的ndarray非常相似并且可以方便地相互转换。但Tensor的威力在于两点GPU加速和自动求导。创建与属性import torch import numpy as np # 从列表创建 a torch.tensor([[1, 2], [3, 4]]) # 从NumPy数组创建共享内存修改一个会影响另一个 np_array np.ones((2, 3)) b torch.from_numpy(np_array) # 创建特定形状的Tensor c torch.zeros(2, 3) # 2行3列的全0张量 d torch.ones(2, 3, dtypetorch.float64) # 指定数据类型 e torch.rand(2, 3) # 均匀分布随机数 f torch.randn(2, 3) # 标准正态分布随机数 print(a.shape) # 形状 torch.Size([2, 2]) print(a.dtype) # 数据类型 torch.int64 print(a.device) # 所在设备 device(typecpu)核心操作 Tensor支持所有你熟悉的数学运算并且语法非常直观。更重要的是大多数操作都有“就地操作”in-place版本以_结尾可以节省内存。x torch.tensor([1., 2., 3.], requires_gradTrue) # 稍后解释requires_grad y torch.tensor([4., 5., 6.]) # 基本运算 z1 x y # 逐元素相加 z2 torch.add(x, y) # 函数形式 z3 x * y # 逐元素相乘 z4 x y.T # 矩阵乘法如果形状允许 x.add_(y) # 就地加法x的值被改变 # 形状变换 x_reshaped x.view(3, 1) # 改变形状为(3,1)要求总元素数不变 x_flattened x.flatten() # 展平为一维3.2 Autograd让神经网络自己学会“反向传播”Autograd包是PyTorch实现神经网络训练的核心。它的原理是自动微分。我们只需要在前向传播时构建一个计算图PyTorch会自动记录所有操作并在反向传播时计算梯度。requires_grad属性这是触发Autograd的开关。当一个Tensor的requires_grad属性被设置为True时PyTorch会开始跟踪在其上的所有操作构建一个动态计算图。x torch.ones(2, 2, requires_gradTrue) # 告诉PyTorch请记录对x的操作 y x 2 z y * y * 3 out z.mean() print(out) # tensor(27., grad_fnMeanBackward0)注意out有一个grad_fn属性它指向创建这个张量的函数MeanBackward0这就是计算图的一部分。反向传播与梯度计算 调用.backward()方法PyTorch会从该张量开始沿着计算图反向传播计算所有requires_gradTrue的叶子节点即用户直接创建的张量如这里的x的梯度。out.backward() # 等价于 out.backward(torch.tensor(1.)) print(x.grad) # 打印x的梯度x.grad现在是一个与x形状相同的张量包含了损失函数out对x的偏导数。在这个例子中out mean(3*(x2)^2)对x求导当x1时梯度为4.5因为d(out)/dx 3*2*(x2)/4代入x1得到4.5。PyTorch计算出的x.grad应该是一个所有元素都为4.5的矩阵。梯度累加与清零 在训练循环中一个非常容易忽略的细节是梯度累加。每次调用.backward()计算出的梯度会累加到对应变量的.grad属性中而不是替换。这是因为在有些场景下如RNN我们需要在一个batch内多次进行前向-反向传播累加梯度。但在标准的每个batch独立训练的场景下我们必须在每次参数更新前将梯度手动清零。# 错误的做法梯度会越累越大 for data, target in dataloader: output model(data) loss criterion(output, target) loss.backward() optimizer.step() # 忘记 optimizer.zero_grad() # 正确的做法 for data, target in dataloader: optimizer.zero_grad() # 清零上一轮的梯度 output model(data) loss criterion(output, target) loss.backward() optimizer.step() # 根据梯度更新参数忘记zero_grad()是新手常犯的错误会导致训练过程不稳定甚至发散。4. 构建你的第一个神经网络以图像分类为例理论说再多不如动手搭一个。我们以经典的MNIST手写数字分类为例构建一个简单的卷积神经网络CNN。这个过程会串联起nn.Module、数据加载、训练循环等核心概念。4.1 定义网络模型nn.Module在PyTorch中我们通过继承torch.nn.Module类来定义自己的网络。你需要实现两个方法__init__初始化网络层和forward定义前向传播逻辑。import torch.nn as nn import torch.nn.functional as F class SimpleCNN(nn.Module): def __init__(self): super(SimpleCNN, self).__init__() # 卷积层: 输入通道1灰度图输出通道32卷积核3x3填充1保持尺寸 self.conv1 nn.Conv2d(in_channels1, out_channels32, kernel_size3, padding1) # 卷积层: 输入32输出64 self.conv2 nn.Conv2d(32, 64, kernel_size3, padding1) # 最大池化层窗口2x2步长2 self.pool nn.MaxPool2d(kernel_size2, stride2) # 丢弃层防止过拟合 self.dropout1 nn.Dropout2d(0.25) self.dropout2 nn.Dropout(0.5) # 全连接层 # 经过两次池化28x28的图像 - 14x14 - 7x7 # 第二层卷积输出64个通道所以输入特征数是 64 * 7 * 7 self.fc1 nn.Linear(64 * 7 * 7, 128) # 输出层10个类别数字0-9 self.fc2 nn.Linear(128, 10) def forward(self, x): # 输入x形状: [batch_size, 1, 28, 28] x self.pool(F.relu(self.conv1(x))) # - [batch_size, 32, 14, 14] x self.dropout1(x) x self.pool(F.relu(self.conv2(x))) # - [batch_size, 64, 7, 7] x self.dropout1(x) x torch.flatten(x, 1) # 展平保持batch维度 - [batch_size, 64*7*7] x F.relu(self.fc1(x)) x self.dropout2(x) x self.fc2(x) # 输出层通常不在这里加激活函数如softmax因为损失函数会处理 return x关键点解析nn.Conv2d,nn.Linear等是包含可学习参数权重和偏置的层。F.relu是函数式接口不包含参数常用于前向传播中。forward方法定义了数据如何流过这些层。你永远不需要直接调用forward而是调用模型实例本身如output model(input)PyTorch会自动调用forward。全连接层输入尺寸的计算是容易出错的地方。务必根据卷积、池化后的特征图尺寸仔细计算。4.2 准备数据DataLoaderPyTorch提供了torch.utils.data.DataLoader来高效地加载和批处理数据。它需要配合一个Dataset对象使用。对于常见数据集如MNISTtorchvision.datasets已经提供了。import torchvision import torchvision.transforms as transforms # 定义数据预处理转换转换为Tensor并归一化到[0,1]除以255 transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) # MNIST的均值和标准差 ]) # 下载并加载训练集和测试集 trainset torchvision.datasets.MNIST(root./data, trainTrue, downloadTrue, transformtransform) trainloader torch.utils.data.DataLoader(trainset, batch_size64, shuffleTrue, num_workers2) testset torchvision.datasets.MNIST(root./data, trainFalse, downloadTrue, transformtransform) testloader torch.utils.data.DataLoader(testset, batch_size1000, shuffleFalse, num_workers2)batch_size一次训练/测试加载的数据量。太大耗内存太小不稳定。64或128是常见起点。shuffleTrue每个epoch遍历一遍数据集开始时打乱数据顺序防止模型学习到数据的顺序信息。num_workers用于数据加载的子进程数。可以加快数据读取速度尤其是在使用机械硬盘时。通常设置为CPU核心数。在Windows上有时需要设置为0以避免多进程问题。Normalize归一化非常重要它能让输入数据分布更稳定加速模型收敛。这里的(0.1307,)和(0.3081,)是MNIST数据集的全局像素均值和标准差。4.3 训练循环完整的迭代过程训练一个模型包含三个核心组件模型、损失函数、优化器。训练循环就是反复执行前向传播 - 计算损失 - 反向传播 - 更新参数。import torch.optim as optim # 初始化模型、损失函数、优化器 device torch.device(cuda:0 if torch.cuda.is_available() else cpu) model SimpleCNN().to(device) # 将模型移动到GPU如果可用 criterion nn.CrossEntropyLoss() # 交叉熵损失适用于多分类 optimizer optim.Adam(model.parameters(), lr0.001) # Adam优化器 # 训练多个epoch num_epochs 10 for epoch in range(num_epochs): running_loss 0.0 model.train() # 将模型设置为训练模式启用Dropout等 for i, data in enumerate(trainloader, 0): # 获取输入数据 inputs, labels data inputs, labels inputs.to(device), labels.to(device) # 数据移动到设备 # 清零梯度 optimizer.zero_grad() # 前向传播 计算损失 outputs model(inputs) loss criterion(outputs, labels) # 反向传播 优化 loss.backward() optimizer.step() # 打印统计信息 running_loss loss.item() if i % 200 199: # 每200个mini-batch打印一次 print(f[{epoch 1}, {i 1:5d}] loss: {running_loss / 200:.3f}) running_loss 0.0 print(Finished Training)逐行解读model.to(device)和data.to(device)这是将模型和数据转移到GPU的关键步骤。模型和它要处理的数据必须在同一个设备上。model.train()和model.eval()这是一个非常重要的模式切换。在训练时我们需要启用如Dropout、BatchNorm等层的特定行为如随机丢弃神经元、用当前batch统计量归一化。在测试/验证时我们需要固定这些层的行为如关闭Dropout使用训练阶段累积的全局统计量进行归一化。忘记切换模式是导致模型在测试时表现异常的常见原因。optimizer.zero_grad()如前所述清除上一轮迭代的梯度。loss.backward()自动计算所有requires_gradTrue的参数的梯度。optimizer.step()根据优化器算法如Adam和计算出的梯度更新模型参数。loss.item()loss是一个包含单个元素的Tensor。使用.item()可以将其转换为Python标量方便打印和记录。4.4 模型评估与推理训练完成后我们需要在测试集上评估模型的泛化能力。correct 0 total 0 model.eval() # 切换到评估模式 with torch.no_grad(): # 禁用梯度计算节省内存和计算 for data in testloader: images, labels data images, labels images.to(device), labels.to(device) outputs model(images) _, predicted torch.max(outputs.data, 1) # 获取预测类别最大值的索引 total labels.size(0) correct (predicted labels).sum().item() print(fAccuracy of the network on the 10000 test images: {100 * correct / total:.2f} %)model.eval()至关重要这会关闭Dropout、BatchNorm等的训练期行为。with torch.no_grad():在这个上下文管理器下所有计算都不会被记录在计算图中也不会计算梯度。这能显著减少内存占用并加速计算因为前向传播只是为了得到预测结果不需要为反向传播保存中间变量。torch.max(outputs.data, 1)outputs的形状是[batch_size, 10]10个类别的得分/对数几率。torch.max在维度1类别维度上求最大值返回两个Tensor最大值和最大值的索引。我们只需要索引predicted即模型预测的类别。5. 调试与优化让模型真正“学”起来模型跑起来只是第一步让它“学好”才是挑战。你可能会遇到损失不下降、准确率震荡、过拟合等问题。这里分享几个关键的调试和优化经验。5.1 损失函数与优化器的选择损失函数分类任务用CrossEntropyLoss回归任务用MSELoss或L1Loss二分类有时用BCEWithLogitsLoss它内部集成了Sigmoid和BCE数值更稳定。一个常见误区在使用CrossEntropyLoss时网络的最后一层不需要也不应该加Softmax激活函数因为该损失函数内部已经包含了LogSoftmax。如果你加了Softmax反而可能因为数值饱和导致梯度消失。优化器Adam是当前最流行的默认选择它自适应调整学习率对超参数不那么敏感。SGD随机梯度下降配合动量momentum和学习率调度在精心调参后可能达到更好的最终性能尤其在计算机视觉任务中。对于新手从Adam开始是稳妥的。学习率lr是关键超参数通常从1e-3或3e-4开始尝试。5.2 学习率调度Learning Rate Scheduling固定学习率可能不是最优的。在训练后期一个较小的学习率有助于模型收敛到更精细的局部最优点。PyTorch在torch.optim.lr_scheduler中提供了多种调度器。# 在优化器定义之后 optimizer optim.Adam(model.parameters(), lr0.001) scheduler optim.lr_scheduler.StepLR(optimizer, step_size5, gamma0.1) # 或者使用ReduceLROnPlateau当指标停止改善时降低学习率 # scheduler optim.lr_scheduler.ReduceLROnPlateau(optimizer, modemin, factor0.1, patience3) # 在每个epoch的训练循环结束后调用 for epoch in range(num_epochs): # ... 训练循环 ... scheduler.step() # 对于StepLR # 对于ReduceLROnPlateau需要传入监控的指标如验证集损失 # scheduler.step(val_loss)StepLR是每过step_size个epoch将学习率乘以gamma。ReduceLROnPlateau更智能它监控一个指标如验证集损失当该指标在patience个epoch内没有改善时才降低学习率。5.3 过拟合与欠拟合的识别与应对欠拟合模型在训练集和测试集上表现都很差。可能原因模型容量太小层数太少、神经元太少、训练轮数不够、特征工程不足。对策增加模型复杂度、延长训练时间、检查数据预处理和特征。过拟合模型在训练集上表现很好但在测试集上表现差。这是更常见的问题。对策数据增强对训练数据进行随机变换如翻转、旋转、裁剪、颜色抖动增加数据的多样性。torchvision.transforms提供了丰富的工具。正则化Dropout如前所述在训练时随机“关闭”一部分神经元迫使网络不依赖于任何单个神经元增强鲁棒性。权重衰减在优化器中设置weight_decay参数即L2正则化惩罚大的权重值防止模型过于复杂。早停监控验证集性能当性能不再提升时甚至开始下降时停止训练而不是一味地训练到训练损失最小。使用更简单的模型有时减少层数或神经元数量是直接有效的方法。5.4 可视化与监控“黑箱”训练是不可取的。使用TensorBoard或更轻量的wandbWeights Biases来监控训练过程至关重要。# 一个简单的TensorBoard日志记录示例 from torch.utils.tensorboard import SummaryWriter writer SummaryWriter(runs/mnist_experiment_1) # 指定日志目录 for epoch in range(num_epochs): running_loss 0.0 for i, data in enumerate(trainloader, 0): # ... 训练步骤 ... running_loss loss.item() if i % 200 199: # 记录标量损失 writer.add_scalar(training loss, running_loss / 200, epoch * len(trainloader) i) running_loss 0.0 # 每个epoch结束后可以记录验证集准确率等 # writer.add_scalar(validation accuracy, val_acc, epoch) writer.close()运行后在终端使用tensorboard --logdirruns启动服务然后在浏览器打开localhost:6006就能看到损失曲线等图表。观察损失曲线是否平滑下降验证集准确率是否同步提升是判断训练是否正常的最直观方法。6. 项目进阶从MNIST到自定义数据集与模型部署掌握了基础流程后真正的挑战在于处理你自己的数据和将模型用起来。6.1 处理自定义数据集现实中你很少会一直用MNIST。你需要创建自己的Dataset类。这需要继承torch.utils.data.Dataset并实现__len__和__getitem__方法。from torch.utils.data import Dataset from PIL import Image import os class CustomImageDataset(Dataset): def __init__(self, img_dir, transformNone): Args: img_dir (string): 包含所有图片的目录。 transform (callable, optional): 应用于图片的变换/增强。 self.img_dir img_dir self.transform transform # 假设目录结构为: img_dir/class_0/*.jpg, img_dir/class_1/*.jpg ... self.image_paths [] self.labels [] for label, class_name in enumerate(sorted(os.listdir(img_dir))): class_dir os.path.join(img_dir, class_name) for img_name in os.listdir(class_dir): self.image_paths.append(os.path.join(class_dir, img_name)) self.labels.append(label) def __len__(self): return len(self.image_paths) def __getitem__(self, idx): img_path self.image_paths[idx] image Image.open(img_path).convert(RGB) # 确保是RGB三通道 label self.labels[idx] if self.transform: image self.transform(image) return image, label然后你就可以像使用MNIST一样用DataLoader来加载这个自定义数据集了。__getitem__方法在每次迭代时被调用返回一个样本和其标签。DataLoader会自动帮你组batch、打乱顺序。6.2 模型保存与加载训练好的模型需要保存下来以备后续使用或继续训练。# 保存整个模型包括结构和参数 torch.save(model, model.pth) # 加载整个模型需要模型类定义在当前作用域 model torch.load(model.pth) # 推荐方式仅保存模型的状态字典参数 torch.save(model.state_dict(), model_state_dict.pth) # 加载时需要先实例化模型结构再加载参数 model SimpleCNN() # 或者你的自定义模型类 model.load_state_dict(torch.load(model_state_dict.pth)) model.eval() # 别忘了切换到评估模式推荐使用保存state_dict的方式因为它更灵活且与模型代码解耦。保存整个模型torch.save(model)可能会因为Python的pickle序列化问题在不同环境或代码版本间加载失败。6.3 模型部署推理将模型用于实际预测推理时核心是torch.no_grad()和model.eval()。def predict_single_image(image_path, model, transform, device): 对单张图片进行预测。 model.eval() image Image.open(image_path).convert(RGB) image transform(image).unsqueeze(0) # 增加一个batch维度 - [1, C, H, W] image image.to(device) with torch.no_grad(): outputs model(image) _, predicted torch.max(outputs, 1) # 如果需要概率可以加softmax # probabilities F.softmax(outputs, dim1) return predicted.item() # 返回预测的类别索引unsqueeze(0)因为模型期望的输入是[batch_size, channels, height, width]。单张图片没有batch维度所以需要手动在0维度添加一个维度。确保输入的transform与训练时完全一致特别是归一化的均值和标准差。对于生产环境你可能需要将PyTorch模型转换为其他格式如ONNX开放神经网络交换格式以便在不同的推理引擎如TensorRT, OpenVINO或移动端上运行。这涉及到torch.onnx.export函数需要额外注意输入输出的动态形状等问题。7. 避坑指南那些官方文档没明说的细节最后分享一些从实际项目中积累的、容易踩坑的经验。GPU内存溢出CUDA out of memory这是最常见的问题。首先检查你的batch_size是否设得太大。尝试减小它。其次在训练循环中确保没有不必要地在GPU上累积中间变量。例如在计算损失或指标时如果使用了.item()或.cpu().numpy()将数据移回CPU就能释放GPU内存。使用torch.cuda.empty_cache()可以清理PyTorch的CUDA缓存但这不是根本解决办法。使用梯度累积Gradient Accumulation技术可以在不增加batch size的情况下模拟大batch的效果每N个小batch做一次反向传播但只在最后一次调用optimizer.step()和optimizer.zero_grad()。验证/测试时结果不一致99%的原因是你忘记了model.eval()和torch.no_grad()。Dropout和BatchNorm在训练和评估模式下的行为天差地别。BatchNorm在训练时使用当前batch的均值和方差在评估时使用训练阶段累积的全局均值和方差。如果弄混结果会非常随机。损失为NaN或无限大这通常意味着出现了数值不稳定。可能的原因学习率太高网络层中出现了除零或对数运算检查是否有log(0)梯度爆炸。对策降低学习率在可能出现问题的地方加入数值稳定措施如F.log_softmax代替手动log(softmax)使用梯度裁剪torch.nn.utils.clip_grad_norm_来防止梯度爆炸。数据加载是瓶颈如果训练时GPU利用率很低可以用nvidia-smi查看而CPU很高很可能是数据加载拖慢了整体速度。对策增加DataLoader的num_workers通常设置为CPU核心数使用pin_memoryTrue如果使用GPU这能将数据锁页内存加速到GPU的数据传输考虑将数据集预先处理成更快的格式如HDF5或LMDB。随机性无法复现深度学习训练本身具有随机性权重初始化、数据打乱、Dropout但有时我们需要复现结果。可以设置以下随机种子import torch import numpy as np import random def set_seed(seed): torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) np.random.seed(seed) random.seed(seed) torch.backends.cudnn.deterministic True # 保证卷积算法确定性 torch.backends.cudnn.benchmark False # 对固定尺寸输入关闭benchmark以保持确定性注意设置cudnn.deterministicTrue可能会降低一些性能。PyTorch的魅力在于它的灵活与直观它把构建和训练神经网络的复杂性封装在了一个符合直觉的接口之下。从理解Tensor和Autograd开始到搭建、训练、调试一个完整的模型每一步都需要动手实践和思考。遇到问题多查文档PyTorch官方文档质量很高、多搜社区如PyTorch论坛、Stack Overflow大部分坑前人都踩过。记住在深度学习的实践中代码能跑通只是起点让模型高效、稳定、泛化能力强才是持续精进的方向。
返回列表