PyTorch入门实战:从张量、自动求导到完整训练循环
我最早碰深度学习那阵子用的还是静态图框架。模型写完之后要先“编译”再执行中间过程跟黑盒一样你想打印某个层的输出看一眼都得先搞清楚算子注册到了哪一步。那种感觉怎么说呢有点像蒙眼开车撞了护栏才知道方向偏了。后来切到PyTorch写训练脚本第一次在forward函数里随手print一个张量的shape我就知道回不去了——这才是人写代码的方式。这篇文章就是给准备入门深度学习的读者准备的。我会从框架选型讲到张量机制从自动求导讲到完整跑通一个图像分类模型再把训练循环里那些文档不会明说的细节和坑都翻出来。内容尽量说人话代码可以直接复制去跑适合刚看完理论、想动手敲第一行PyTorch代码的同学也适合已经跑过Demo但总在奇怪报错上卡住的人。1. 为什么我现在会劝新手直接上PyTorch1.1 动态计算图带来的调试自由度早年主流框架是静态图思路你先定义一张完整的计算图把输入输出、层与层之间的连接全部声明好然后整个模型被“编译”成一个固定的执行流程再往里面喂数据。这个设计在部署上有优势但对做研究、调模型的人来说非常不友好——你没法在模型跑到一半的时候停下来看看某个中间结果因为图是预先建好的除非你专门写一堆调试代码去“抓”某个节点的输出。PyTorch走的是另一条路动态计算图。它不预先构建全局结构而是每次前向传播的时候“现场”把计算图搭出来跑完就释放。这意味着你在forward函数里写什么它就是什么——打印、断点、if判断、for循环所有Python原生操作都可以直接用。调试一个模型跟调试普通Python函数没有区别这一条就足以让大多数新手和研究者倒戈。1.2 生态成熟度与学习性价比除了调试体验PyTorch的生态也是我推荐它的重要原因。现在学术界开源的模型实现十个里有八个是PyTorch写的你想找一个预训练模型来迁移学习主流模型库几乎都能直接加载。配套的工具链也很齐全数据加载、分布式训练、模型可视化、部署转换官方和社区都有成熟的方案。对新手来说这意味着你遇到的所有问题几乎都能搜到现成答案不至于卡在一个冷门报错上怀疑人生。当然不是说静态图框架一无是处它在某些工业落地场景下确实有优势。但如果你正处于入门阶段目标是快速理解深度学习原理、把模型跑起来、验证你的想法那么PyTorch的学习曲线绝对是最平滑的。先学会用PyTorch把事情跑通以后再谈部署优化这个顺序不会错。2. 装环境与第一行代码张量到底是什么2.1 环境准备里最容易忽略的两个细节安装PyTorch本身不复杂官方站会给出适配你本机环境的安装命令比如用pip安装CPU版还是GPU版。这里有两个细节我建议新手留意第一个是Python版本。别为省事去装系统自带的古老Python建议装稍微新一点的稳定版本很多第三方组件对老版本的支持会逐渐消失没必要给自己埋坑。第二个是虚拟环境。我见过太多同学全局装了一堆套件版本互相打架最后只能重装系统。老老实实给项目建一个独立环境虽然多敲两行命令但后面能省出大量排查依赖冲突的时间。安装完之后终端里敲一下验证代码确认框架能正常导入即可。如果你有独立显卡并且安装了GPU版驱动可以再检查一下CUDA是否可见后续训练能明显提速。2.2 用生活类比理解张量很多教程上来就抛概念张量就是一个多维数组。这么说没错但我想换个角度帮你建立直觉。你可以把张量理解成“带编号的大型集装箱”一维张量就是一条队列二维张量是一张表格三维张量是一叠表格摞在一起四维以上你直接想象成仓库里的一排货架每层每列都能精确索引到。PyTorch里的torch.Tensor就是这种数据结构但它比普通数组多了两个关键能力一是可以放到显卡上做大规模并行计算二是可以记录自身的计算历史为后面的自动求导服务。对一个刚入门的人来说你要记住的就三件事张量怎么创建、怎么改形状、怎么搬到设备上。创建张量最基本的写法是这样的import torch # 直接通过列表创建 x torch.tensor([1.0, 2.0, 3.0]) print(x.dtype, x.shape, x.device) # torch.float32 torch.Size([3]) cpu # 全零 / 全一 / 随机初始化 zeros torch.zeros(2, 3) ones torch.ones(2, 3) randn torch.randn(2, 3) # 标准正态分布改形状是高频操作最常用的是view和reshape两者都可以改变张量维度只是view要求改动前后元素总数一致且内存连续。reshape更宽容一点它会在必要时复制数据。实际写代码时我用reshape更多省得在报错边缘来回试探。2.3 设备与运算数据到底在哪块“地盘”上深度学习绕不开设备问题。最简单的理解CPU像一个大而全的仓库什么都能干但速度一般显卡像一条专门的高速公路适合处理大批量并行运算但数据要先“运上去”才能跑。在PyTorch里搬运张量的方法就是.to(device)device torch.device(cuda if torch.cuda.is_available() else cpu) x torch.randn(3, 3).to(device)注意一个高频踩坑点如果x在显卡上你直接x.numpy()会报错。必须先把数据搬回CPU再用.detach()切断梯度追踪才能转成NumPy数组。这个顺序很多人记不住写成x.cpu().detach().numpy()就对了。运算本身不复杂加减乘除、矩阵乘法、拼接拆分都能直接用算符或函数完成。我建议新手花半小时把常用运算过一遍后面写模型时会反复用到。3. autograd自动求导PyTorch的发动机舱3.1 手动算梯度早就过时了在自动求导出现之前你要自己实现反向传播把一个复合函数的梯度逐层手动推导出来再写成代码。一旦网络深一点链式法则展开就是一大片数学公式人肉推导既慢又容易错。PyTorch的autograd机制把这个过程完全自动化了。它的核心思路是在每一次前向计算过程中框架会记下张量之间经历了哪些操作形成一个临时的计算关系网。当你调用backward()时框架沿着这张网从输出端向输入端逐层回传梯度每个参与计算的张量都会得到一个.grad属性存放它相对于最终结果的梯度。3.2 一个最小例子看懂梯度回传看个最简单的例子import torch x torch.tensor(3.0, requires_gradTrue) y x ** 2 2 * x 1 y.backward() print(x.grad) # tensor(8.)从数学角度y对x的导数是2x2代入x3得到8。这个结果和框架给出的梯度完全一致。关键在于requires_gradTrue这一句它告诉框架这个张量是“待求导”的你要记录对它做的所有操作。正常情况下输入数据、模型参数里需要更新的部分都要开启梯度追踪而像标签、常量这类不需要求导的保持默认False即可。3.3 三个常用模式no_grad / enable_grad / inference_mode梯度记录不是免费的它要额外存储计算历史占用内存、降低速度。所以在不需要梯度的场景里我们要手动关掉它。最常见的场景是验证和推理。模型已经训练好了你只想让数据过一遍前向过程、看看预测结果这时候再记录计算图纯属浪费。写法是with torch.no_grad(): logits model(x)还有一个inference_mode从名字就能看出是专门为纯推理设计的比no_grad更激进一些效率也更高。如果你只是跑验证集做评估用前者就够了如果是做线上推理或者大规模跑预测可以试试后者。另外提一句模型参数默认是requires_gradTrue的因为我们要通过反向传播更新它们。但如果你想在训练过程中冻结某层比如迁移学习里锁定骨干网络把对应参数的requires_grad置为False就可以了这样优化器也不会更新它们。4. 用nn.Module攒一个能跑通的图像分类模型4.1 一个模块就是一个“积木块”nn.Module是PyTorch里组织模型的基础单元。你可以把它理解成一个积木块块里面既包含参数比如卷积核权重、偏置也包含前向计算逻辑。小模块可以拼成大模块大模块再拼成完整网络层层嵌套非常符合人脑的组织方式。自定义模型的标准写法是两步在__init__里定义层在forward里用这些层完成计算。注意不要在forward里临时创建新层除非你有特殊设计因为只有注册进__init__的子模块才会被框架自动管理参数、自动搬到GPU上。4.2 手写一个精简卷积网络以手写数字识别这类经典任务为例我来写一个能直接跑的卷积网络。输入是单通道的灰度图尺寸可以按28×28来理解这类公开数据集通常都是这个量级import torch import torch.nn as nn class SimpleCNN(nn.Module): def __init__(self, num_classes10): super().__init__() self.features nn.Sequential( nn.Conv2d(1, 32, kernel_size3, padding1), nn.ReLU(inplaceTrue), nn.MaxPool2d(2), nn.Conv2d(32, 64, kernel_size3, padding1), nn.ReLU(inplaceTrue), nn.MaxPool2d(2), ) self.classifier nn.Sequential( nn.Flatten(), nn.Linear(64 * 7 * 7, 128), nn.ReLU(inplaceTrue), nn.Dropout(0.5), nn.Linear(128, num_classes), ) def forward(self, x): x self.features(x) x self.classifier(x) return x这个网络很简单两个卷积块提取特征两次下采样把尺寸缩小最后展平接全连接层输出分类分数。这里我重点说两个容易算错的地方。第一个是卷积后的尺寸变化。如果输入是28×28第一层卷积padding1保持尺寸不变池化后变成14×14第二次卷积仍然保持尺寸池化后变成7×7。所以展平之前是64通道×7×7全连接层第一个维度就是6477。这个数值是你自己推导出来的不是凭空取的。第二个是Dropout。我在分类器里放了它来抑制过拟合但注意它只在训练阶段生效。如果你忘了切换模型的train/eval模式就会出现在验证集上结果飘忽不定的问题。这一点我后面专门展开讲。4.3 Dataset和DataLoader把数据变成“流水线”训练模型不能一次性把全部数据丢进显卡内存扛不住也没必要。正确做法是做成一个可以按序号取样本的数据集再用加载器按批次、按顺序地取数据。Dataset类需要实现两个方法__len__返回样本总数__getitem__根据索引返回一组输入, 标签。DataLoader负责在这之上做批量打包、随机打乱、多进程预取等工作。核心代码长这样from torch.utils.data import Dataset, DataLoader class SimpleDataset(Dataset): def __init__(self, x_data, y_labels): self.x_data x_data self.labels y_labels def __len__(self): return len(self.x_data) def __getitem__(self, idx): return self.x_data[idx], self.labels[idx] train_loader DataLoader(train_set, batch_size64, shuffleTrue, num_workers2) test_loader DataLoader(test_set, batch_size128, shuffleFalse)在Windows上num_workers如果设大于0有概率触发子进程相关的报错业界通用做法是设成0或者把相关代码包进脚本入口别在交互式环境里开多进程预取。宁可慢一点也别卡在一个诡异问题上。5. 训练循环里那些文档不会告诉你的细节5.1 经典三行代码的固定顺序每个训练batch里几乎都是固定的四步清零梯度、前向计算、反向传播、更新参数。代码长这样for epoch in range(epochs): model.train() total_loss 0 for x, y in train_loader: x, y x.to(device), y.to(device) optimizer.zero_grad() # 第一步清零上一次的梯度 logits model(x) # 第二步前向传播 loss criterion(logits, y) # 计算损失 loss.backward() # 第三步反向传播算出梯度 optimizer.step() # 第四步更新参数 total_loss loss.item()我见过至少三个新手把optimizer.zero_grad()写成了loss.backward()之后结果训练曲线上下乱跳准确率完全上不去。原因很简单PyTorch里的梯度是“累加”的不清零的话本次batch的梯度会跟上次的加在一起参数更新的方向就完全错了。这个顺序没有任何商量的余地一定要刻在肌肉记忆里。loss.item()用于取出Python数值方便记录日志。注意这里取的是标量值不会参与计算图追踪。如果你把张量直接存进列表内存会一直持有计算图引用训练几百轮后内存直接爆掉这类问题排查起来非常隐蔽。5.2 train()和eval()两个字就能毁掉你的验证集PyTorch的模型有train和eval两种状态。调用model.train()时Dropout会随机屏蔽神经元BatchNorm会使用当前batch的统计量调用model.eval()时Dropout失效BatchNorm改用训练阶段积累的全局统计量。很多新手把这两个模式混着用训练完了直接在同一个模式下跑验证结果验证准确率一会高一会低还以为模型没收敛。其实不是模型的问题是Dropout在验证阶段还在“随机丢东西”所以你每次跑出来的结果都不一样。正确做法是训练阶段在遍历数据前调用model.train()验证阶段切换到model.eval()并且配合torch.no_grad()关闭梯度追踪。这两条配合起来验证结果才是稳定可靠的。5.3 选损失函数、学习率和batch size的朴素原则分类任务一般用交叉熵损失在PyTorch里是nn.CrossEntropyLoss。有一件事容易混淆这个损失函数内部已经把softmax做了所以模型最后一层直接输出原始分数logits就行不要在模型里再加softmax否则会重复计算。如果你只是想看每个类别的概率那就在推理阶段对logits做softmax。学习率是训练里最需要盯住的超参数。设太大损失会发疯一样乱跳甚至直接变NaN设太小损失半天降不下来。我的习惯是先试1e-3这个量级观察前几个batch的损失下降趋势再逐步调整。如果模型大、数据多可以做学习率衰减让训练后期更平稳。batch size的选择受显存限制同时也影响训练稳定性。太大的batch会导致梯度方向过于“平滑”有时反而需要配合更高的学习率。小batch噪声大但有时候泛化性能意外地好。这块没有金科玉律都是试出来的。我个人经验是先从32或64开始能跑通再往下调优。5.4 训练过程中应该盯住哪些信号训练不是把代码跑完就结束。我建议每轮结束时输出三个数字训练损失、验证损失、验证准确率。你会发现一些典型现象训练损失下降验证损失也在下降正常继续跑。训练损失下降验证损失先降后升过拟合信号考虑加正则、Dropout或数据增强。训练损失和验证损失都下不去可能是学习率不对或者模型容量不足。损失出现NaN大概率是学习率过大也可能是输入数据里有异常值。养成盯这些指标的习惯后你对模型状态的判断会准很多这也是所谓“手感”的来源。6. 高频报错和模型保存加载提前帮你排雷6.1 我踩过最狠的四个坑下面这几个报错每个我都亲眼目睹过无数次也自己踩过。整理成表格给你报错场景根本原因快速解法显卡张量直接转NumPy报错CUDA张量在显存不通CPU内存先.cpu().detach()再.numpy()梯度一直累加训练曲线乱跳忘记调用optimizer.zero_grad()按固定顺序四步走别乱序验证集结果忽高忽低没切model.eval()Dropout还在生效验证前加model.eval()配合no_grad维度对不上Linear层输入尺寸报错conv/pool后的尺寸算错了按输入尺寸逐层推一遍多打印shape还有一个隐形坑如果你用了BatchNorm但训练和验证时batch size特别小比如只有一个样本那么BatchNorm会直接报错或产生极不稳定的统计量。这类问题在视频、长文本这样的变长数据上尤其常见解决办法是调整batch size或改用其他归一化方式。6.2 模型的保存与加载姿势训练完了模型要落盘。PyTorch里最推荐的做法是只保存权重不保存整个模型对象# 保存 torch.save(model.state_dict(), model_weights.pth) # 加载 model SimpleCNN(num_classes10) model.load_state_dict(torch.load(model_weights.pth, map_locationcpu))第一次加载state_dict时你要先手动创建好一个结构完全一致的模型实例再往里填权重。这个设计初看麻烦但它保证了不同机器、不同环境之间加载的兼容性也避免把一堆不稳定的代码对象序列化进文件里。torch.load的map_location参数很常用原模型是在GPU上训练的你现在只有CPU加载时指定map_locationcpu就能正常读到权重省去手动搬运的麻烦。如果是GPU迁移也可以传对应设备名。6.3 从训练到推理还有一段路训练一个模型只是开始真正要把它用起来还要做推理部署。这一步对新手来说可以晚点再研究但我先给你打个底。一个尽量简洁的推理流程是模型加载权重后切到eval模式对输入做和训练时一致的预处理然后在no_grad或inference_mode下跑前向最后把输出概率映射到类别。这里最关键的一点是预处理必须和训练完全一致——很多人训练时用归一化、尺寸缩放推理时忘了做结果模型输出莫名其妙的概率分布还以为模型坏了其实只是数据没对齐。如果后续要做服务化部署可以考虑把模型导出成开放的标准化格式或者配合推理引擎做加速。这部分属于进阶内容我不展开但你提前知道“训练环境≠生产环境”这件事未来会少走很多弯路。我个人最后再分享一个小经验入门阶段千万别纠结在那些花哨的高级API上把张量、自动求导、训练循环这三件事玩明白你就已经掌握了九成的日常开发能力。至于分布式训练、混合精度、模型量化这些都是在基础扎实之后水到渠成的事。先把第一个模型老老实实跑起来比看一百篇教程都管用。

相关新闻

SpringCloud微服务如何读取Nacos配置:从Data ID到动态刷新

SpringCloud微服务如何读取Nacos配置:从Data ID到动态刷新

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

2026/10/14 1:14:05 阅读更多 →
PointNet分类代码深度解析:从对称函数到工程实现

PointNet分类代码深度解析:从对称函数到工程实现

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

2026/10/14 1:14:05 阅读更多 →
Vue项目视频播放方案:原生video标签组件化实战解析

Vue项目视频播放方案:原生video标签组件化实战解析

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

2026/10/14 1:14:05 阅读更多 →

最新新闻

从模糊标题到生产系统:响应式编程与实时流处理实战指南

从模糊标题到生产系统:响应式编程与实时流处理实战指南

1. 从“rea”这个标题说起:一个被低估的缩写背后藏着什么第一次看到“rea”这个标题的时候,我脑子里蹦出来的第一反应是——这大概率又是一个被缩写玩坏了的项目名。做技术的人都有个通病,喜欢把什么都缩成三个字母,仿佛字数越少越…

2026/10/14 11:37:47 阅读更多 →
量贩式KTV数据库设计:ER图与数据流程图实战

量贩式KTV数据库设计:ER图与数据流程图实战

简介:这份资源是面向数据库课程设计、信息系统分析与毕业设计场景的完整文档,围绕量贩式KTV管理信息系统的数据库分析设计展开,适合计算机相关专业学生及需要撰写数据库设计报告的开发者参考。压缩包内共1个doc文件,约1.85MB&…

2026/10/14 11:37:47 阅读更多 →
智慧燃气数字化方案拆解:从埃森哲建议书到SCADA与GIS落地

智慧燃气数字化方案拆解:从埃森哲建议书到SCADA与GIS落地

简介:这份《智慧燃气埃森哲项目建议书》PDF面向燃气及公用事业领域从业者、企业战略规划人员与咨询顾问,聚焦全球公用事业市场化改革背景下的企业战略转型议题。内容系统梳理了北美、欧洲、亚洲、南美及南非等地区的改革进程与民营化路径,剖析…

2026/10/14 11:37:47 阅读更多 →
工厂模式详解:原理、实现与最佳实践

工厂模式详解:原理、实现与最佳实践

1. 工厂模式初探:为什么我们需要它?在软件开发中,对象创建是最基础也最频繁的操作之一。但直接使用new关键字实例化对象会带来一系列问题:代码耦合度高、难以扩展、违反开闭原则。这就是工厂模式要解决的核心痛点。我曾在电商系统…

2026/10/14 11:37:47 阅读更多 →
资金流入流出预测:LSTM建模范式重构与业务对齐

资金流入流出预测:LSTM建模范式重构与业务对齐

1. 为什么“资金流入流出预测”不能直接套用教科书LSTM?我第一次接到某高校金融实验室的模拟项目X需求时,对方发来一句:“用LSTM做个baseline,跑通就行”。听起来简单——不就是序列建模嘛,PyTorch官网示例改两行就能出…

2026/10/14 11:37:47 阅读更多 →
基于PSO算法的双微网优化调度MATLAB实现

基于PSO算法的双微网优化调度MATLAB实现

1. 多微网优化调度模型概述 微电网作为分布式能源系统的重要实现形式,其优化调度一直是能源领域的研究热点。当多个微电网通过联络线相互连接时,就形成了多微网系统(Multi-Microgrid System)。这种架构能够实现能源的互补共享&…

2026/10/14 11:36:46 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →