TVM教程-----Bring Your Own Codegen
Bring Your Own CodegenTVM 的 Bring Your Own CodegenBYOC框架允许你将模型的部分内容卸载到自定义后端——硬件加速器、推理库或你自己的 kernel——而其余部分仍由 TVM 编译。本教程分为两部分BYOC 如何工作—— 我们先用一个捆绑的、无需硬件的示例 NPU 后端讲解流程再用同一流程驱动真实的生产后端 NVIDIA TensorRT。两者都运行一个小型手写模型以便每一步都清晰可见两者之间唯一变化的是后端而这种对比正是本课要点。部署真实模型—— 随后将其投入实际使用把一个真实的 PyTorchnn.Module从 export 经 TensorRT 跑到 GPU 上。示例 NPU 是一个教学用桩stub其 runtime 会记录 NPU 会做出的调度决策内存层级、执行引擎、融合但不做真实计算因此输出 buffer 保持未初始化。所以在 NPU 相关小节我们只检查 shape不检查数值——它的职责是让每一步 BYOC 都可见没有任何隐藏。TensorRT 则用同一流程做真实计算因此我们会将其结果与参考结果交叉验证。前置条件示例 NPU 小节需要 TVM 以USE_EXAMPLE_NPU_CODEGENON和USE_EXAMPLE_NPU_RUNTIMEON构建TensorRT 小节需要USE_TENSORRT_CODEGENON、USE_TENSORRT_RUNTIMEON和USE_CUDAON外加 CUDA GPU 以及匹配的 TensorRT 安装来自 NVIDIA 的pip install tensorrt包或 TensorRT 压缩包最终部署小节还需要 PyTorch。当其后端不可用时各小节会优雅降级。BYOC 流程概览BYOC 通过四个步骤把自定义后端接入 TVM 的编译流水线注册 pattern—— 描述后端能处理哪些 Relax op 序列。划分图partition—— 将匹配到的算子归组为 composite function。运行 codegen—— 将每个 composite 降到后端表示本教程中两个后端都是 JSON graph。执行—— runtime 将每个 composite 派发到后端。步骤 1 和 2 是纯 Python可在任意环境运行步骤 3 和 4 需要将后端的 codegen 与 runtime 编入 TVM因此下文的 build-and-run 单元都做了可用性守卫。Step 1Import 后端以注册其 pattern导入后端模块会将其 pattern 注册到 TVM 的全局 registry。Pattern 注册与 C 构建无关——只有 codegen 和 runtime 需要把后端编进去——因此我们探测每个后端并据此守卫 build-and-run 单元。importosimporttempfileimportnumpyasnpimporttvmimporttvm.relax.backend.contrib.example_npufromtvmimportrelaxfromtvm.relax.backend.contrib.tensorrtimportpartition_for_tensorrtfromtvm.relax.backend.pattern_registryimportget_patterns_with_prefixfromtvm.relax.transformimportFuseOpsByPattern,MergeCompositeFunctions,RunCodegenfromtvm.scriptimportrelaxasR has_example_npu_codegentvm.get_global_func(relax.ext.example_npu,True)has_example_npu_runtimetvm.get_global_func(runtime.ExampleNPUJSONRuntimeCreate,True)has_example_npuhas_example_npu_codegenandhas_example_npu_runtime has_tensorrt_codegentvm.get_global_func(relax.ext.tensorrt,True)isnotNone_is_trt_runtime_enabledtvm.get_global_func(relax.is_tensorrt_runtime_enabled,True)has_tensorrt(has_tensorrt_codegenand_is_trt_runtime_enabledisnotNoneand_is_trt_runtime_enabled())has_cudatvm.cuda(0).existStep 2定义模型单个卷积后接 ReLU。该模型同时用于两个后端。tvm.script.ir_moduleclassConvReLU:R.functiondefmain(data:R.Tensor((1,3,32,32),float32),weight:R.Tensor((16,3,3,3),float32),)-R.Tensor((1,16,30,30),float32):withR.dataflow():convrelax.op.nn.conv2d(data,weight)outrelax.op.nn.relu(conv)R.output(out)returnoutStep 3为示例 NPU 做 PartitionFuseOpsByPattern将匹配已注册 pattern 的算子归组为 composite functionMergeCompositeFunctions再把绑定到同一后端的相邻 composite 合并为一次外部调用。有两个标志控制划分bind_constantsFalse让权重保持为函数参数从而由 host 管理参数。下文的 TensorRT 做相反选择它把权重绑定为常量因为会将其 bake 进 engine。annotate_codegenTrue用带后端名称标签的函数包装每个匹配到的 composite——RunCodegen依据该标签路由。后续的MergeCompositeFunctions在归组 composite 时也会附上该标签因此下文的partition_for_tensorrt可以不设该标志。示例 NPU 注册了一个融合的conv2d relupattern优先级高于独立的conv2dpattern因此这两个算子会折叠成单个example_npu.conv2d_relu_fusedcomposite——可在打印出的 module 中看到它。npu_patternsget_patterns_with_prefix(example_npu)npu_modFuseOpsByPattern(npu_patterns,bind_constantsFalse,annotate_codegenTrue)(ConvReLU)npu_modMergeCompositeFunctions()(npu_mod)print(After partitioning for the example NPU:)print(npu_mod)After partitioning for the example NPU: # from tvm.script import ir as I # from tvm.script import relax as R I.ir_module class Module: R.function def fused_relax_nn_conv2d_relax_nn_relu_example_npu_example_npu(data: R.Tensor((1, 3, 32, 32), dtypefloat32), weight: R.Tensor((16, 3, 3, 3), dtypefloat32)) - R.Tensor((1, 16, 30, 30), dtypefloat32): R.func_attr({Codegen: example_npu}) # from tvm.script import relax as R R.function def local_func(data_1: R.Tensor((1, 3, 32, 32), dtypefloat32), weight_1: R.Tensor((16, 3, 3, 3), dtypefloat32)) - R.Tensor((1, 16, 30, 30), dtypefloat32): R.func_attr({Composite: example_npu.conv2d_relu_fused}) conv: R.Tensor((1, 16, 30, 30), dtypefloat32) R.nn.conv2d(data_1, weight_1, strides[1, 1], padding[0, 0, 0, 0], dilation[1, 1], groups1, data_layoutNCHW, kernel_layoutOIHW, out_layoutNCHW, out_dtypeNone) gv: R.Tensor((1, 16, 30, 30), dtypefloat32) R.nn.relu(conv) return gv output: R.Tensor((1, 16, 30, 30), dtypefloat32) local_func(data, weight) return output R.function def main(data: R.Tensor((1, 3, 32, 32), dtypefloat32), weight: R.Tensor((16, 3, 3, 3), dtypefloat32)) - R.Tensor((1, 16, 30, 30), dtypefloat32): cls Module with R.dataflow(): gv: R.Tensor((1, 16, 30, 30), dtypefloat32) cls.fused_relax_nn_conv2d_relax_nn_relu_example_npu_example_npu(data, weight) R.output(gv) return gvStep 4在示例 NPU 上 Codegen、build 与运行RunCodegen调用每个被注解的 composite 的后端 codegen将其替换为后端 runtime module此处为 NPU 的 JSON graph随后relax.build编译剩余的 host 侧程序并链接所有内容。由于该 runtime 是一个不做任何计算的桩我们只对输出 shape 做断言——数值是未初始化的。np.random.seed(0)data_npnp.random.randn(1,3,32,32).astype(float32)weight_npnp.random.randn(16,3,3,3).astype(float32)ifhas_example_npu:npu_modRunCodegen()(npu_mod)withtvm.transform.PassContext(opt_level3):npu_execrelax.build(npu_mod,tvm.target.Target(llvm))npu_vmrelax.VirtualMachine(npu_exec,tvm.cpu())npu_outnpu_vm[main](tvm.runtime.tensor(data_np,tvm.cpu()),tvm.runtime.tensor(weight_np,tvm.cpu()))assertnpu_out.numpy().shape(1,16,30,30)print(Example NPU run completed. Output shape:,npu_out.numpy().shape)else:print(Example NPU backend unavailable; skipping its build and run.)Example NPU backend unavailable; skipping its build and run.同一流程打到真实后端TensorRT上面的 Step 1–4 就是全部机制。把它们对准真实后端时变化很少因此不再重复走一遍这里只说明对 NVIDIA TensorRT 有何不同一次调用完成 Partition。partition_for_tensorrt打包了你手写运行的FuseOpsByPatternMergeCompositeFunctions并使用 TensorRT 自己的 pattern 表。权重变为常量bind_constantsTrueTensorRT 会把它们 bake 进所构建的 engine因此在 partition 之前先绑定参数。真实数值。TensorRT 会真正计算因此我们为 CUDA 构建、在 GPU 上运行并与普通的 CPU 构建交叉验证——而不仅仅是 shape。下面的 build-and-run 单元仅在 TensorRT 与 CUDA 可用时执行。在仅 CPU 的文档构建中它们不会产生输出。trt_modrelax.transform.BindParams(main,{weight:weight_np})(ConvReLU)trt_modpartition_for_tensorrt(trt_mod)print(After partition_for_tensorrt:)print(trt_mod)After partition_for_tensorrt: # from tvm.script import ir as I # from tvm.script import relax as R I.ir_module class Module: R.function def fused_relax_nn_conv2d_relax_nn_relu_tensorrt(data: R.Tensor((1, 3, 32, 32), dtypefloat32)) - R.Tensor((1, 16, 30, 30), dtypefloat32): R.func_attr({Codegen: tensorrt}) # from tvm.script import relax as R R.function def gv(data_1: R.Tensor((1, 3, 32, 32), dtypefloat32)) - R.Tensor((1, 16, 30, 30), dtypefloat32): R.func_attr({Composite: tensorrt.nn.conv2d}) with R.dataflow(): gv_1: R.Tensor((1, 16, 30, 30), dtypefloat32) R.nn.conv2d(data_1, metadata[relax.expr.Constant][0], strides[1, 1], padding[0, 0, 0, 0], dilation[1, 1], groups1, data_layoutNCHW, kernel_layoutOIHW, out_layoutNCHW, out_dtypeNone) R.output(gv_1) return gv_1 lv: R.Tensor((1, 16, 30, 30), dtypefloat32) gv(data) # from tvm.script import relax as R R.function def gv1(lv_1: R.Tensor((1, 16, 30, 30), dtypefloat32)) - R.Tensor((1, 16, 30, 30), dtypefloat32): R.func_attr({Composite: tensorrt.nn.relu}) with R.dataflow(): gv_1: R.Tensor((1, 16, 30, 30), dtypefloat32) R.nn.relu(lv_1) R.output(gv_1) return gv_1 gv_1: R.Tensor((1, 16, 30, 30), dtypefloat32) gv1(lv) return gv_1 R.function def main(data: R.Tensor((1, 3, 32, 32), dtypefloat32)) - R.Tensor((1, 16, 30, 30), dtypefloat32): cls Module with R.dataflow(): gv: R.Tensor((1, 16, 30, 30), dtypefloat32) cls.fused_relax_nn_conv2d_relax_nn_relu_tensorrt(data) R.output(gv) return gv # Metadata omitted. Use show_metaTrue in script() method to show it.为 CUDA 构建在 GPU 上运行并与 CPU 参考结果比较。ifhas_tensorrtandhas_cuda:devtvm.cuda(0)withtvm.transform.PassContext(opt_level3):trt_execrelax.build(RunCodegen()(trt_mod),cuda)trt_outrelax.VirtualMachine(trt_exec,dev)[main](tvm.runtime.tensor(data_np,dev)).numpy()cpu_modrelax.transform.LegalizeOps()(relax.transform.BindParams(main,{weight:weight_np})(ConvReLU))cpu_execrelax.build(cpu_mod,llvm)cpu_outrelax.VirtualMachine(cpu_exec,tvm.cpu())[main](tvm.runtime.tensor(data_np,tvm.cpu())).numpy()np.testing.assert_allclose(trt_out,cpu_out,rtol1e-2,atol1e-2)print(TensorRT output shape:,trt_out.shape,- matches the CPU reference.)真实后端还会暴露教学桩没有的旋钮。通过relax.ext.tensorrt.options配置设置use_fp16可让 TensorRT 选用 FP16 kernel用少许精度换取速度流程的其余部分不变。其他选项由环境变量驱动TVM_TENSORRT_USE_INT8启用带 calibration 的 INT8TVM_TENSORRT_MAX_WORKSPACE_SIZE限制 build workspaceTVM_TENSORRT_CACHE_DIR将已构建的 engine 缓存到磁盘以便跨运行复用。ifhas_tensorrtandhas_cuda:fp16_modpartition_for_tensorrt(relax.transform.BindParams(main,{weight:weight_np})(ConvReLU))withtvm.transform.PassContext(opt_level3,config{relax.ext.tensorrt.options:{use_fp16:True}}):fp16_execrelax.build(RunCodegen()(fp16_mod),cuda)fp16_outrelax.VirtualMachine(fp16_exec,tvm.cuda(0))[main](tvm.runtime.tensor(data_np,tvm.cuda(0))).numpy()np.testing.assert_allclose(fp16_out,cpu_out,rtol5e-2,atol5e-2)print(TensorRT FP16 output shape:,fp16_out.shape,- matches within FP16 tolerance.)Example NPU vs TensorRT 一览同一套四步流程两个后端AspectExample NPU教学桩TensorRT真实后端Runtime记录决策不做计算构建并运行 nvinfer engineOutput未初始化检查 shape真实数值与 CPU 交叉验证Weightsbind_constantsFalsebind_constantsTruebake 进去Partition两步 Pass手写partition_for_tensorrt一次调用用 TensorRT 部署 PyTorch 模型上面全部使用手写IRModule以便每个 op 都可见。实践中你从训练好的模型出发。最后一节对真实的 PyTorchnn.Module端到端运行同一套partition_for_tensorrt流程export 它用 PyTorch frontend 导入 Relax权重以常量形式进入——正是 TensorRT bake 进 engine 所需的形式partition为 CUDA 构建并将 GPU 结果与 PyTorch 自身输出对照。除 frontend 导入外唯一差异是导入后的程序以 tuple 返回输出因此对单个结果张量取索引[0]partition-build-run 流程本身不变。本节额外需要 PyTorch。try:importtorchfromtorchimportnn has_torchTrueexceptImportError:has_torchFalseifhas_torchandhas_tensorrtandhas_cuda:fromtvm.relax.frontend.torchimportfrom_exported_programclassSmallConvNet(nn.Module):def__init__(self):super().__init__()self.conv1nn.Conv2d(3,8,3)self.conv2nn.Conv2d(8,16,3)self.poolnn.MaxPool2d(2)defforward(self,x):xtorch.relu(self.conv1(x))xself.pool(x)xtorch.relu(self.conv2(x))returnx torch_modelSmallConvNet().eval()example_inputtorch.randn(1,3,32,32)withtorch.no_grad():torch_reftorch_model(example_input).numpy()exportedtorch.export.export(torch_model,(example_input,))torch_modfrom_exported_program(exported)torch_modpartition_for_tensorrt(torch_mod)print(After importing and partitioning the PyTorch model:)print(torch_mod)torch_devtvm.cuda(0)withtvm.transform.PassContext(opt_level3):torch_execrelax.build(RunCodegen()(torch_mod),cuda)deployedrelax.VirtualMachine(torch_exec,torch_dev)[main](tvm.runtime.tensor(example_input.numpy(),torch_dev))[0].numpy()np.testing.assert_allclose(deployed,torch_ref,rtol1e-2,atol1e-2)print(Deployed PyTorch model on TensorRT; output,deployed.shape,matches PyTorch.)真实部署会构建一次并复用产物。将编译后的 module export 为共享库之后再加载运行——可在全新进程中进行无需 PyTorch也无需重新构建。ifhas_torchandhas_tensorrtandhas_cuda:withtempfile.TemporaryDirectory()astmpdir:lib_pathos.path.join(tmpdir,deployed_trt.so)torch_exec.export_library(lib_path)loadedtvm.runtime.load_module(lib_path)reranrelax.VirtualMachine(loaded,torch_dev)[main](tvm.runtime.tensor(example_input.numpy(),torch_dev))[0].numpy()np.testing.assert_allclose(reran,torch_ref,rtol1e-2,atol1e-2)print(Reloaded the exported library and reran; output,reran.shape,still matches.)真实部署注意事项算子覆盖与回退。TensorRT 只卸载其 pattern 表中的算子见python/tvm/relax/backend/contrib/tensorrt.py任何不支持的算子会留在 host 上。打印划分后的 module查找带Codegen: tensorrt的函数即可看到卸载了什么。动态 shape。Builder 会为动态的 leadingbatch维度设置 optimization profile因此该集成可以服务以 symbolic batch size export 的模型。Engine 构建成本。第一次构建 TensorRT engine 很慢不是卡死。设置TVM_TENSORRT_CACHE_DIR可将已构建的 engine 缓存到磁盘后续运行跳过重建。下一步要以示例 NPU 为起点构建你自己的后端用你的硬件 SDK 调用替换src/runtime/extra/contrib/example_npu/example_npu_runtime.cc中的桩 runtime。在patterns.py中扩展你的硬件支持的算子。若后端需要非 JSON 的序列化格式在src/relax/backend/contrib/下添加 C codegen。参照ExampleNPU.cmake在cmake/modules/contrib/下添加 CMake 模块。若要研究完整的真实后端实现参见 TensorRT 集成python/tvm/relax/backend/contrib/tensorrt.py中的 pattern 表与partition_for_tensorrtsrc/relax/backend/contrib/tensorrt/中的 codegen以及src/runtime/extra/contrib/tensorrt/中的 runtime。

相关新闻

Python办公自动化实战:基于python-docx与docxtpl的公文批量排版解决方案

Python办公自动化实战:基于python-docx与docxtpl的公文批量排版解决方案

1. 项目概述:为什么用Python处理公文排版?如果你在体制内单位、大型企业或者任何需要处理大量正式文档的部门工作过,一定对“公文排版”这四个字深有感触。那不仅仅是调调字体和字号,而是一套严谨到近乎苛刻的格式规范&#xff1a…

2026/7/31 1:30:00 阅读更多 →
2026岳阳黄金回收白银回收铂金回收市民首选无隐形扣费正规备案回收门店联系方式推荐

2026岳阳黄金回收白银回收铂金回收市民首选无隐形扣费正规备案回收门店联系方式推荐

岳阳黄金白银铂金回收2026实测榜单|公安工商双备案无损测金无折旧费门店 在岳阳这座历史悠久的城市,贵金属回收店铺遍地丛生,行业套路层出不穷,不少市民变现遭遇虚高报价、克扣损耗、未经同意熔金压价等问题。为帮助本地居民规避消…

2026/7/31 1:30:00 阅读更多 →
2026云浮黄金回收白银回收铂金回收市民首选无隐形扣费正规备案回收门店联系方式推荐

2026云浮黄金回收白银回收铂金回收市民首选无隐形扣费正规备案回收门店联系方式推荐

