算子详解 #

算子概述 #

ONNX 定义了一套标准算子集,涵盖深度学习中常用的各种操作。每个算子都有明确的输入、输出和属性定义。

算子分类 #

text
┌─────────────────────────────────────────────────────────────┐
│                    ONNX 算子分类                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  神经网络层 (Neural Network)                                │
│  ├── Conv - 卷积                                           │
│  ├── ConvTranspose - 转置卷积                              │
│  ├── MaxPool / AveragePool - 池化                          │
│  ├── BatchNormalization - 批归一化                         │
│  ├── Dropout - 随机失活                                    │
│  ├── Gemm - 通用矩阵乘法                                   │
│  └── InstanceNormalization - 实例归一化                    │
│                                                             │
│  激活函数 (Activation)                                      │
│  ├── Relu - ReLU                                          │
│  ├── Sigmoid - Sigmoid                                    │
│  ├── Tanh - Tanh                                          │
│  ├── LeakyRelu - Leaky ReLU                               │
│  ├── Softmax - Softmax                                    │
│  ├── PRelu - PReLU                                        │
│  ├── Elu - ELU                                            │
│  └── Selu - SELU                                          │
│                                                             │
│  数学运算 (Math)                                            │
│  ├── Add, Sub, Mul, Div - 四则运算                        │
│  ├── MatMul - 矩阵乘法                                    │
│  ├── Pow, Sqrt, Exp, Log - 指数对数                       │
│  ├── Abs, Neg, Sign - 符号运算                            │
│  ├── ReduceMean, ReduceSum, ReduceMax - 归约运算          │
│  └── Clip, Ceil, Floor - 数值处理                         │
│                                                             │
│  张量操作 (Tensor)                                          │
│  ├── Reshape - 形状变换                                    │
│  ├── Transpose - 转置                                      │
│  ├── Concat - 拼接                                        │
│  ├── Split - 分割                                         │
│  ├── Slice - 切片                                         │
│  ├── Gather - 收集                                        │
│  ├── Flatten - 展平                                       │
│  ├── Squeeze / Unsqueeze - 维度操作                       │
│  └── Pad - 填充                                           │
│                                                             │
│  控制流 (Control Flow)                                      │
│  ├── If - 条件分支                                        │
│  └── Loop - 循环                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

神经网络层算子 #

Conv(卷积) #

卷积是深度学习中最核心的算子之一。

text
┌─────────────────────────────────────────────────────────────┐
│                    Conv 算子详解                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输入:                                                     │
│  ├── X: 输入张量 [N, C_in, H, W]                           │
│  ├── W: 权重张量 [C_out, C_in/group, kH, kW]              │
│  └── B: 偏置张量 [C_out] (可选)                            │
│                                                             │
│  输出:                                                     │
│  └── Y: 输出张量 [N, C_out, H_out, W_out]                 │
│                                                             │
│  属性:                                                     │
│  ├── kernel_shape: 卷积核大小 [kH, kW]                     │
│  ├── strides: 步长 [sH, sW]                                │
│  ├── pads: 填充 [pH_begin, pW_begin, pH_end, pW_end]      │
│  ├── dilations: 膨胀率 [dH, dW]                            │
│  ├── group: 分组数                                         │
│  └── auto_pad: 自动填充模式                                │
│                                                             │
│  输出尺寸计算:                                             │
│  H_out = floor((H + pH_begin + pH_end - dH*(kH-1) - 1) / sH + 1) │
│  W_out = floor((W + pW_begin + pW_end - dW*(kW-1) - 1) / sW + 1) │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
from onnx import helper, TensorProto

conv_node = helper.make_node(
    "Conv",
    inputs=["X", "W", "B"],
    outputs=["Y"],
    kernel_shape=[3, 3],
    strides=[1, 1],
    pads=[1, 1, 1, 1],
    dilations=[1, 1],
    group=1
)

depthwise_conv = helper.make_node(
    "Conv",
    inputs=["X", "W"],
    outputs=["Y"],
    kernel_shape=[3, 3],
    strides=[1, 1],
    pads=[1, 1, 1, 1],
    group=64
)

MaxPool / AveragePool(池化) #

text
┌─────────────────────────────────────────────────────────────┐
│                    Pool 算子详解                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  MaxPool:                                                   │
│  ├── 输入: X [N, C, H, W]                                  │
│  ├── 输出: Y [N, C, H_out, W_out]                          │
│  └── 属性: kernel_shape, strides, pads                     │
│                                                             │
│  AveragePool:                                               │
│  ├── 输入: X [N, C, H, W]                                  │
│  ├── 输出: Y [N, C, H_out, W_out]                          │
│  └── 属性: kernel_shape, strides, pads, count_include_pad  │
│                                                             │
│  GlobalAveragePool:                                         │
│  ├── 输入: X [N, C, H, W]                                  │
│  └── 输出: Y [N, C, 1, 1]                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
maxpool_node = helper.make_node(
    "MaxPool",
    inputs=["X"],
    outputs=["Y"],
    kernel_shape=[2, 2],
    strides=[2, 2],
    pads=[0, 0, 0, 0]
)

avgpool_node = helper.make_node(
    "AveragePool",
    inputs=["X"],
    outputs=["Y"],
    kernel_shape=[2, 2],
    strides=[2, 2],
    pads=[0, 0, 0, 0]
)

global_avgpool = helper.make_node(
    "GlobalAveragePool",
    inputs=["X"],
    outputs=["Y"]
)

BatchNormalization(批归一化) #

text
┌─────────────────────────────────────────────────────────────┐
│                    BatchNormalization 算子                   │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输入:                                                     │
│  ├── X: 输入张量 [N, C, ...]                               │
│  ├── scale: 缩放参数 γ [C]                                 │
│  ├── B: 偏置参数 β [C]                                     │
│  ├── input_mean: 均值 μ [C]                                │
│  └── input_var: 方差 σ² [C]                                │
│                                                             │
│  输出:                                                     │
│  └── Y: 归一化后的张量                                     │
│                                                             │
│  计算公式:                                                 │
│  Y = scale * (X - mean) / sqrt(var + epsilon) + B         │
│                                                             │
│  属性:                                                     │
│  ├── epsilon: 防止除零的小数值                             │
│  └── momentum: 移动平均动量(训练时使用)                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
bn_node = helper.make_node(
    "BatchNormalization",
    inputs=["X", "scale", "B", "mean", "var"],
    outputs=["Y"],
    epsilon=1e-5,
    momentum=0.9
)

Gemm(通用矩阵乘法) #

text
┌─────────────────────────────────────────────────────────────┐
│                    Gemm 算子详解                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输入:                                                     │
│  ├── A: 矩阵 A                                             │
│  ├── B: 矩阵 B                                             │
│  └── C: 偏置矩阵 C (可选)                                  │
│                                                             │
│  输出:                                                     │
│  └── Y: 输出矩阵                                           │
│                                                             │
│  计算公式:                                                 │
│  Y = alpha * A' * B' + beta * C                            │
│  其中 A' = transA ? A^T : A                                │
│       B' = transB ? B^T : B                                │
│                                                             │
│  属性:                                                     │
│  ├── alpha: A*B 的缩放因子                                 │
│  ├── beta: C 的缩放因子                                    │
│  ├── transA: 是否转置 A                                    │
│  └── transB: 是否转置 B                                    │
│                                                             │
│  常用于全连接层:                                           │
│  Y = X @ W^T + B                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
fc_node = helper.make_node(
    "Gemm",
    inputs=["X", "W", "B"],
    outputs=["Y"],
    alpha=1.0,
    beta=1.0,
    transA=0,
    transB=1
)

激活函数算子 #

ReLU 系列 #

text
┌─────────────────────────────────────────────────────────────┐
│                    激活函数算子                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ReLU:                                                      │
│  Y = max(0, X)                                             │
│                                                             │
│  LeakyReLU:                                                 │
│  Y = X if X >= 0 else alpha * X                            │
│  属性: alpha (默认 0.01)                                    │
│                                                             │
│  PReLU:                                                     │
│  Y = X if X >= 0 else slope * X                            │
│  输入: X, slope (可学习参数)                                │
│                                                             │
│  ELU:                                                       │
│  Y = X if X >= 0 else alpha * (exp(X) - 1)                 │
│  属性: alpha (默认 1.0)                                     │
│                                                             │
│  SELU:                                                      │
│  Y = scale * (max(0, X) + min(0, alpha * (exp(X) - 1)))    │
│  默认: alpha=1.67326, scale=1.0507                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
relu_node = helper.make_node("Relu", inputs=["X"], outputs=["Y"])

leaky_relu = helper.make_node(
    "LeakyRelu",
    inputs=["X"],
    outputs=["Y"],
    alpha=0.01
)

prelu_node = helper.make_node(
    "PRelu",
    inputs=["X", "slope"],
    outputs=["Y"]
)

elu_node = helper.make_node(
    "Elu",
    inputs=["X"],
    outputs=["Y"],
    alpha=1.0
)

Sigmoid / Tanh / Softmax #

text
┌─────────────────────────────────────────────────────────────┐
│                    其他激活函数                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Sigmoid:                                                   │
│  Y = 1 / (1 + exp(-X))                                     │
│  输出范围: (0, 1)                                          │
│                                                             │
│  Tanh:                                                      │
│  Y = (exp(X) - exp(-X)) / (exp(X) + exp(-X))              │
│  输出范围: (-1, 1)                                         │
│                                                             │
│  Softmax:                                                   │
│  Y = exp(X) / sum(exp(X))                                  │
│  属性: axis (默认 -1, 最后一维)                            │
│  输出和为 1                                                 │
│                                                             │
│  Softplus:                                                  │
│  Y = log(1 + exp(X))                                       │
│                                                             │
│  Softsign:                                                  │
│  Y = X / (1 + |X|)                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
sigmoid_node = helper.make_node("Sigmoid", inputs=["X"], outputs=["Y"])

tanh_node = helper.make_node("Tanh", inputs=["X"], outputs=["Y"])

softmax_node = helper.make_node(
    "Softmax",
    inputs=["X"],
    outputs=["Y"],
    axis=-1
)

数学运算算子 #

四则运算 #

text
┌─────────────────────────────────────────────────────────────┐
│                    四则运算算子                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Add:    Y = A + B                                         │
│  Sub:    Y = A - B                                         │
│  Mul:    Y = A * B                                         │
│  Div:    Y = A / B                                         │
│                                                             │
│  支持广播机制:                                             │
│  [3, 4] + [4]      -> [3, 4]                               │
│  [3, 4] + [3, 1]   -> [3, 4]                               │
│  [3, 4] + [1, 4]   -> [3, 4]                               │
│                                                             │
│  属性:                                                     │
│  └── broadcast: 是否广播 (opset < 7)                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
add_node = helper.make_node("Add", inputs=["A", "B"], outputs=["Y"])

sub_node = helper.make_node("Sub", inputs=["A", "B"], outputs=["Y"])

mul_node = helper.make_node("Mul", inputs=["A", "B"], outputs=["Y"])

div_node = helper.make_node("Div", inputs=["A", "B"], outputs=["Y"])

矩阵运算 #

text
┌─────────────────────────────────────────────────────────────┐
│                    矩阵运算算子                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  MatMul:                                                    │
│  矩阵乘法 Y = A @ B                                        │
│  支持 N 维张量(最后两维做矩阵乘法)                        │
│                                                             │
│  Gemm:                                                      │
│  通用矩阵乘法 Y = alpha * A' @ B' + beta * C               │
│                                                             │
│  MatMulInteger:                                             │
│  整数矩阵乘法(用于量化)                                   │
│                                                             │
│  QLinearMatMul:                                             │
│  量化线性矩阵乘法                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
matmul_node = helper.make_node(
    "MatMul",
    inputs=["A", "B"],
    outputs=["Y"]
)

归约运算 #

text
┌─────────────────────────────────────────────────────────────┐
│                    归约运算算子                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ReduceMean:                                                │
│  沿指定轴计算均值                                           │
│  属性: axes, keepdims                                      │
│                                                             │
│  ReduceSum:                                                 │
│  沿指定轴求和                                               │
│                                                             │
│  ReduceMax / ReduceMin:                                     │
│  沿指定轴求最大/最小值                                      │
│                                                             │
│  ReduceProd:                                                │
│  沿指定轴求积                                               │
│                                                             │
│  ReduceL1 / ReduceL2:                                       │
│  沿指定轴计算 L1/L2 范数                                    │
│                                                             │
│  ReduceLogSum:                                              │
│  沿指定轴计算对数和                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
reduce_mean = helper.make_node(
    "ReduceMean",
    inputs=["X"],
    outputs=["Y"],
    axes=[2, 3],
    keepdims=True
)

reduce_sum = helper.make_node(
    "ReduceSum",
    inputs=["X", "axes"],
    outputs=["Y"],
    keepdims=False
)

张量操作算子 #

Reshape / Transpose #

text
┌─────────────────────────────────────────────────────────────┐
│                    形状操作算子                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Reshape:                                                   │
│  改变张量形状                                               │
│  输入: data, shape                                         │
│  shape 中可以使用 0 表示保持原维度大小                      │
│  shape 中可以使用 -1 表示自动推断                          │
│                                                             │
│  Transpose:                                                 │
│  转置张量维度                                               │
│  属性: perm (维度排列)                                      │
│  例: [0, 2, 3, 1] 将 [N,C,H,W] 变为 [N,H,W,C]              │
│                                                             │
│  Flatten:                                                   │
│  展平张量                                                   │
│  属性: axis (从哪个维度开始展平)                            │
│                                                             │
│  Squeeze:                                                   │
│  移除大小为 1 的维度                                        │
│                                                             │
│  Unsqueeze:                                                 │
│  插入大小为 1 的维度                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
reshape_node = helper.make_node(
    "Reshape",
    inputs=["data", "shape"],
    outputs=["reshaped"]
)

transpose_node = helper.make_node(
    "Transpose",
    inputs=["data"],
    outputs=["transposed"],
    perm=[0, 2, 3, 1]
)

flatten_node = helper.make_node(
    "Flatten",
    inputs=["data"],
    outputs=["flattened"],
    axis=1
)

squeeze_node = helper.make_node(
    "Squeeze",
    inputs=["data", "axes"],
    outputs=["squeezed"]
)

unsqueeze_node = helper.make_node(
    "Unsqueeze",
    inputs=["data", "axes"],
    outputs=["unsqueezed"]
)

Concat / Split / Slice #

text
┌─────────────────────────────────────────────────────────────┐
│                    分割合并算子                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Concat:                                                    │
│  沿指定轴拼接张量                                           │
│  属性: axis                                                │
│  输入: input1, input2, ...                                 │
│                                                             │
│  Split:                                                     │
│  沿指定轴分割张量                                           │
│  属性: axis, split (各部分大小)                             │
│                                                             │
│  Slice:                                                     │
│  切片张量                                                   │
│  输入: data, starts, ends, axes, steps                     │
│                                                             │
│  Gather:                                                    │
│  按索引收集元素                                             │
│  输入: data, indices                                       │
│  属性: axis                                                │
│                                                             │
│  ScatterND:                                                 │
│  按索引更新元素                                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
concat_node = helper.make_node(
    "Concat",
    inputs=["input1", "input2", "input3"],
    outputs=["output"],
    axis=1
)

split_node = helper.make_node(
    "Split",
    inputs=["input"],
    outputs=["output1", "output2"],
    axis=1,
    split=[2, 3]
)

slice_node = helper.make_node(
    "Slice",
    inputs=["data", "starts", "ends", "axes", "steps"],
    outputs=["output"]
)

gather_node = helper.make_node(
    "Gather",
    inputs=["data", "indices"],
    outputs=["output"],
    axis=0
)

控制流算子 #

If 条件分支 #

text
┌─────────────────────────────────────────────────────────────┐
│                    If 算子                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输入:                                                     │
│  └── cond: 布尔条件                                        │
│                                                             │
│  属性:                                                     │
│  ├── then_branch: 条件为真时执行的子图                     │
│  └── else_branch: 条件为假时执行的子图                     │
│                                                             │
│  输出:                                                     │
│  └── outputs: 子图的输出                                   │
│                                                             │
│  示例:                                                     │
│  if cond:                                                   │
│      Y = A + B                                             │
│  else:                                                      │
│      Y = A - B                                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘
python
from onnx import helper

then_graph = helper.make_graph(
    [helper.make_node("Add", inputs=["A", "B"], outputs=["Y"])],
    "then_branch",
    [],
    [helper.make_tensor_value_info("Y", TensorProto.FLOAT, [1])]
)

else_graph = helper.make_graph(
    [helper.make_node("Sub", inputs=["A", "B"], outputs=["Y"])],
    "else_branch",
    [],
    [helper.make_tensor_value_info("Y", TensorProto.FLOAT, [1])]
)

if_node = helper.make_node(
    "If",
    inputs=["cond"],
    outputs=["Y"],
    then_branch=then_graph,
    else_branch=else_graph
)

Loop 循环 #

text
┌─────────────────────────────────────────────────────────────┐
│                    Loop 算子                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输入:                                                     │
│  ├── M: 最大迭代次数(可选)                               │
│  ├── cond: 循环条件                                        │
│  └── v_initial: 初始状态变量                               │
│                                                             │
│  属性:                                                     │
│  └── body: 循环体子图                                      │
│                                                             │
│  输出:                                                     │
│  └── v_final_and_scan_outputs: 最终状态和扫描输出          │
│                                                             │
│  循环体子图:                                               │
│  输入: iteration, cond, v_current                          │
│  输出: cond, v_next, scan_outputs                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

查询算子信息 #

使用 Python API #

python
import onnx
from onnx import defs

all_schemas = defs.get_all_schemas()

conv_schemas = defs.get_all_schemas_with_history("Conv")

latest_conv = defs.get_schema("Conv")

print(f"算子名: {latest_conv.name}")
print(f"版本: {latest_conv.since_version}")
print(f"域: {latest_conv.domain}")
print(f"文档: {latest_conv.doc}")

for input in latest_conv.inputs:
    print(f"输入: {input.name}, 类型: {input.type_str}")

for output in latest_conv.outputs:
    print(f"输出: {output.name}, 类型: {output.type_str}")

for attr in latest_conv.attributes:
    print(f"属性: {attr.name}, 类型: {attr.type}")

列出所有算子 #

python
import onnx
from onnx import defs

all_ops = defs.get_all_operator_names()
print(f"共有 {len(all_ops)} 个算子")

for op in sorted(all_ops)[:20]:
    schema = defs.get_schema(op)
    print(f"{op}: since_version={schema.since_version}")

下一步 #

现在你已经了解了 ONNX 算子,接下来学习 模型转换,学习如何将各框架模型转换为 ONNX 格式!

最后更新:2026-04-04