PyTorch深度学习入门指南:从环境搭建到模型训练全流程

1. 从零上手 PyTorch:为什么它是深度学习入门的首选框架

如果你刚开始接触深度学习,或者已经用过其他框架但想转到 PyTorch,大概率会遇到一个很现实的问题:到底该从哪儿下手?网上教程一大堆,但要么是纯理论推导让人昏昏欲睡,要么是直接甩一个完整项目让你照抄却不知道每行代码在干什么。我自己当年从零学 PyTorch 的时候,光环境配置就折腾了大半天,后来才发现很多坑其实完全可以绕过去。

PyTorch 是 Facebook 人工智能研究院开源的一个深度学习框架,核心卖点是动态计算图和Python 原生风格。说人话就是:你写 PyTorch 代码的感觉就像在写普通的 Python 程序,该调试调试,该打印打印,不用先定义一个完整的计算图再跑。这对新手来说太重要了,因为你可以像调试普通代码一样去排查模型的问题,而不是对着一堆图结构发呆。

这篇文章适合谁看?如果你满足以下任意一条,接下来的内容应该能帮到你:

  • 刚学完 Python 基础,想入门深度学习但不知道选哪个框架
  • 用过其他框架,想转到 PyTorch 但被各种 API 搞晕了
  • 能跑通别人的 Demo,但自己从头写一个模型就卡壳
  • 想搞清楚 PyTorch 的核心机制到底是怎么回事,而不是只会调库

我会从环境搭建开始,一步步讲到张量操作、自动求导、模型构建、训练流程,最后分享一些我实际踩过的坑和总结出来的经验。每部分都会解释“为什么这么做”,而不是只给代码让你抄。

2. 环境搭建:那些教程不会告诉你的细节

2.1 版本选择的核心逻辑

PyTorch 的版本更新非常快,几乎每几个月就有新版本。很多人上来就装最新的,结果发现跟自己的显卡驱动不匹配,或者跟其他依赖库冲突。我的建议是:不要盲目追新,选一个稳定版本就行。

截至我写这篇内容的时候,PyTorch 2.x 系列已经比较成熟了。如果你用的是 NVIDIA 显卡,需要关注 CUDA 版本和 PyTorch 版本的对应关系。这个对应关系在 PyTorch 官网有明确的表格,但很多人会忽略一个关键点:你显卡驱动支持的 CUDA 版本,不一定等于 PyTorch 需要的 CUDA 版本。

举个例子,你的显卡驱动可能支持 CUDA 12.1,但你想装的 PyTorch 版本只支持 CUDA 11.8。这时候你有两个选择:要么升级显卡驱动,要么选一个支持 CUDA 12.1 的 PyTorch 版本。我个人的经验是,如果驱动不是特别老,优先选跟驱动匹配的 PyTorch 版本,省得折腾。

2.2 安装方式的取舍

PyTorch 提供了几种安装方式:pip、conda、源码编译。对于绝大多数人来说,pip 和 conda 就够了,源码编译除非你有特殊需求,否则完全没必要。

pip 安装的好处是简单直接,一条命令搞定。conda 的好处是能帮你管理 CUDA 和 cuDNN 的依赖,省得自己配。我个人的习惯是:如果用的是 conda 环境,就用 conda 装;如果是纯 pip 环境,就用 pip 装。不要混着用,否则容易出现依赖冲突。

安装命令在 PyTorch 官网有生成器,你选好版本、系统、安装方式,它会给你一条完整的命令。这里有个小技巧:先把命令复制到文本编辑器里看一眼,确认 CUDA 版本和你的环境匹配再执行。我见过太多人直接复制粘贴,结果装了个 CPU 版本,训练的时候发现用不了显卡,又得重装。

2.3 验证安装是否成功

装完之后别急着写模型,先验证一下。打开 Python 交互环境,输入以下代码:

import torch print(torch.__version__) print(torch.cuda.is_available())

如果第一行输出了版本号,第二行输出了True,说明 GPU 版本安装成功。如果第二行是False,要么你装的是 CPU 版本,要么 CUDA 环境有问题。