2026云浮黄金白银铂金回收实测榜单|公安工商双备案无损测金无折旧费门店 云浮黄金回收哪家靠谱|工商公安双备案中检认证实体门店 云浮本地贵金属回收店铺遍地丛生,行业套路层出不穷,不少市民变现遭遇虚高报价、克扣损耗、未经同意…

2026/7/31 1:30:00 阅读更多 →

最新新闻

PTA编程题解析:L1-019谁先倒的算法实现

PTA编程题解析:L1-019谁先倒的算法实现

1. 题目解析与背景说明"L1-019 谁先倒"是PTA(程序设计类实验辅助教学平台)中一道经典的编程练习题。这道题目主要考察编程初学者对条件判断和循环控制的理解与应用能力,属于典型的逻辑模拟类题目。这类题目在编程竞赛和算法练习中非…

2026/7/31 2:24:17 阅读更多 →
OpenAI 智能体入侵 Hugging Face,消息人士称 OpenAI 至少一周都没察觉

OpenAI 智能体入侵 Hugging Face,消息人士称 OpenAI 至少一周都没察觉

OpenAI 智能体入侵 Hugging Face,消息人士称 OpenAI 至少一周都没察觉 OpenAI 一款由 GPT-5.6 Sol 等驱动的网络安全智能体于 7 月 11 日闯入 Hugging Face 并持续攻击至 7 月 13 日。Hugging Face 于 7 月 16 日公开披露后,OpenAI 才意识到攻击者来自内…

2026/7/31 2:24:17 阅读更多 →
华为HCIP网络工程师认证—VLAN间路由

华为HCIP网络工程师认证—VLAN间路由

VLAN 划分之后,不同 VLAN 之间默认是隔离的,但实际工作中,财务部得给人事部发文件吧?研发部得访问服务器吧?这就涉及 VLAN 间路由——让不同 VLAN 能互相通信。本博客将用通俗易懂的方式给你总结明白。VLAN 间路由就是…

2026/7/31 2:24:17 阅读更多 →
Java编码utf-8搞崩心态?源码吃透才能不再踩坑

Java编码utf-8搞崩心态?源码吃透才能不再踩坑

Java高手速成:吃透源码手写组件定制开发的核心路径非得成为掌握相关底层原理跟工程化能力的 Java 高手, 就得经由源码深度解析、手写核心组件、业务定制开发这三个阶段进行系统化进阶。具体实现路径跟关键技术要点如下:一、对源码进行深度剖析, 来构建技术认知体系的…

2026/7/31 2:24:17 阅读更多 →
Java后端面试3年速通秘籍,轻松上岸

Java后端面试3年速通秘籍,轻松上岸

程序员圈内流传了整整3年之久的Java后端面试速通秘籍, 用不着去死记硬背那种几百页的八股文便能够精准地实现上岸目标, 就在今天全部给你毫无保留地抖落出来。 察觉到没, 当下寻觅Java后端岗位时, 背诵了长达半年的八股文, 然而一旦进入面试环节, 仍旧被问得无言以对, 说不出话…

2026/7/31 2:24:17 阅读更多 →
2026年算法工程师最新必问面试题十四:开放性与系统设计题

2026年算法工程师最新必问面试题十四:开放性与系统设计题

一、如何设计一个大模型智能客服的端到端评测体系?——离线 + 线上 + 用户采纳闭环 面试官期望:考察候选人对评测体系完整性的理解,能否从离线指标、线上指标到用户反馈形成闭环。 1. 离线评测(开发阶段) 维度 指标 说明 语义理解 意图识别准确率、实体抽取 F1 基于标注…

2026/7/31 2:23:16 阅读更多 →

日新闻

物理复制比逻辑复制好在哪?数据库复制原理详解

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:00:34 阅读更多 →
BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:00:34 阅读更多 →
有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:00:34 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/31 1:03:03 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