当前位置: 首页 > news >正文

.pt vs .onnx vs .rknn

理解 PyTorch、ONNX、RKNN 三种格式的本质差异——从 pickle 到 protobuf 到 NPU 指令。


1. 写在前面

本文是神经网络各层详解的姊妹篇——那篇文章解释了 Conv、Pool、FC、BN 等各层做了什么,本文聚焦这些层的权重和结构以什么格式存储、如何跨框架流转、最终怎么在 NPU 上执行

我们沿用同一个例子:

输入: 28×28 灰度图
结构: Conv(1→8通道, 3×3核) → ReLU → MaxPool(2×2) → FC(→10类)
输出: 数字 0-9 的识别结果

2. 三种格式一句话概括

格式 本质 类比
.pt / .pth Python pickle + 浮点二进制 "字典 + 一堆 float 数组,结构在代码里"
.onnx protobuf 计算图 + 权重 "一张蓝图:算子、连接、超参全写着"
.rknn NPU 指令 + 量化权重 "编译好的二进制,只能跑不能读"

3. .pt 文件:Python 的序列化

3.1 文件结构(新版 PyTorch,zip 容器)

model.pt (ZIP)
├── archive/
│   ├── data.pkl     ← pickle: 对象结构描述
│   ├── data/0       ← conv.weight: 72 × 4 = 288 字节
│   ├── data/1       ← conv.bias:   8 × 4 = 32  字节
│   ├── data/2       ← fc.weight:   13520 × 4 = 54080 字节
│   └── data/3       ← fc.bias:     10 × 4 = 40 字节
└── version

3.2 Pickle 是什么

Pickle 是一个栈式虚拟机字节码,不是文本格式:

指令              栈(底→顶)
─────────────────────────────────
EMPTY_DICT       [ {} ]
MARK             [ {}, (mark) ]
'conv.weight'    [ {}, (mark), 'conv.weight' ]
<Tensor ref→0>   [ ..., Tensor→data/0 ]
'conv.bias'      [ ..., 'conv.bias', Tensor→data/1 ]
SETITEMS         [ {'conv.weight':Tensor, 'conv.bias':Tensor} ]
STOP             → 返回 dict

3.3 .pt 的能力边界

✅ 权重数值、张量形状
❌ stride / padding —— 不在文件里
❌ 后面是 ReLU 还是 Sigmoid —— 不在文件里
❌ 网络结构 —— 隐式在 Python 类代码里

本质:.pt 是一组数字 + 隐式公式。 没有 Python 源码,无法重建网络。


4. .onnx 文件:显式的计算蓝图

4.1 文件结构(protobuf 二进制)

ModelProto {ir_version: 8graph: GraphProto {node[0] { op_type: "Conv"input:  ["input", "conv.weight", "conv.bias"]output: ["conv_out"]attribute: { kernel_shape: [3,3]  strides: [1,1]  pads: [0,0,0,0] } }node[1] { op_type: "Relu"    input:"conv_out"     output:"relu_out" }node[2] { op_type: "MaxPool" input:"relu_out"     output:"pool_out"kernel_shape:[2,2]  strides:[2,2] }node[3] { op_type: "Gemm"    input:"pool_out_flat","fc.weight","fc.bias"output:"output" }initializer { name: "conv.weight"  dims: [8,1,3,3]  raw_data: <288 字节> }initializer { name: "fc.weight"    dims: [10,1352]  raw_data: <54080 字节> }}
}

4.2 .pt vs .onnx

.pt .onnx
格式 pickle + zip protobuf
包含权重
包含结构 ❌(在代码里) ✅(显式计算图)
stride/padding ✅ attribute
激活函数 ✅ 独立节点
跨框架

本质:.onnx 是一组数字 + 显式公式。 任何 ONNX 运行时都能执行。


5. .rknn 文件:编译后的 NPU 二进制

5.1 ONNX → RKNN

ONNX 图解析├── 算子融合: Conv+BN+ReLU → 一个操作├── 量化:      float32 → int8, 每个 tensor 附 scale + zero_point├── 内存规划:  输入 784B → conv 5408B → pool 1352B → fc 10B└── 生成 NPU 指令序列 → .rknn (不可读微码 + int8 权重)

5.2 NPU vs GPU

GPU (OpenCL/CUDA) NPU (RK3576)
算力 ~50-100 GFLOPS 6 TOPS (int8)
功耗 几瓦 < 1W
计算方式 im2col + GEMM 专用 MAC 阵列
精度 FP32/FP16 int8/int16
适用 图形渲染 推理专用

本质:.rknn 是编译产物,类似 C 编译出的 ELF。


6. 全流程总结

 ┌─────────┐      ┌──────────┐      ┌─────────┐      ┌──────────────┐│  .pt    │ ───→ │  .onnx   │ ───→ │ .rknn   │ ───→ │  RK3576 NPU  ││ pickle  │      │ protobuf │      │ NPU 指令 │      │  6 TOPS      │└─────────┘      └──────────┘      └─────────┘      └──────────────┘torch.save()     torch.             RKNN-            rknn_run()onnx.export()      Toolkit2.build()

7. 实操流程

# PC 端 (x86, conda rknn_toolkit2)
python -c "
import torch
from rknn.api import RKNNmodel = YourModel()
torch.onnx.export(model, dummy_input, 'model.onnx', opset_version=12)rknn = RKNN()
rknn.config(target_platform='rk3576', quantized_dtype='asymmetric_quantized-u8')
rknn.load_onnx('model.onnx')
rknn.build(do_quantization=True)
rknn.export_rknn('model.rknn')
"# RK3576 板端
python -c "
from rknnlite.api import RKNNLiterknn = RKNNLite()
rknn.load_rknn('model.rknn')
rknn.init_runtime(core_mask=0b11)while True:obs = get_observation()action = rknn.inference([obs])send_command(action)
"

附录:训练是怎么学的

A. 什么是"参数"

参数 = 训练中被修改的、存在 .pt 里的数值。

是参数 不是参数
Conv weight, bias stride, padding(超参,固定)
BN γ, β μ, σ²(训练累积的统计量)
ReLU 输出值(每次前向现场算)
FC weight, bias

B. CrossEntropy:衡量"猜得有多错"

网络输出: [0.1, 0.0, 0.1, 7.8, 0.2, 0.3, ...]  → 第 3 位最高,猜 "3"
正确答案: "5"① Softmax 把分数转概率
② 取正确答案(5)的概率: 0.0001
③ L = -log(0.0001) = 9.2概率越小 → loss 越大;概率=1 → loss=0

C. lr(学习率)

控制参数每步更新幅度的小正数(典型 0.001)。

W_new = W - lr × ∂L/∂Wlr 太大: 参数跳过头,震荡发散
lr 太小: 学得太慢

D. 链式法则:如何计算参数对错误的贡献

反向传播 = 从 L 出发,逐层往回算梯度。

前向: x ─→ Conv ─→ BN ─→ ReLU ─→ FC ─→ L反向: ∂L/∂x ← ∂L/∂Conv ← ∂L/∂BN ← ∂L/∂ReLU ← ∂L/∂FC ← ∂L/∂L=1

FC 层(前向 z = a·W + b):

∂L/∂W = ∂L/∂z × a           ← z 对 W 求导 = a
∂L/∂b = ∂L/∂z × 1
∂L/∂a = ∂L/∂z × W           ← 往前传CrossEntropy + Softmax 组合:∂L/∂z[i] = softmax(z)[i] - (i 是正确答案 ? 1 : 0)

ReLU:前向正 → 梯度原样传;前向负 → 截断为 0。

BN

∂L/∂γ = Σ ∂L/∂y × x̂
∂L/∂β = Σ ∂L/∂y × 1

Conv:每个滑动窗口对核权重贡献一份,多个窗口覆盖的输入像素收到多份梯度求和。

数值例子

前向 (FC 层):a=[2.0, 3.0],  W₅=[0.4, 0.6],  z₅=2.9softmax(z)₅ = 0.15,  L = 1.90反向:∂L/∂z₅ = 0.15 - 1 = -0.85∂L/∂W₅[0] = -0.85 × 2.0 = -1.70∂L/∂W₅[1] = -0.85 × 3.0 = -2.55∂L/∂b₅ = -0.85∂L/∂a[0] = -0.85 × 0.4 = -0.34    ← 往前传

全部机械化——每个算子有对偶的反向公式,L.backward() 全自动执行。

E. γ 和 β 如何"学习"

γ 和 β 跟 Conv 的 72 个权重没有本质区别——都通过反向传播更新:

前向: y = γ × x̂ + β
反向: ∂L/∂γ = Σ ∂L/∂y × x̂    ∂L/∂β = Σ ∂L/∂y × 1
更新: γ_new = γ - lr × ∂L/∂γ   β_new = β - lr × ∂L/∂β

直观:每个通道自己学到"这个特征应该多大、偏多少才方便下一层用"。γ 大的通道说明该特征对任务更重要。

http://www.jsqmd.com/news/1258319/

相关文章:

  • AI驱动检测报告自动化生成与智能审核系统解析
  • 2026年7月卧龙防爆电气/南阳防爆电气厂家推荐大全_南阳利特防爆电机有限公司 - 行业平台推荐
  • 解决Windows系统vcruntime140.dll丢失错误的完整指南
  • AI产品经理Agent落地实战指南
  • AI Agent中Token优化策略与成本控制实战
  • 如何突破60帧限制:艾尔登法环帧率解锁完全指南
  • Linux文件IO操作详解与性能优化实践
  • 基于YOLO实例分割的管道缺陷智能检测系统
  • 3分钟解锁网易云VIP音乐:ncmToMp3工具让你的音乐无处不在
  • Reflex 纯 Python 全栈无前端:不写一行代码打造数据可视化后台
  • 5分钟掌握AMD Ryzen处理器调试工具:从入门到精通的完整指南
  • MySQL语法错误解析与常见问题修复指南
  • AI 在 BI 前端中的应用:自然语言查询与智能图表推荐
  • Nginx在Ubuntu上的安装与配置指南
  • CollisionLoss 设计与实现原理说明
  • Docker部署Doris集群:详解FE/BE节点注册与网络配置避坑指南
  • 一套流程打通 Windows 与 Mac,OpenClaw 2.7.9 本地 AI 工具搭建全过程
  • 持续领跑工业 AI 赛道!蓝卓再登2026浙江未来独角兽TOP100
  • 提示词润色到底靠不靠谱?Nature审稿人实测5大模型对比数据,第4种方法让SCI接受率提升37%
  • 视频图神经网络:从原理到工程实践
  • 边缘AI测试:技术原理、挑战与实践指南
  • Logback 1.6.0 发布:移除弃用成员、升级依赖,适配性再提升
  • 神经形态计算:从忆阻器到SNN训练工程实践
  • PowerInfer:消费级显卡运行40B大模型的突破性方案
  • 连云港本地防水补漏精选TOP5推荐:正规漏水检测维修公司上门师傅推荐:厕所/棚顶/屋面/飘窗/阳台/地下室/厨房渗漏水精准测漏维修(2026最新) - 即刻修防水
  • Paperzz智能论文写作平台:从初稿到答辩的全流程解决方案
  • 从VHS到4K:一位央视修复组首席工程师的私藏工作流(含自研时序对齐算法,未公开发表)
  • 2026精选广东省佛山市南海区狮山镇电动车上牌服务团队哪家靠谱 - 装修教育财税推荐2026
  • Nvidia工具链构建多模态数据湖的AI工程实践
  • 知识蒸馏技术:原理、实现与工业应用