这里有个常见的坑:有些人装了 GPU 版本,但torch.cuda.is_available()返回False。原因通常是 CUDA 版本和显卡驱动不匹配,或者环境变量没配好。排查方法是先确认显卡驱动版本,再确认 PyTorch 编译时用的 CUDA 版本,两者要兼容。

提示:如果你用的是笔记本电脑,且有独立显卡和集成显卡,确保 Python 使用的是独立显卡。有些系统默认会用集成显卡跑,导致 CUDA 不可用。

3. 张量操作:PyTorch 的地基该怎么打

3.1 张量到底是什么

张量这个词听起来很唬人,其实你可以把它理解成多维数组。标量是 0 维张量,向量是 1 维张量,矩阵是 2 维张量,再往上就是 3 维、4 维甚至更高维的张量。PyTorch 的一切操作都建立在张量之上,所以这部分必须打牢。

创建一个张量有很多种方式,最常用的是torch.tensor()、torch.zeros()、torch.ones()、torch.randn()。我刚开始学的时候经常搞混torch.tensor()和torch.Tensor(),后来才搞清楚:torch.tensor()是根据你给的数据推断类型,torch.Tensor()是创建一个默认类型的张量。建议统一用torch.tensor(),不容易出错。

import torch # 从列表创建 a = torch.tensor([1, 2, 3]) print(a) # tensor([1, 2, 3]) # 创建全零张量 b = torch.zeros(2, 3) print(b) # 创建随机张量 c = torch.randn(2, 3) print(c)

3.2 形状操作:最容易出错的地方

张量的形状操作是新手最容易踩坑的地方。view()、reshape()、permute()、transpose()这几个函数看起来差不多,但用错了就会报错或者得到错误的结果。

view()和reshape()的区别在于:view()要求张量在内存中是连续的,reshape()不要求。如果你不确定张量是否连续,直接用reshape()更安全。permute()是交换维度,transpose()是交换两个维度。举个例子,一个形状为(2, 3, 4)的张量,用permute(2, 0, 1)之后形状变成(4, 2, 3)。

这里有个我踩过的坑:在神经网络中,全连接层的输入需要是二维的,但卷积层的输出通常是四维的。这时候需要用view()或reshape()把四维张量展平成二维。如果搞错了维度顺序,模型能跑但结果完全不对,而且不会报错,非常隐蔽。

3.3 广播机制:省代码但容易出 bug

广播机制是 PyTorch 中非常强大的一个特性,它允许不同形状的张量进行运算。比如一个形状为(3, 4)的张量和一个形状为(4,)的张量相加,PyTorch 会自动把后者扩展成(3, 4)。

这个机制能省很多代码,但也容易出 bug。因为广播是自动的,不会报错,所以如果你不小心搞错了形状,可能得到一个看似合理但完全错误的结果。我的建议是:在关键运算之前,先打印张量的形状确认一下。这个习惯能帮你省很多调试时间。

a = torch.randn(3, 4) b = torch.randn(4) c = a + b # b 被广播成 (3, 4) print(c.shape) # torch.Size([3, 4])

4. 自动求导机制:PyTorch 最核心的设计

4.1 计算图是怎么工作的

PyTorch 的自动求导机制是它最核心的功能之一。简单来说,当你对一个张量进行操作时,PyTorch 会在后台记录这些操作,形成一个计算图。当你调用backward()时,它会沿着这个计算图反向传播,自动计算梯度。

这个机制的关键在于requires_grad属性。只有设置了requires_grad=True的张量,PyTorch 才会追踪它的操作。模型的参数默认都是requires_grad=True,而输入数据通常是False。

x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True) y = x ** 2 z = y.sum() z.backward() print(x.grad) # tensor([2., 4., 6.])

这段代码的意思是:z是x的平方和,对x求导得到2x,所以梯度是[2, 4, 6]。

4.2 梯度累积与清零

这是新手最容易忽略的一个点:PyTorch 的梯度是累积的。也就是说,如果你不手动清零,每次backward()之后梯度会累加到之前的梯度上。这在某些场景下有用(比如梯度累积训练大 batch),但大多数情况下你需要手动清零。

标准做法是在每次训练迭代开始时调用optimizer.zero_grad()。我见过很多人忘了这一步,结果模型训练效果很差,排查半天才发现是梯度累积导致的。

注意:optimizer.zero_grad()和model.zero_grad()效果类似,但推荐用optimizer.zero_grad(),因为有些优化器有特殊处理。

4.3 禁用梯度追踪的场景

有些时候你不需要梯度,比如在验证阶段或者推理阶段。这时候可以用torch.no_grad()上下文管理器来禁用梯度追踪,能省显存也能加速。

with torch.no_grad(): output = model(input)

还有一个常用的方法是detach(),它能把一个张量从计算图中分离出来,返回一个新的张量,不携带梯度信息。这在处理损失函数或者记录指标时很有用。

5. 模型构建:从 nn.Module 开始

5.1 nn.Module 的基本用法

PyTorch 中所有的神经网络模型都继承自nn.Module。你需要实现两个方法:__init__和forward。__init__里定义网络层,forward里定义前向传播的逻辑。

import torch.nn as nn class SimpleNet(nn.Module): def __init__(self): super().__init__() self.fc1 = nn.Linear(784, 256) self.fc2 = nn.Linear(256, 10) self.relu = nn.ReLU() def forward(self, x): x = self.relu(self.fc1(x)) x = self.fc2(x) return x

这个结构看起来很简单,但有几个细节需要注意。super().__init__()必须调用,否则 PyTorch 无法正确注册参数。层定义在__init__里,逻辑写在forward里,不要搞反了。

5.2 常用层的选择逻辑

PyTorch 提供了丰富的网络层,新手容易挑花眼。我整理了一个简单的选择逻辑:

场景推荐层说明
全连接nn.Linear最基础的层,输入输出都是二维
卷积nn.Conv2d处理图像,注意通道数和卷积核大小
池化nn.MaxPool2d降采样,减少计算量
归一化nn.BatchNorm2d加速训练,防止过拟合
丢弃nn.Dropout正则化,防止过拟合
循环nn.LSTM / nn.GRU处理序列数据

选择层的核心逻辑是:先确定数据的形状和类型,再选对应的层。图像用卷积,序列用循环,表格数据用全连接。不要为了用某个层而强行套用。

5.3 参数初始化的重要性

很多人忽略了参数初始化,直接用默认的。但实际上,好的初始化能显著加速收敛。PyTorch 的默认初始化是 Kaiming 均匀分布,对大多数情况够用。但如果你发现模型训练很慢或者不收敛,可以试试手动初始化。

def init_weights(m): if isinstance(m, nn.Linear): nn.init.xavier_uniform_(m.weight) nn.init.zeros_(m.bias) model.apply(init_weights)

Xavier 初始化适合 tanh 激活函数,Kaiming 初始化适合 ReLU。这个细节在论文里经常被提到,但实际写代码时很多人会忽略。

6. 训练流程:把碎片拼成完整链路

6.1 标准训练循环的五个步骤

PyTorch 的训练循环可以总结为五个步骤:前向传播、计算损失、梯度清零、反向传播、更新参数。这五步缺一不可,顺序也不能乱。

for epoch in range(num_epochs): for batch in dataloader: inputs, labels = batch # 1. 前向传播 outputs = model(inputs) # 2. 计算损失 loss = criterion(outputs, labels) # 3. 梯度清零 optimizer.zero_grad() # 4. 反向传播 loss.backward() # 5. 更新参数 optimizer.step()

这个流程看起来简单,但每一步都有坑。比如梯度清零必须在反向传播之前,否则梯度会累积。optimizer.step()必须在backward()之后,否则没有梯度可更新。

6.2 数据加载的优化技巧

PyTorch 的DataLoader提供了多进程加载、打乱、批处理等功能。有几个参数对训练速度影响很大:

  • num_workers:加载数据的进程数,建议设为 CPU 核心数
  • pin_memory:如果用的是 GPU,设为True能加速数据传输
  • batch_size:根据显存大小调整,太小训练慢,太大可能爆显存

我个人的经验是:先用小 batch 跑通流程,再逐步增大 batch size。这样能快速发现代码问题,而不是等半天才报错。

6.3 验证与保存模型

训练过程中需要定期验证模型效果,防止过拟合。验证时要用model.eval()切换到评估模式,并配合torch.no_grad()禁用梯度。

model.eval() with torch.no_grad(): for batch in val_loader: inputs, labels = batch outputs = model(inputs) # 计算指标 model.train()

保存模型有两种方式:保存整个模型和只保存参数。推荐只保存参数,因为保存整个模型会依赖具体的类定义,加载时容易出问题。

torch.save(model.state_dict(), 'model.pth') model.load_state_dict(torch.load('model.pth'))

7. 那些年我踩过的坑与排查思路

7.1 显存溢出:最常见也最头疼

显存溢出(OOM)是训练深度学习模型时最常见的问题。原因通常有几个:batch size 太大、模型太大、中间变量没释放。排查思路是:先减小 batch size,如果还不行就简化模型,再不行就检查是否有不必要的张量保留。

有一个容易被忽略的点:验证阶段也会占用显存。如果你在验证时没有用torch.no_grad(),PyTorch 会继续追踪梯度,导致显存占用增加。所以验证时一定要加上torch.no_grad()。

7.2 损失不下降:原因可能有很多

损失不下降是另一个常见问题。可能的原因包括:学习率太大或太小、数据没有归一化、模型结构有问题、标签搞错了。排查顺序建议是:先检查数据和标签,再检查学习率,最后检查模型结构。

我遇到过一次损失完全不降的情况,排查了半天发现是数据加载时标签和图像没对应上。这种问题不会报错,但模型根本学不到东西。所以在训练之前,一定要可视化几个 batch 的数据确认一下。

7.3 训练和验证差距大:过拟合的信号

如果训练集上的效果很好,但验证集上很差,说明模型过拟合了。解决方法包括:增加数据量、加正则化(Dropout、权重衰减)、简化模型、早停。我个人的经验是:先加 Dropout 和权重衰减,如果还不行再考虑增加数据。

还有一个容易被忽略的点:BatchNorm 在训练和验证时的行为不同。训练时用当前 batch 的统计量,验证时用全局统计量。所以一定要用model.train()和model.eval()正确切换模式,否则验证结果会不准确。

8. 从能跑到跑好:一些实用的进阶建议

8.1 学习率调度的重要性

学习率是训练中最重要的超参数之一。固定学习率往往不是最优的,使用学习率调度器能显著提升效果。PyTorch 提供了多种调度器,比如StepLR、CosineAnnealingLR、ReduceLROnPlateau。

scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=10)

我个人的习惯是:先用固定学习率跑通,再尝试调度器。CosineAnnealing 在大多数场景下表现不错,ReduceLROnPlateau 适合验证损失波动较大的情况。

8.2 混合精度训练:省显存提速

混合精度训练(AMP)是 PyTorch 1.6 之后引入的功能,能在保持精度的同时减少显存占用、加速训练。用法很简单:

scaler = torch.cuda.amp.GradScaler() for batch in dataloader: with torch.cuda.amp.autocast(): outputs = model(inputs) loss = criterion(outputs, labels) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update()

这个功能对显存紧张的场景特别有用,我实测下来能省 30% 左右的显存,速度也有提升。

8.3 模型调试的实用技巧

最后分享几个调试模型的小技巧。第一,用torchsummary打印模型结构,能快速确认每层的输出形状。第二,用torch.autograd.set_detect_anomaly(True)检测梯度异常,虽然会慢一些,但能定位到具体哪一步出了问题。第三,保存训练过程中的损失和指标,用图表可视化,比看数字直观得多。

还有一个我经常用的方法:先用一个很小的数据集(比如 10 个样本)跑通整个流程,确认代码没问题再上完整数据。这样能快速发现形状不匹配、梯度爆炸等问题,省得等半天才报错。

PyTorch 的学习曲线其实不算陡,但细节很多。我自己的体会是:不要一开始就追求完美,先跑通一个最简单的模型,再逐步加功能。每加一个功能就验证一下,确保没问题再加下一个。这样虽然看起来慢,但实际上比一次性写一大堆代码再调试要快得多。

相关新闻

struct-to-graphql:Go结构体生成Mutation实践

struct-to-graphql:Go结构体生成Mutation实践

一直觉得GraphQL的Mutation是后端开发里最磨人的活之一。Query那边你用Go结构体写着写着还能靠工具省点力,一到Mutation就只能手动拼接SDL字符串、手写input类型、再给每个字段写resolver,结构体改了字段还容易漏同步,上线后又多一堆字段映射…

2026/10/20 14:01:04 阅读更多 →
Yakit指纹识别实战:从HTTP响应头到TCP协议栈锁定真实服务

Yakit指纹识别实战:从HTTP响应头到TCP协议栈锁定真实服务

前阵子给一个客户做资产梳理,扫到一台对外的Web服务。HTTP响应头里清清楚楚写着Server: nginx/1.18.0,连版本号都有,看起来没什么可疑的。但同网段另一台机器上,同样的代码部署,响应头却变成了Server: nginx&#xff0…

2026/10/20 14:01:04 阅读更多 →
ESP32芯片选型与ESPHome实战避坑指南

ESP32芯片选型与ESPHome实战避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 14:01:04 阅读更多 →

最新新闻

Ubuntu 24.04用Docker Compose部署Whisper语音识别服务全指南

Ubuntu 24.04用Docker Compose部署Whisper语音识别服务全指南

如果你需要在Ubuntu 24.04上搭一个完全本地的语音识别服务,把录音、播客、会议音频批量转成文本,同时又不想被一堆Python依赖折腾到怀疑人生,那Whisper配合Docker Compose几乎是我目前试过最省心的组合。我最近把整套流程从零跑通&#xff0c…

2026/10/20 14:45:32 阅读更多 →
NLP数据增强实战:EDA、回译与生成式模型解决小样本过拟合

NLP数据增强实战:EDA、回译与生成式模型解决小样本过拟合

一个训练集只有两三千条标注文本的分类项目,模型在验证集上跑出来的准确率始终提不上去,训练loss快到底了验证loss却在往上走——如果你撞上过这种过拟合的墙,大概率已经意识到,真正短板的不是模型结构,而是数据。NLP数…

2026/10/20 14:45:32 阅读更多 →
PatchPae2内核补丁:破解32位Windows 8.1内存4GB限制

PatchPae2内核补丁:破解32位Windows 8.1内存4GB限制

简介:面向32位Windows 8.1用户的物理内存扩展补丁PatchPae2,用于解锁系统默认无法识别的4GB以上内存。其核心是修改系统内核,启用物理地址扩展(PAE)机制,突破原版32位系统约4GB的寻址上限,适合老…

2026/10/20 14:45:32 阅读更多 →
Keras大数据训练:突破内存限制的3种流式数据供给方案

Keras大数据训练:突破内存限制的3种流式数据供给方案

1. 项目概述:当数据大到内存喊“救命”,Keras不是靠堆内存硬扛的你有没有试过加载一个30GB的CSV,或者读取上万张4K分辨率的医学影像切片,刚调用pd.read_csv()或tf.keras.preprocessing.image.load_img(),Python就直接抛…

2026/10/20 14:45:32 阅读更多 →
OctaFuse Gateway 2.13.0 实测:供应商折扣计价、路由快速测试与用量分析升级

OctaFuse Gateway 2.13.0 实测:供应商折扣计价、路由快速测试与用量分析升级

1. 从版本号背后看这次升级的真实分量做供应链系统集成这行的朋友大概都有个共识:网关类中间件的版本迭代,最怕的就是"为了更新而更新"——加一堆花哨的仪表盘,核心计价逻辑却还是老样子。OctaFuse Gateway 2.13.0 这个版本我拿到手…

2026/10/20 14:45:32 阅读更多 →
免部署AI绘画实战指南:从零生成第一张图的完整路径与避坑要点

免部署AI绘画实战指南:从零生成第一张图的完整路径与避坑要点

很多人第一次听说AI绘画,第一个念头可能就是“这东西是不是得配一台特别牛的电脑?”实际上这两年“免部署、即开即用”的AI绘画方案已经非常成熟了,你不用装Python、不用配CUDA、甚至不用下载动辄几个G的模型文件,打开浏览器就能画…

2026/10/20 14:43:57 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →