PyTorch Tensor与Numpy内存共享机制及转换接口详解
1. 为什么Tensor和Numpy的关系值得单独拎出来讲很多人学PyTorch的时候看到torch.Tensor和numpy.ndarray长得差不多用起来也差不多就觉得这俩是一回事顶多API名字不一样。我一开始也这么想直到有一次在数据预处理管道里混用两者踩了一个内存共享的坑才发现这里面有不少值得说清楚的东西。Tensor和Numpy的关系本质上不是“两个库各干各的”而是同一块内存的两种视角。PyTorch在设计之初就考虑到了与Numpy生态的互操作性所以Tensor和ndarray之间可以做到零拷贝转换——也就是说转换本身不复制数据只是换了一层“壳”。这个特性用好了能省内存、省时间用不好就会遇到“我明明没改这个变量它怎么变了”的诡异问题。这篇内容适合已经写过一些Numpy代码、刚开始接触PyTorch的读者也适合用了一段时间PyTorch但没仔细想过两者底层关系的人。我会从内存模型讲起把torch.from_numpy()、.numpy()、torch.tensor()、torch.as_tensor()这几个最容易混淆的接口掰开揉碎说清楚再补充实际项目中数据在Numpy和Tensor之间来回转换时的注意事项。读完你应该能做到看到一段混合使用Numpy和PyTorch的代码立刻判断出哪里会发生内存共享、哪里会复制、哪里可能出bug。2. 从内存布局看Tensor和ndarray的本质联系2.1 两者都是“数据指针元信息”的结构Numpy的ndarray和PyTorch的Tensor在底层设计上有惊人的相似性。一个ndarray对象并不直接“装”着数据它包含的是一个指向连续内存块的指针再加上描述这块内存如何解释的元信息数据类型dtype、形状shape、步长strides、偏移量offset。Tensor也是同样的结构——一个Storage对象持有实际数据Tensor本身则记录shape、stride、dtype以及在这个Storage上的偏移。这种设计带来的直接结果是多个Tensor可以共享同一个Storage但各自有不同的shape和stride。你在PyTorch里用.view()、.transpose()、切片操作很多时候并没有创建新数据只是创建了一个新的“视角”。Numpy里的.reshape()、.T、切片也是同样的逻辑。理解这一点之后torch.from_numpy()的行为就很好解释了它创建一个新的Tensor对象但这个Tensor的Storage直接指向原来ndarray的内存块。没有数据复制没有额外内存分配两个对象从此共享同一块内存。2.2 零拷贝转换的前提条件零拷贝不是无条件成立的。torch.from_numpy()要求输入的ndarray必须是C连续的即内存按行优先连续排列。如果你对一个Numpy数组做了转置或者某些切片操作得到的是一个非连续视图这时候torch.from_numpy()仍然能工作但PyTorch内部会怎么处理呢实测结果是torch.from_numpy()对非连续数组也能创建Tensor但这个Tensor会保留Numpy的stride信息在PyTorch里表现为一个“非连续Tensor”。大部分运算能正常跑但某些操作比如.view()会报错要求你先调用.contiguous()。这一点在后面讲踩坑的时候会展开。另一个前提是dtype的兼容性。Numpy支持的dtype比PyTorch多比如float128、complex256这些PyTorch并不支持。遇到不兼容的dtypetorch.from_numpy()会直接抛错。常见的float32、float64、int64、bool这些都没问题。2.3 共享内存带来的“联动效应”共享内存最直观的表现是改一个另一个也跟着变。看下面这段代码import numpy as np import torch arr np.array([1.0, 2.0, 3.0]) t torch.from_numpy(arr) arr[0] 100.0 print(t) # tensor([100., 2., 3.], dtypetorch.float64) t[1] 200.0 print(arr) # [100. 200. 3.]这种双向联动在有些场景下非常方便比如你用Numpy做数据加载和预处理然后直接转成Tensor送进模型不需要额外复制。但在另一些场景下就是灾难——比如你在某个函数里修改了Tensor的值结果发现调用方的Numpy数组也被改了如果这个数组还在别处被引用就会产生难以追踪的bug。我的经验是如果你不打算让两边联动就显式地做一次复制。torch.tensor(arr)会复制数据torch.from_numpy(arr).clone()也会复制。多花一点内存换来确定性大多数时候是值得的。3. 四个转换接口的选用逻辑与实测对比3.1 torch.from_numpy零拷贝但要求苛刻torch.from_numpy(ndarray)是最直接的Numpy转Tensor方式。它的特点很鲜明零拷贝、共享内存、要求输入是ndarray不能是list、dtype必须兼容。这个接口适合什么场景当你确定后续不会修改原Numpy数组或者你就是要两边联动的时候。比如在数据增强管道里你用Numpy做了一堆变换最后一步转成Tensor送进模型模型只读不写那用from_numpy完全没问题还省了一次复制的开销。但要注意一个细节torch.from_numpy()返回的Tensor和原ndarray共享内存如果原ndarray被垃圾回收了Tensor还能正常工作吗答案是能因为Tensor的Storage持有对那块内存的引用Python的引用计数机制会保证内存不会被提前释放。这一点可以放心。3.2 .numpy()Tensor转Numpy的零拷贝通道反过来把一个Tensor转成Numpy数组用.numpy()方法。同样地如果Tensor在CPU上且不是需要梯度的requires_gradFalse这个转换是零拷贝的两者共享内存。但如果Tensor在GPU上.numpy()会直接报错。你需要先.cpu()再.numpy()而.cpu()这一步会涉及数据从显存到内存的复制。如果Tensor的requires_gradTrue也不能直接.numpy()需要先.detach()。这两个限制在实际写代码时经常遇到尤其是调试阶段想看看中间结果的时候。# GPU上的Tensor转Numpy的正确姿势 t_gpu torch.randn(3, 3, devicecuda, requires_gradTrue) arr t_gpu.detach().cpu().numpy()顺序很重要先detach()断开计算图再cpu()搬到内存最后numpy()转格式。反过来先.cpu()再.detach()也行但先detach更符合逻辑因为计算图本来就在GPU上。3.3 torch.tensor总是复制的“安全牌”torch.tensor(data)是一个工厂函数它接受各种输入——list、tuple、ndarray都可以——然后总是创建新的内存。也就是说即使你传入一个ndarray它也会复制一份数据不和原数组共享内存。这个接口的好处是安全、通用。你不需要关心输入是不是连续、dtype是否兼容它会自动推断或按你指定的dtype转换也不用担心后续修改会互相影响。代价就是多一次内存分配和复制。什么时候用torch.tensor()当你需要一份独立的数据副本时。比如你从某个全局配置里读了一个Numpy数组要在函数内修改它但不想影响全局那就用torch.tensor()复制一份。或者当你传入的是Python list时也只能用torch.tensor()因为from_numpy不接受list。3.4 torch.as_tensor智能选择能共享就共享torch.as_tensor(data)的设计哲学是如果输入已经是Tensor直接返回或按需转换dtype/device如果输入是ndarray尽量零拷贝共享内存如果输入是list那就复制。这个接口在写通用函数时特别有用。比如你写一个工具函数参数可能是Numpy数组也可能是Tensor用as_tensor就能统一处理而且不会做不必要的复制。但正因为它的行为依赖于输入类型用的时候要清楚传入的是什么否则可能在不知不觉中引入了内存共享。下面这张表把四个接口的关键差异整理在一起接口输入类型是否复制共享内存典型场景torch.from_numpyndarray否是确定不需要独立副本.numpy()CPU Tensor否是把Tensor结果交给Numpy生态处理torch.tensor任意是否需要独立副本或输入是listtorch.as_tensor任意视情况视情况写通用工具函数4. 内存共享踩坑实录与排查思路4.1 一个真实的数据污染案例我之前写过一个图像预处理管道大致流程是用Numpy做归一化和裁剪然后转成Tensor送进模型。为了省内存转换那一步用了torch.from_numpy()。管道跑起来没问题但训练几个epoch之后发现loss异常波动排查了很久才定位到问题。原因出在数据增强环节。我的增强函数里有一个随机翻转操作实现方式是对Numpy数组做切片arr[::-1]然后返回。这个切片是原数组的一个视图不是副本。接着这个视图被torch.from_numpy()转成Tensor送进模型。模型本身不修改输入所以到这里都没问题。问题出在下一个epoch。数据加载器复用了同一块内存缓冲区为了减少分配开销新的数据被写入这个缓冲区时上一个epoch的Tensor还引用着这块内存导致历史数据被覆盖。而由于Tensor和Numpy共享内存这种覆盖是静默发生的没有任何报错。这个坑的根源是零拷贝转换让Tensor的生命周期和Numpy缓冲区的生命周期绑定了。如果Numpy缓冲区被复用Tensor看到的数据就会变。解决方案很简单——在转换时加一个.clone()或者用torch.tensor()代替from_numpy()。多一次复制换来确定性。4.2 非连续数组引发的隐蔽错误另一个常见的坑是非连续数组。看这个例子arr np.arange(12).reshape(3, 4) arr_t arr.T # 转置非连续 t torch.from_numpy(arr_t) print(t.is_contiguous()) # False # 下面这行会报错 try: t.view(-1) except RuntimeError as e: print(e) # view size is not compatible with input tensors size and stridetorch.from_numpy()对非连续数组不会报错但生成的Tensor是非连续的。大部分逐元素运算没问题但一旦用到.view()就会失败。这时候需要先.contiguous()而.contiguous()会触发一次复制把数据重新排列成连续布局。排查这类问题的思路是当你看到“view size is not compatible”这个报错时第一反应应该是检查Tensor是否连续。用t.is_contiguous()确认如果不是要么改用.reshape()它会自动处理非连续情况要么先.contiguous()再.view()。4.3 dtype不匹配的静默转换Numpy的默认浮点类型是float64而PyTorch的默认浮点类型是float32。当你用torch.from_numpy()转换一个float64数组时得到的Tensor也是float64。如果你直接把这个Tensor送进一个期望float32输入的模型PyTorch会报dtype不匹配的错误。更隐蔽的情况是用torch.tensor()。如果你传入一个Numpy数组但不指定dtypetorch.tensor()会保留原数组的dtype。所以torch.tensor(np.array([1.0, 2.0]))得到的是float64Tensor而不是float32。我的习惯是在数据管道的最后一步显式地做类型转换。比如t torch.as_tensor(arr, dtypetorch.float32)这样不管输入是什么dtype输出都是统一的float32。这个习惯帮我避免了很多因为dtype不一致导致的诡异报错。5. 实际项目中的数据流转策略5.1 什么时候该用Numpy什么时候该用Tensor在一个典型的深度学习项目里Numpy和Tensor各有各的生态位。Numpy在数据加载、预处理、可视化、与其它库如OpenCV、Pandas交互方面有优势Tensor在GPU加速、自动求导、模型运算方面不可替代。我的做法是数据加载和预处理阶段用Numpy进入模型前转成Tensor。这样做的理由是预处理阶段的操作大多是CPU密集型的Numpy的API更成熟、更灵活而模型运算需要GPU和自动求导必须用Tensor。转换点放在数据加载器的collate_fn或者__getitem__的末尾。转换的时候如果确定后续不会修改原数组用torch.from_numpy()如果不确定用torch.tensor()复制一份。在数据加载器这种多进程环境下我倾向于用torch.tensor()因为多进程的内存共享行为更复杂复制一份更省心。5.2 避免在训练循环中频繁转换有些代码会在训练循环里反复做Numpy和Tensor之间的转换比如每个batch都把Tensor转成Numpy做某种计算再转回Tensor。这种模式非常低效因为每次转换都可能涉及内存复制和设备间传输。更好的做法是如果某个计算用Tensor也能做就全程用Tensor不要来回转。PyTorch的算子覆盖已经很全面了大部分Numpy能做的Tensor都能做。如果确实需要Numpy的某个特定函数考虑把它放在数据预处理阶段而不是训练循环里。5.3 内存占用的权衡零拷贝转换省内存但省内存不总是第一优先级。在GPU显存充足的情况下多复制一份数据换来代码的确定性和可维护性通常是划算的。我见过一些项目为了追求极致的零拷贝代码里到处是共享内存的隐式依赖结果新人接手后改一个地方就出bug维护成本远高于省下来的那点内存。一个实用的判断标准是如果数据量不大比如几MB到几十MB直接复制如果数据量很大比如几百MB以上再考虑零拷贝。对于大多数图像和文本任务单个batch的数据量并不大复制的开销可以忽略。6. 几个容易被忽略的细节6.1 Tensor的requires_grad对转换的影响一个Tensor如果requires_gradTrue它就不能直接.numpy()。这个限制的原因是Numpy数组没有计算图的概念无法承载梯度信息。必须先.detach()断开计算图才能转成Numpy。但要注意.detach()返回的Tensor和原Tensor共享内存。也就是说如果你修改了detach后的Tensor原Tensor的值也会变。这个行为在大多数情况下没问题但如果你在调试时想“冻结”某个中间结果记得再.clone()一下。6.2 字节序和内存对齐Numpy支持指定字节序大端或小端而PyTorch的Tensor默认使用本机字节序。如果你从文件读取了一个大端字节序的Numpy数组直接torch.from_numpy()可能会得到错误的结果。这种情况在处理某些科学数据格式时会遇到。排查方法是检查arr.dtype.byteorder如果不是本机字节序或|不适用就需要先转换。Numpy提供了arr.astype(arr.dtype.newbyteorder())来做这个转换。6.3 共享内存与多线程PyTorch的Tensor和Numpy的ndarray在共享内存时如果多个线程同时读写需要自己加锁。Python的GIL对Numpy的某些操作会释放对PyTorch的C后端操作也会释放所以多线程环境下共享内存的读写不是自动安全的。在数据加载器使用多进程num_workers0时每个进程有独立的内存空间共享内存的行为和单进程不同。如果你在__getitem__里用了from_numpy返回的Tensor会被序列化传给主进程这时候实际上发生了一次复制。所以多进程场景下from_numpy的零拷贝优势并不存在用torch.tensor反而更直观。6.4 版本兼容性PyTorch和Numpy的版本更新都可能影响两者之间的转换行为。比如某些旧版本PyTorch对非连续数组的处理和新版本不同某些Numpy版本修改了默认的整数类型。在跨版本迁移代码时建议跑一遍转换相关的单元测试确认行为符合预期。我自己的习惯是在项目里固定Numpy和PyTorch的版本写进requirements.txt或environment.yml避免因为版本差异导致转换行为不一致。这个习惯在团队协作中尤其重要能省掉很多“在我机器上没问题”的扯皮。7. 写转换代码时我遵循的几条规则经过上面这些踩坑和经验积累我现在写涉及Numpy和Tensor转换的代码时会遵循几条简单的规则。第一条默认用torch.tensor()除非有明确的性能理由才用from_numpy()。复制一份数据带来的确定性比省那点内存重要得多。只有在数据量确实很大、且我完全掌控数据生命周期的时候才会用零拷贝。第二条转换时显式指定dtype。不管是torch.tensor()还是torch.as_tensor()都加上dtypetorch.float32或项目统一使用的类型。这样不依赖输入的dtype输出始终一致。第三条在函数边界做转换不在函数内部来回转。一个函数的输入和输出保持类型一致要么全是Numpy要么全是Tensor。混用会让调用方困惑也容易引入隐蔽的共享内存问题。第四条调试时用.clone()隔离。当我想检查某个中间结果但不希望影响后续计算时.clone()一下再操作。这个习惯帮我避免了很多“改了调试代码结果训练结果变了”的困惑。第五条写注释说明是否共享内存。在转换的那一行加一句注释比如# 零拷贝与原数组共享内存或# 复制独立内存。这个注释对未来的自己和新接手的同事都很有价值。这些规则看起来琐碎但每一条背后都有踩坑的教训。Tensor和Numpy的互操作是PyTorch入门阶段最容易“会用但不懂”的部分之一花点时间把内存模型和转换接口搞清楚后面写数据管道和调试模型时会顺畅很多。

相关新闻

Smart Install Maker实战:从项目配置到出包验证的安装包制作指南

Smart Install Maker实战:从项目配置到出包验证的安装包制作指南

简介:面向个人开发者与小企业的《安装程序制作软件SmartInstallMaker使用教程终稿》PDF,定位是讲清如何将应用程序快速封装为专业安装包,解决软件分发前“打包难、条件多、配置杂”的常见问题。内容按完整流程展开,从新建项目到生…

2026/10/12 8:38:16 阅读更多 →
无人驾驶MPC模型预测控制:从建模到代码落地实战

无人驾驶MPC模型预测控制:从建模到代码落地实战

简介:这份资料是北京理工大学「无人驾驶车辆模型预测控制」第二版配套程序代码,面向智能交通、自动驾驶方向的学习者与研究人员,用于理解并实践MPC在无人车路径规划、速度控制与避障中的落地细节。压缩包共349个文件,约1.52MB&…

2026/10/12 8:37:15 阅读更多 →
HUD光学仿真实战:Ansys多物理场破解重影与阳光烘烤难题

HUD光学仿真实战:Ansys多物理场破解重影与阳光烘烤难题

开车时在前挡风玻璃上直接看到车速、限速和转弯箭头,不用低头、不用重新对焦——这个常被叫作HUD的东西,如今已经从前几年的豪华配置,悄悄变成了十万级家用车也在卷的卖点。但只有真正做过HUD的光学、结构和热管理工程师才明白,这…

2026/10/12 8:37:15 阅读更多 →

最新新闻

四旋翼动力学建模与卡尔曼滤波状态估计:从原理到飞控实战

四旋翼动力学建模与卡尔曼滤波状态估计:从原理到飞控实战

这门课我前后刷了两遍,第一遍是在校期间跟着课程节奏走,第二遍是工作后做飞控相关项目时回头补的。两次学习的感受完全不同:第一次是被动接受知识点,第二次才真正理解了四旋翼为什么这么飞、控制器为什么这么设计。如果你正在学这…

2026/10/12 11:36:31 阅读更多 →
【SPIE出版、往届会后四个月检索】第二届计算机视觉和影像计算国际学术会议(CVIC 2026)

【SPIE出版、往届会后四个月检索】第二届计算机视觉和影像计算国际学术会议(CVIC 2026)

在当今快速发展的科技环境中,计算机视觉和影像计算作为计算机科学中的重要分支,正经历着深刻而快速的变革。随着深度学习算法的突破、硬件性能的提升,以及数据量的激增,这两个领域在自动驾驶、医疗影像、强化现实和遥感等诸多应用…

2026/10/12 11:36:31 阅读更多 →
开放式代码评审:四阶协同法与多触点实践指南

开放式代码评审:四阶协同法与多触点实践指南

1. “open-code-review”不是开源项目,而是一套可落地的代码评审实践方法论“open-code-review”这个词乍看像某个 GitHub 上的新仓库名,或是某款刚发布的开源工具——但实际翻遍主流代码托管平台、技术社区和工具索引库,都找不到一个叫open-…

2026/10/12 11:36:31 阅读更多 →
AI 隐藏“思维链”背后的工程真相:从 OpenAI 访谈看 Codex 与强化学习的驾驭工程实践

AI 隐藏“思维链”背后的工程真相:从 OpenAI 访谈看 Codex 与强化学习的驾驭工程实践

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

2026/10/12 11:36:31 阅读更多 →
MCP协议深度解析2026:构建可互操作的AI工具生态系统与TaoToken实践

MCP协议深度解析2026:构建可互操作的AI工具生态系统与TaoToken实践

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

2026/10/12 11:36:31 阅读更多 →
Qt四大内核机制:元对象、属性、对象树与信号槽深度解析

Qt四大内核机制:元对象、属性、对象树与信号槽深度解析

1. 这不是C的普通类库,而是Qt的“操作系统级”设计内核很多人刚接触Qt时,第一反应是:“不就是个带GUI的C框架吗?写个窗口、放几个按钮、连个信号槽,好像也没多难。”——这种理解在入门阶段够用,但一旦项目…

2026/10/12 11:35:30 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →