尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

深度学习入门与PyTorch实战:从环境搭建到模型训练全攻略

深度学习入门与PyTorch实战:从环境搭建到模型训练全攻略 深度学习这几年确实火但很多新人学起来最大的障碍不是数学也不是代码而是不知道整个领域的地图长什么样。这个领域太大了CV、NLP、语音、强化学习各自为战今天看一篇讲CNN的文章明天刷到一个讲Transformer的视频知识点散落一地很难串成体系。更麻烦的是光是环境搭建就能劝退一大批人尤其是GPU版PyTorch的安装很多教程写得含糊其辞照着抄错了都不知道错在哪。这篇文章我打算把两件事讲透一是深度学习本身到底在做什么、常见的模型结构解决什么问题、为什么训练过程会表现出各种诡异现象二是PyTorch这个框架的核心设计逻辑以及从环境搭建到训练一个真实模型的完整路径。这篇文章适合两类人看一类是完全零基础、想系统入门深度学习的技术爱好者另一类是已经用过一些深度学习库、但一直在调参侠阶段、对底层逻辑和框架设计理解不够深的人。我会尽量把原理讲清楚也会把最容易踩坑的细节全部列出来。1. 深度学习总览从数据到模型这张图里的关系和它们各自的角色很多人一开始学深度学习就陷入公式推导和数学证明的泥潭我不反对数学但如果你想先跑起来、先做出东西就应该先建立一张全局认知地图。深度学习本质上做了一件特别朴素的事给定一堆输入和输出去学一个函数让这个函数能够把新的输入映射到合理的输出上。这里面有几个关键角色必须搞清楚。数据是燃料。模型从数据里学到的不是某种神谕而是统计规律。数据决定了模型能力的上限模型结构只是逼近这个上限的手段。这句话听起来像鸡汤但做项目时间长了会发现很多模型效果不佳根本不是结构不够新、不够深而是数据太脏、太少、分布太偏。现在主流的深度学习框架——无论PyTorch还是TensorFlow——都只是解决了表达函数和求梯度这两个问题数据质量和数据管线质量反而常常成为整个项目的瓶颈。模型是函数家族的候选集合。不同的模型结构不过是对函数应该长成什么样子的某种先验假设。CNN假设局部性和平移不变性RNN假设时序依赖Transformer假设注意力可以替代距离约束。你选用某种结构本质上是在做归纳偏置的取舍。没有免费的午餐结构带来的优势总会在某些数据分布下变成劣势。损失函数是标尺。它定义了你认为什么算好。回归任务常用MSE分类任务常用交叉熵对比学习用InfoNCE生成模型里头还有各种对抗损失和感知损失。损失函数的选择和业务目标必须匹配否则会出现训练指标挺好、业务上没啥用的情况。优化器是调整模型参数的手段。SGD让参数沿着梯度方向微调Adam系会为每个参数自适应地调整步长。不要只把优化器当工具调参它的选择本质上是对梯度噪声和损失曲面形状的一种应对策略。评估指标是最终裁判。准确率、精确率召回率、IoU、BLEU、FID每种指标都在用不同视角衡量模型好坏。评估指标和损失函数经常不一致这也是为什么训练出来的模型在验证集上表现很好放到线上就现出原形。这五个角色串起来就是一次完整的深度学习迭代闭环。所有复杂的技巧比如正则化、数据增强、学习率调度、迁移学习、蒸馏、量化本质上都是在优化这个闭环中某个环节的效率或效果没有哪个技巧是银弹。2. 深度学习任务场景与常用模型结构深度学习落地跟做菜很像得先知道客人想吃什么菜系再决定准备什么厨具。来来回回主要就是这几类场景。2.1 图像分类、检测、分割CNN与目标检测链路图像分类是CV领域最基础的任务输入一张图输出一个类别标签。经典的CNN结构从AlexNet到VGG、ResNet、DenseNet、EfficientNet一路演化下来核心逻辑都在解决如何让网络更深的同时不至于退化和难收敛。ResNet提出的残差连接可以说是近几年深度学习最重要的单点创新——它让训练几百层的网络变得可行。残差连接的思想后来也被Transformer、MLP-Mixer等各种结构广泛吸收。目标检测则走的是另外一条路既要找到什么东西在哪里又要输出目标和类别。以YOLO为代表的单阶段检测器优点就是快以Faster R-CNN为代表的两阶段检测器精度更高但速度慢一些。这里要补充一句实际工程里YOLO系用的非常多正是因为部署方便、实时性好、社区生态成熟。缺陷检测、工业质检、安防监控、遥感影像识别这些方向YOLO几乎是标配。图像分割分为语义分割和实例分割基本思路是对每个像素做分类。UNet在医学图像分割里是绝对的主角因为它结构对称、代码简单、在少量数据上也能训练出不错的效果。2.2 文本任务从RNN到Transformer自然语言处理里最核心的问题是如何让模型理解词的语义和句子的结构。早期Embedding加RNN、LSTM的做法本质上是设计一个顺序处理的结构让模型一个词一个词地读句子同时用内部状态记住之前的语义信息。但这种顺序处理有两个天然问题一是无法并行训练速度上不去二是长距离依赖很难学也就是序列太长之后靠循环结构传播信息会衰减得很厉害。Transformer的核心创新在于自注意力机制让任意两个位置的词可以直接交互一步到位建立全局依赖。这就解释了为什么Transformer能后来居上成为NLP领域的事实标准也解释了为什么预训练语言模型BERT系、GPT系能通过大规模语料预训练加下游微调的模式横扫各种榜单。2.3 序列、语音与时序数据语音识别、语音合成、音乐生成、传感器时序数据这类问题看似五花八门但共性都是数据有时间顺序。CNN加注意力也能处理这类问题比如用一维卷积去提取局部模式RNN/LSTM处理序列依赖Transformer并行能力强但直接用在超长时序上要小心显存。实际的工业界做法往往是几种结构混合使用Conv提取局部特征LSTM或者Transformer建模时序依赖再加一个全连接头去输出预测结果。2.4 生成任务与强化学习生成任务最知名的是GAN和扩散模型。生成式AI火起来以后扩散模型几乎统一了图像生成领域Stable Diffusion就是典型代表。强化学习完全是另一套逻辑它不基于静态数据集做监督训练而是让智能体在环境里通过试错来学习策略。AlphaGo、机器人控制、推荐系统中的探索利用都跟强化学习有关。注意这里的内容比较深入门阶段不必一头扎进去先把监督学习框架玩熟收益更高。3. 为什么选PyTorch以及不同框架之间的真实差异聊完了任务和结构落到工具选型上。现在主流框架无非PyTorch、TensorFlow、PaddlePaddle、JAX这几个选型这件事看似无关紧要实际上会长期影响你的开发效率和调试心态。3.1 框架采用的编程范式不同PyTorch是动态图边定义边执行想输出哪个中间结果就打印哪个中间结果debug起来非常顺手。TensorFlow 2虽然也默认了动态图但整体设计痕迹太重很多老代码是1.x的静态图风格网上搜到的教程五花八门新人很难分辨过时教程。PaddlePaddle百度在推中文文档和社区做得好国内很多工业项目在用但国际社区生态还是弱一些。JAX追求函数式编程和高性能计算适合搞研究、写底层库的人不太适合新手入门。我自己的判断是如果你目标是快速上手做项目、搞研究、或者转行AI工程师选PyTorch是当前风险最低的选择。它的生态太庞大了几乎所有最新论文都会放出PyTorch实现遇到问题一搜一大把解决方案。3.2 生态完整度和社区活跃度PyTorch生态里有几个核心库撑起了科研和落地的大部分环节。torchvision提供了常用数据集、预训练模型、图像变换工具做CV方向离不开它。torchaudio面向音频处理torchtext面向文本处理虽然近两年torchtext迭代有点混乱但NLP任务的数据处理大部分人还是会结合HuggingFace的transformers和datasets库来用。HuggingFace虽然不是PyTorch官方出品但几乎成了NLP领域的标配把预训练模型的加载和使用简化到了极致。Lightning则是在PyTorch之上做了一个封装层帮你处理训练循环、分布式训练、日志记录等样板代码做大型实验的时候能省不少事。3.3 TensorFlow和PyTorch的流行趋势变化前面热搜词里提到一个tensorflow与pytorch的流行趋势2024年这一年之后TensorFlow在学术界的份额进一步缩水PyTorch基本成了论文开源的第一选择。这并不是说TensorFlow没有价值它在生产环境的部署工具链方面仍然有优势例如TF Serving而且国内很多大企业的存量系统都是用TensorFlow搭的。但从新项目的技术选型角度看PyTorch占优的趋势非常明确。4. PyTorch环境搭建实战从零到能跑GPU训练环境搭建看似简单但根据我的经验这一步卡掉的人比后面的算法学习多得多。这里给出我跑过很多次的一套稳妥流程按这个顺序操作基本不会有幺蛾子。4.1 先确认显卡和驱动信息在安装PyTorch之前先看看电脑上有没有NVIDIA独立显卡。在命令行里输入nvidia-smi如果能正常显示显卡信息说明驱动已经装好了。重点看右上角的CUDA Version注意这个表示当前驱动支持的最高CUDA版本不代表你系统里已经装了CUDA。这里要明确一个概念PyTorch安装包是自带CUDA相关组件的不需要单独安装完整的CUDA Toolkit。很多教程让人先去NVIDIA官网下载CUDA对于只是用PyTorch的人来说这是多余的步骤还容易因为环境变量配置错误把自己搞晕。只要驱动版本够新直接安装对应CUDA版本的PyTorch即可。如果输入nvidia-smi显示不是内部或外部命令说明驱动没装或者没装好。去NVIDIA官网下载驱动安装好再继续。4.2 用Anaconda还是Miniconda建议用Miniconda。Anaconda预装太多用不到的包又大又慢Miniconda只有conda和Python后面缺什么装什么干净清爽。安装好conda之后创建一个新的虚拟环境执行conda create -n torch python3.10 conda activate torchPython版本这里不用选最新的PyTorch的兼容性往往滞后于Python最新版本。3.9、3.10、3.11都比较稳3.12后有些老版本包会编译报错没必要冒这个险。4.3 正确安装PyTorch去PyTorch官网的Get Started页面选择合适的操作系统、包管理器、CUDA版本官网会给出对应的安装命令。比如Linux系统、conda安装、CUDA 12.1命令大概是conda install pytorch torchvision torchaudio pytorch-cuda12.1 -c pytorch -c nvidia用pip安装的话pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121这里注意千万不要在搜索引擎里找那种一条命令安装GPU版PyTorch的教程很多老帖子的命令对应的是旧版本安装完跑torch.cuda.is_available()显示False排查起来更费劲。提示CPU版本的PyTorch和GPU版本的PyTorch安装包是不同的。CPU版安装命令是pip install torch torchvision torchaudioGPU版必须走官网给的带CUDA标识的安装源。如果只是想跑通代码不训练大模型CPU版也能学但真正训练的时候速度差距是几十倍。4.4 验证安装是否成功python -c import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.get_device_name(0))如果输出类似2.4.0 True NVIDIA GeForce RTX ...说明环境就绪了。如果torch.cuda.is_available()返回False先别急着换命令检查以下三点驱动是否是近几年更新的版本是否安装了CPU版的PyTorch如果torch.backends.cuda.is_built()返回True但是is_available()返回False大概率是驱动太老虚拟环境是否激活。4.5 Linux服务器和Windows的差异在生产训练环境中绝大多数情况是Linux服务器。在Linux上离线安装PyTorch也是个高频需求尤其是内网环境。解决思路是找一台能联网的同系统机器用pip download把需要的安装包和依赖全下下来再拷贝到内网机器上离线安装。具体来说pip download torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 -d /path/to/download_dir然后把整个目录拷贝到内网机器执行pip install --no-index --find-links/path/to/download_dir torch torchvision torchaudioWindows用户需要注意PyTorch在Windows上使用NVIDIA的GPU需要额外确认Microsoft Visual C Redistributable是否安装大部分情况下系统会自动装但有时候没装会导致运行时报错找不到torch_python.dll。4.6 使用云平台和DCU等国产加速卡的情况如果本机没有显卡可以考虑云GPU平台像AutoDL、恒源云这些按小时计费配置好镜像和环境花几块钱就把环境跑通了。另外热搜词里出现的dcu版pytorch值得提一句。DCU是国产加速卡AMD旗下的海光信息也有类似产品部分国产加速卡厂商会提供自己魔改过的PyTorch版本安装方法和NVIDIA版略有不同通常需要去对应厂商的官网下载安装包。整体使用逻辑和标准PyTorch基本一致但细节上要注意算子支持度不是所有PyTorch算子都被国产加速卡支持。5. PyTorch核心机制拆解张量、自动求导与模型构建装好环境之后下一步是理解PyTorch到底怎么帮你完成前面说的定义函数、求梯度这个动作。PyTorch的核心组件就三个张量、自动求导、模块系统。5.1 张量numpy在GPU上的亲戚张量Tensor是PyTorch的基本数据结构你可以理解成带GPU加速的numpy数组。张量和numpy数组一个重要的区别是张量可以记录自身的运算历史配合自动求导机制方便求出梯度。import torch x torch.tensor([[1.0, 2.0], [3.0, 4.0]], requires_gradTrue)这里的requires_gradTrue表示这个张量在后续计算中需要计算梯度。创建张量的方式很多可以从list构造可以用torch.zeros、torch.randn、torch.ones生成也可以用torch.from_numpy从numpy数组转换。注意PyTorch中张量默认是浮点数32位float32深度学习模型里基本都用float32显存不够时可以降到float16甚至bfloat16。5.2 自动求导机制这是PyTorch最核心的设计之一。你不用手动推导梯度公式只要把张量之间的运算关系建好然后调用backward()PyTorch就会通过反向传播自动计算所有requires_gradTrue的张量的梯度。loss (x ** 2).sum() loss.backward() print(x.grad) # tensor([[2., 4.], [6., 8.]])每个张量内部都有一个grad_fn记录了它是怎么算出来的。反向传播时PyTorch沿着计算图从输出到输入用链式法则逐层算出梯度。理解计算图是理解PyTorch调优的前提很多训练中出现的问题本质都是对自动求导机制的误解。例如原地修改张量值导致计算图断链、在不需要梯度的场景下忘了用torch.no_grad()导致显存爆炸这些都是新手常犯的问题。5.3 模型构建nn.Module的定义方式PyTorch中用nn.Module来封装模型。一个模型类通常包含__init__方法定义层结构和forward方法定义前向传播其他地方跟普通Python类没什么区别。import torch.nn as nn import torch.nn.functional as F class MyNetwork(nn.Module): def __init__(self): super().__init__() self.conv1 nn.Conv2d(1, 32, kernel_size3) self.fc1 nn.Linear(32 * 13 * 13, 10) def forward(self, x): x F.relu(self.conv1(x)) x torch.flatten(x, 1) x self.fc1(x) return x运行时PyTorch自动追踪forward里用到的所有参数并用.parameters()方法返回可训练参数列表。优化器拿到这个列表就能在反向传播之后更新参数。5.4 数据集与DataLoader真实项目里数据不是一次性全塞进模型的因为显存放不下必须分批送入模型训练。PyTorch用Dataset和DataLoader两个类配合完成这件事。Dataset实现给定一个索引返回样本和标签的接口DataLoader负责打乱、分批、多进程加载、自动收集batch。from torch.utils.data import Dataset, DataLoader class MyDataset(Dataset): def __init__(self, images, labels): self.images images self.labels labels def __len__(self): return len(self.labels) def __getitem__(self, idx): return self.images[idx], self.labels[idx] dataloader DataLoader(MyDataset(images, labels), batch_size32, shuffleTrue, num_workers4)num_workers是个容易忽略的参数设置成0表示在主进程加载数据多了会拖慢训练设成4或8能明显提速但太大也可能因为内存不够导致死机具体数值要看机器配置。5.5 torchvision与数据转换图像任务里torchvision提供了一整套数据加载和预处理工具包括transforms的序列操作调整尺寸、转张量、归一化、数据增强等。from torchvision import transforms transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ])这里的Normalize归一化用的mean和std是ImageNet数据集的统计值如果你做的是自己领域的任务通常可以直接沿用这个值因为大多数预训练模型都是按这个分布训练的也可以根据自己数据重新统计。6. 一个完整的训练循环手写数字识别实战纸上谈兵不如动手跑一遍。下面用MNIST手写数字识别为例把从数据到训练再到保存模型的完整流程走一遍。这一步看懂了后续任何深度学习项目都是在这个骨架上做扩展。6.1 准备数据和模型MNIST是28x28的灰度图共10个类别0到9torchvision里自带下载。import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) train_dataset datasets.MNIST(./data, trainTrue, downloadTrue, transformtransform) test_dataset datasets.MNIST(./data, trainFalse, downloadTrue, transformtransform) train_loader DataLoader(train_dataset, batch_size64, shuffleTrue) test_loader DataLoader(test_dataset, batch_size1000, shuffleFalse)模型用一个简单的两层卷积加全连接class CNN(nn.Module): def __init__(self): super().__init__() self.conv1 nn.Conv2d(1, 16, kernel_size3, padding1) self.conv2 nn.Conv2d(16, 32, kernel_size3, padding1) self.pool nn.MaxPool2d(2, 2) self.fc1 nn.Linear(32 * 7 * 7, 128) self.fc2 nn.Linear(128, 10) def forward(self, x): x self.pool(torch.relu(self.conv1(x))) x self.pool(torch.relu(self.conv2(x))) x torch.flatten(x, 1) x torch.relu(self.fc1(x)) x self.fc2(x) return x这里需要注意最后的fc2没有接激活函数因为后面要跟CrossEntropyLossPyTorch的交叉熵损失内部自带softmax操作不需要在模型里显式输出概率。6.2 训练model CNN() optimizer optim.Adam(model.parameters(), lr0.001) criterion nn.CrossEntropyLoss() def train_one_epoch(epoch): model.train() total_loss 0 correct 0 total 0 for data, target in train_loader: optimizer.zero_grad() output model(data) loss criterion(output, target) loss.backward() optimizer.step() total_loss loss.item() pred output.argmax(dim1, keepdimTrue) correct pred.eq(target.view_as(pred)).sum().item() total target.size(0) print(fEpoch {epoch}: loss{total_loss/len(train_loader):.4f}, acc{correct/total:.4f})一段一段来拆解这段代码的每一步在做什么。optimizer.zero_grad()PyTorch的梯度是累加的不清零的话下一batch的梯度会加在上一batch上。无数新人踩过这个坑忘记清零导致loss震荡完全无法收敛。model.train() / model.eval()这个切换影响dropout和batch normalization的行为。训练时dropout会随机失活神经元评估时必须关闭随机性。loss.backward()执行反向传播把梯度算出来存在每个参数的.grad属性里。optimizer.step()根据梯度去更新参数。6.3 评估def evaluate(): model.eval() test_loss 0 correct 0 with torch.no_grad(): for data, target in test_loader: output model(data) test_loss criterion(output, target).item() pred output.argmax(dim1, keepdimTrue) correct pred.eq(target.view_as(pred)).sum().item() acc correct / len(test_loader.dataset) print(fTest loss: {test_loss/len(test_loader):.4f}, Test acc: {acc:.4f}) return acc评估阶段用torch.no_grad()包裹意思是不需要计算梯度。这不仅是为了省算力更重要的是省显存。如果不加这个上下文管理器推理时也会为中间变量分配内存存储运算历史很快就OOM了。6.4 训练轮数对精度的影响以及过拟合MNIST数据集比较简单训练5个epoch就能到99%以上的准确率。但训练轮数越多精度越高这个直觉在真实项目中并不总是成立。训练初期loss下降快精度快速提升。训练后期模型可能开始过拟合——在训练集上表现越来越好在验证集上却停滞甚至下降。这时候再增加训练轮数只会让情况更糟糕。更合理的做法是用early stopping也就是监控验证集指标连续几个epoch没有提升就提前停止训练同时保存验证集指标最好的模型权重。7. 训练中常见的坑与排查思路这一节我把自己踩过和带学员见过的坑集中整理一下很多问题在网上反复被问说明不是个别现象。7.1 loss没有变化或者直接变成NaNloss如果一直是初始值附近波动先检查学习率是不是太大或者太小。学习率太大会导致参数更新幅度过大loss直接爆掉变成NaN太小则模型几乎不更新loss降不动。loss变成NaN还有几个常见原因数据里有NaN值而没有处理初始权重有问题梯度爆炸。解决办法是先把数据集清洗一遍检查输入是否包含NaN用更小的学习率试跑适当增加梯度裁剪。torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm1.0)这行代码放在backward()之后、step()之前可以把梯度范数限制在合理范围内。7.2 训练准确率高但测试准确率低这是典型的过拟合。应对手段包括增加数据增强、添加Dropout、引入正则化L2 weight decay、使用早停、用小一点的学习率、考虑迁移学习用预训练模型做微调。7.3 显存不足OOM好消息是这个报错信息非常明确坏消息是日常训练中它几乎无法避免。解决思路有这几层减小batch_size是最直接的减少图像输入尺寸使用混合精度训练也就是float16和float32混用如果用的是NVIDIA 20系及以上显卡可以用torch.cuda.amp轻松开启显存占用减少一半左右训练速度还更快检查是不是不小心把整个数据集加载到显存里了用torch.no_grad()包裹推理过程对无用变量及时删掉、调用torch.cuda.empty_cache()释放缓存内存。7.4 模型保存和加载PyTorch保存模型有两种主流方式。只保存模型参数推荐方式torch.save(model.state_dict(), model.pt)这种方式占用空间小加载时要求先定义出相同结构的模型类然后把参数灌进去model CNN() model.load_state_dict(torch.load(model.pt)) model.eval()另一种是保存整个模型torch.save(model, model_full.pt)这种方式加载时不需要提前定义模型结构直接model torch.load(model_full.pt)就能用。但这种方式对代码重构很不友好模型类定义改了旧文件就废了。实际工程中建议用第一方式。如果加载时遇到module.前缀的key报错是因为训练时用了DataParallel或DistributedDataParallel参数名多了模块前缀。加载时做一次strip即可from collections import OrderedDict state_dict torch.load(model.pt) new_state_dict OrderedDict() for k, v in state_dict.items(): name k.replace(module., ) new_state_dict[name] v model.load_state_dict(new_state_dict)7.5 自定义数据集加载亮红牌热搜词里提到PyTorch处理高光谱HDR文件和SPE文件的问题这其实是很多科研人员的痛点。PyTorch原生不支持这些专用格式但处理思路是通用的先把文件用专业库读成numpy数组再包成Dataset类。高光谱HDR文件一般配合ENVI格式可以用spectral库读取SPE文件可以用spe2py或者pims读取。读取成功后照常封装成Dataset类就行。这里多提一嘴remote sensing里的ENVI深度学习工具是另一条技术路线和PyTorch社区不太互通。我在实际项目里遇到过ENVI深度学习训练失败的情况排了半天发现是输入图像波段数超出模型预期。如果你打算在自己的流程里做多波段数据处理先确认模型第一层卷积的输入通道数是不是和波段数一致。8. PyTorch里的其他高频操作8.1 forward函数如何调用很多初学者会问nn.Module里明明定义了forward方法代码里为什么是model(x)而不是model.forward(x)因为nn.Module重写了__call__方法调用model(x)会走内部hooks注册和参数检查的流程最终再调用forward方法。所以请用model(x)这种调用方式不要直接调用model.forward(x)否则在用了hooks或者某些封装层的场景下行为会异常。8.2 模型参数的统计想要知道自己的模型有多少参数量非常简单total_params sum(p.numel() for p in model.parameters()) trainable_params sum(p.numel() for p in model.parameters() if p.requires_grad) print(total_params, trainable_params)参数量只是模型规模的一个指标并不直接等于模型性能。同样参数量不同结构设计效果可能天差地别。8.3 使用GPU训练模型和数据都需要显式移动到GPUdevice torch.device(cuda if torch.cuda.is_available() else cpu) model model.to(device) data data.to(device) target target.to(device)注意数据和模型必须在同一个设备上否则会报Expected all tensors to be on the same device的错误。这种错误在多层模型中尤其恼人往往要逐层排查哪些Tensor还留在CPU上。8.4 从pt到bin或者ONNX的转换热搜词里有个问题叫pytorch bin转换为pt实际上很多深度学习框架的模型文件扩展名都是.bin比如HuggingFace的模型文件就是.bin格式内部其实就是state_dict的序列化结果。你用torch.load(model.bin)去看经常能直接读出来。模型部署经常需要转成ONNXdummy_input torch.randn(1, 3, 224, 224) torch.onnx.export(model, dummy_input, model.onnx, input_names[input], output_names[output])导出ONNX之后可以用ONNX Runtime或者TensorRT做推理部署速度和资源占用都比直接用PyTorch推理更理想。9. 深度学习实用工具链和生态盘点工具决定效率一个顺手的工具链能省下一半的时间。PyTorch生态里有几个工具是我现在几乎每天都会用到的。TensorBoard是训练过程可视化工具中最老牌的一个虽然名字带TensorFlow但它完全独立于TensorFlowPyTorch直接支持。用它记录下来loss曲线、学习率变化、模型结构图from torch.utils.tensorboard import SummaryWriter writer SummaryWriter(runs/exp1) writer.add_scalar(loss/train, loss, epoch) writer.add_scalars(loss/train_val, {train: train_loss, val: val_loss}, epoch)scikit-learn虽然不算深度学习库但它提供了一堆模型评估和预处理函数测试集上算混淆矩阵、报告精确率召回率一行代码搞定。OpenCV在图像读取、预处理、形态学操作、检测结果后处理这些环节几乎是标配。尤其工业项目里缺陷检测通常用深度学习模型分割出缺陷区域再用OpenCV做后处理过滤噪声和提取面积、周长等特征。热搜词里python常用视觉库和深度学习库问的应该就是这个组合我在实际项目里给新人的建议是OpenCV加PyTorch加scikit-image加Pillow这四个库覆盖95%以上的视觉任务了。albumentations这个库做图像增强比torchvision的transforms更强速度快且增强策略丰富。部署层面PyTorch官方提供了TorchScript和TorchServe第三方方案ONNX Runtime、TensorRT、OpenVINO也都很成熟。现在很多实际场景还会关注微信小程序运行深度学习模型的问题这种场景通常需要把模型转成TensorFlow Lite或者ONNX精简版跑在端侧设备上但之前提到的部署思路一样训练用PyTorch导出用ONNX推理用对应的推理引擎。10. 国内学习和实战资源建议与路线规划很多人收藏了一堆资料却不知道怎么开始这里按顺序给一条实践过的学习路线按这个走基本不会走偏。第一步完成深度学习的总览认知构建搞明白机器学习的基本概念。目标是认识数据、特征、模型、训练、测试、过拟合、泛化这些关键词。资料的话吴恩达的机器学习课程、李宏毅的机器学习课程都值得看后者在深度学习部分讲得更详细直观。第二步入门PyTorch。把本文前面几章的代码敲一遍然后可以看动手学深度学习这本书Dive into Deep Learning它最难得的地方是理论和代码结合得很好每一章都有可运行的PyTorch实现适合作为工具书反复查。学完之后你会对张量、自动求导、模型、训练循环有实质性认识。第三步跑到第三个第五个项目时你多半会遇到模型不收敛、loss曲线异常、显存暴涨等问题。这时候再把pytorch的官方文档和论坛翻一遍理解背后的机制。有一点我必须强调不要沉迷于刷视频教程。深度学习不是看会的是写代码写会的。视频几十个小时刷完不如亲手跑通一个模型再尝试改结构、换优化器、调学习率。这样折腾几天下来学到的比看一百个视频都多。而且不要一开始就追求搞懂所有数学公式。我的建议是先会开车再学发动机原理。先跑通代码建立直觉遇到性能问题了再去翻公式效率反而更高。还有一个实用性很强的心得学习过程中准备一本本地笔记记录一个项目的完整链路——数据长什么样、模型结构怎么定义的、每个超参数是怎么定的、loss曲线是在哪个epoch开始下不去了。很多参数组合实验没过多久就会忘记这些记录在你之后做真实项目时能帮你快速定位问题。深度学习的门槛确实存在但它没有传说中那么高。关键是你得用对方式——先建立全局认知再动手实践再回头补理论在踩坑中逐步成长。PyTorch作为当前最主流的深度学习框架为这条学习路径提供了一个非常友好的起点。只要把环境装好、把第一个模型训练出来你会发现自己已经迈过了最难的那道坎。接下来要做的就是持续在项目里打磨遇到问题解决问题多看多问多总结这行没有捷径但也没有想象中那么难。
返回列表