Files
wehub-resource-sync 5cbd3f29e3
Fuzz / Run fuzz harnesses (${{ github.event_name == 'schedule' && 'nightly' || 'smoke' }}) (push) Has been cancelled
Create Releases / call-mac (push) Has been cancelled
Create Releases / call-linux (push) Has been cancelled
Create Releases / call-sdist (push) Has been cancelled
Create Releases / call-win (push) Has been cancelled
Create Releases / call-pyodide (push) Has been cancelled
Windows_No_Exception_CI / build (x64, 3.10) (push) Has been cancelled
Check URLs / build (push) Has been cancelled
Create Releases / Attest CI build artifacts (push) Has been cancelled
Create Releases / Check for Publish release build to pypi (push) Has been cancelled
Create Releases / Check for Publish preview build to test.pypi-weekly (push) Has been cancelled
Create Releases / Publish preview build to test.pypi-weekly (push) Has been cancelled
Create Releases / Check for Publish release build to test.pypi (rc-candidates) (push) Has been cancelled
Create Releases / Publish release build to test.pypi (push) Has been cancelled
Create Releases / Check for Publish preview build to pypi-weekly (push) Has been cancelled
Create Releases / Publish preview build to pypi-weekly (push) Has been cancelled
Create Releases / Publish release build to pypi (push) Has been cancelled
Create Releases / test source distribution (push) Has been cancelled
clang-tidy / clang-tidy (push) Has been cancelled
Lint / Validate SBOM (push) Has been cancelled
Lint / Enforce style (push) Has been cancelled
CI / Test windows-2022, 3.14, External, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test windows-latest, 3.10, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test windows-latest, 3.14, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test windows-latest, 3.14t, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14, Internal, debug=1, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14, External, debug=0, unity_build=1, onnx_ml=1, autogen=1 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14, External, debug=0, unity_build=0, onnx_ml=0, autogen=0 (push) Has been cancelled
CI / Test macos-latest, 3.10, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test macos-latest, 3.14, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test macos-latest, 3.14t, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14, External, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.10, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14t, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
Pixi CI / Install and lint (ubuntu-24.04-arm) (push) Has been cancelled
Pixi CI / Install and lint (windows-2022) (push) Has been cancelled
Pixi CI / Xcode generator build (push) Has been cancelled
Pixi CI / Install and test (macos-latest, default) (push) Has been cancelled
Pixi CI / Install and test (ubuntu-24.04-arm, default) (push) Has been cancelled
Pixi CI / Install and test (ubuntu-latest, default) (push) Has been cancelled
Pixi CI / Install and test (windows-2022, default) (push) Has been cancelled
Pixi CI / Install and test (macos-latest, oldies) (push) Has been cancelled
Pixi CI / Install and test (ubuntu-24.04-arm, oldies) (push) Has been cancelled
Pixi CI / Install and test (ubuntu-latest, oldies) (push) Has been cancelled
Pixi CI / Install and test (windows-2022, oldies) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Copilot Setup Steps / copilot-setup-steps (push) Has been cancelled
Generate and publish ONNX docs / build (push) Has been cancelled
Generate and publish ONNX docs / deploy (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:41:19 +08:00

500 lines
13 KiB
Python

# Copyright (c) ONNX Project Contributors
#
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
import numpy as np
import onnx
from onnx import TensorProto
from onnx.backend.test.case.base import Base
from onnx.backend.test.case.node import expect
from onnx.helper import make_tensor
class QuantizeLinear(Base):
@staticmethod
def export() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
)
x = np.array([0, 2, 3, 1000, -254, -1000]).astype(np.float32)
y_scale = np.float32(2)
y_zero_point = np.uint8(128)
y = np.array([128, 129, 130, 255, 1, 0]).astype(np.uint8)
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear",
)
@staticmethod
def export_axis() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
)
x = np.array(
[
[
[[-162, 10], [-100, 232], [-20, -50]],
[[-76, 0], [0, 252], [32, -44]],
[[245, -485], [-960, -270], [-375, -470]],
],
],
dtype=np.float32,
)
y_scale = np.array([2, 4, 5], dtype=np.float32)
y_zero_point = np.array([84, 24, 196], dtype=np.uint8)
y = (x / y_scale.reshape(1, 3, 1, 1) + y_zero_point.reshape(1, 3, 1, 1)).astype(
np.uint8
)
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_axis",
)
@staticmethod
def export_e4m3fn() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
)
x = np.array([0.0, 1.0, 2.0, 100000.0, 200.0]).astype(np.float32)
y_scale = np.float32(2)
y_zero_point = make_tensor("y_zero_point", TensorProto.FLOAT8E4M3FN, [1], [0])
y = make_tensor("y", TensorProto.FLOAT8E4M3FN, [5], [0, 0.5, 1, 448, 96])
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_e4m3fn",
)
@staticmethod
def export_e5m2() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
)
x = np.array([0.0, 1.0, 2.0, 100000.0, 200.0]).astype(np.float32)
y_scale = np.float32(2)
y_zero_point = make_tensor("y_zero_point", TensorProto.FLOAT8E5M2, [1], [0.0])
y = make_tensor("y", TensorProto.FLOAT8E5M2, [5], [0, 0.5, 1, 49152, 96])
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_e5m2",
)
@staticmethod
def export_uint16() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
)
x = np.array(
[
0.0,
-128.0,
3.0,
-3.0,
2.9,
-2.9,
3.1,
-3.1,
65536.0,
-65534.0,
70000.0,
-70000.0,
]
).astype(np.float32)
y_scale = np.float32(2.0)
y_zero_point = np.uint16(32767)
y = np.array(
[
32767,
32703,
32769,
32765,
32768,
32766,
32769,
32765,
65535,
0,
65535,
0,
]
).astype(np.uint16)
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_uint16",
)
@staticmethod
def export_int16() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
)
x = np.array(
[
0.0,
-514.0,
3.0,
-3.0,
2.9,
-2.9,
3.1,
-3.1,
65022.0,
-66046.0,
65023.0,
-66047.0,
65024.0,
-66048.0,
70000.0,
-70000.0,
]
).astype(np.float32)
y_scale = np.float32(2.0)
y_zero_point = np.int16(256)
y = np.array(
[
256,
-1,
258,
254,
257,
255,
258,
254,
32767,
-32767,
32767,
-32768,
32767,
-32768,
32767,
-32768,
]
).astype(np.int16)
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_int16",
)
@staticmethod
def export_uint4() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
axis=0,
)
x = np.array(
[
[0.0, 2.5, 4.8, 8.6],
[-30, -20, 6, 9],
[12, 15, 16, 40],
]
).astype(np.float32)
y_scale = np.asarray([2.0, 3.0, 4.0], dtype=np.float32)
y_zero_point = make_tensor(
"y_zero_point", TensorProto.UINT4, y_scale.shape, np.ones_like(y_scale)
)
y = make_tensor(
"y", TensorProto.UINT4, x.shape, [1, 2, 3, 5, 0, 0, 3, 4, 4, 5, 5, 11]
)
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_uint4",
)
@staticmethod
def export_int4() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
axis=0,
)
x = np.array(
[
[0.0, 2.5, 4.8, 8.6],
[-30, -20, 6, 9],
[12, 15, 16, 40],
]
).astype(np.float32)
y_scale = np.asarray([2.0, 3.0, 4.0], dtype=np.float32)
y_zero_point = make_tensor(
"y_zero_point", TensorProto.INT4, y_scale.shape, np.ones_like(y_scale)
)
y = make_tensor(
"y", TensorProto.INT4, x.shape, [1, 2, 3, 5, -8, -6, 3, 4, 4, 5, 5, 7]
)
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_int4",
)
@staticmethod
def export_uint2() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
axis=0,
)
x = np.array(
[
[0.0, 2.5, 4.8, 8.6],
[-2.0, -1.0, 1.0, 3.0],
[4.0, 5.0, 6.0, 7.0],
],
dtype=np.float32,
)
y_scale = np.asarray([2.0, 3.0, 4.0], dtype=np.float32)
y_zero_point = make_tensor(
"y_zero_point", TensorProto.UINT2, y_scale.shape, np.zeros_like(y_scale)
)
y = make_tensor(
"y", TensorProto.UINT2, x.shape, [0, 1, 2, 3, 0, 0, 0, 1, 1, 1, 2, 2]
)
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_uint2",
)
@staticmethod
def export_int2() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
axis=0,
)
x = np.array(
[
[0.0, 2.5, 4.8, 8.6],
[-4.0, -3.0, 1.0, 2.0],
[-0.0, -2.5, -4.8, -8.6],
],
dtype=np.float32,
)
y_scale = np.asarray([2.0, 3.0, 4.0], dtype=np.float32)
y_zero_point = make_tensor(
"y_zero_point", TensorProto.INT2, y_scale.shape, np.zeros_like(y_scale)
)
y = make_tensor(
"y", TensorProto.INT2, x.shape, [0, 1, 1, 1, -1, -1, 0, 1, 0, -1, -1, -2]
)
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_int2",
)
@staticmethod
def export_float4e2m1() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
axis=0,
)
x = np.array(
[
[0.0, 2.5, 4.8, 8.6],
[-30, -20, 6, 9],
[-0.0, -2.5, -4.8, -8.6],
]
).astype(np.float32)
y_scale = np.asarray([2.0, 3.0, 4.0], dtype=np.float32)
y_zero_point = make_tensor(
"y_zero_point",
TensorProto.FLOAT4E2M1,
y_scale.shape,
np.zeros_like(y_scale),
)
y = make_tensor(
"y",
TensorProto.FLOAT4E2M1,
x.shape,
[0, 1, 2, 4, -6, -6, 2, 3, 0, -0.5, -1, -2],
)
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_float4e2m1",
)
@staticmethod
def export_blocked_asymmetric() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale", "y_zero_point"],
outputs=["y"],
axis=1,
block_size=2,
)
x = np.array(
[
[6.0, 12.0, 50.0, 5.0],
[1.0, 8.0, 4.0, 5.0],
[0.0, 20.0, 10.0, 4.0],
],
dtype=np.float32,
)
y_scale = np.array(
[
[1.5, 2.5],
[3.0, 4.9],
[5.1, 6.9],
],
dtype=np.float32,
)
y_zero_point = np.array(
[
[0, 1],
[1, 0],
[2, 3],
],
dtype=np.uint8,
)
# x.shape = (3, 4)
# y_scale.shape = (3, 2)
assert y_scale.shape == y_zero_point.shape
block_axis = 1
# The block shape is [x.shape[i] // y_scale.shape[i] for i in range(len(x.shape))] = (1, 2)
assert all(
x.shape[i] == y_scale.shape[i]
for i in range(len(x.shape))
if i != block_axis
)
assert x.shape[block_axis] % y_scale.shape[block_axis] == 0
repeats = x.shape[block_axis] // y_scale.shape[block_axis]
# Create element-wise scale and zero point
y_scale_elementwise = np.repeat(y_scale, repeats=repeats, axis=block_axis)
y_zero_point_elementwise = np.repeat(
y_zero_point, repeats=repeats, axis=block_axis
)
y = np.rint(x / y_scale_elementwise + y_zero_point_elementwise).astype(np.uint8)
expect(
node,
inputs=[x, y_scale, y_zero_point],
outputs=[y],
name="test_quantizelinear_blocked_asymmetric",
)
@staticmethod
def export_blocked_symmetric() -> None:
node = onnx.helper.make_node(
"QuantizeLinear",
inputs=["x", "y_scale"],
outputs=["y"],
axis=1,
block_size=2,
output_dtype=TensorProto.INT16,
)
x = np.array(
[
[6.0, -8, -10, 5.0],
[1.0, 8.0, 4.0, 5.0],
[0.0, 20.0, 10.0, 4.0],
],
dtype=np.float32,
)
y_scale = np.array(
[
[1.5, 2.5],
[3.0, 4.9],
[5.1, 6.9],
],
dtype=np.float32,
)
# x.shape = (3, 4)
# y_scale.shape = (3, 2)
block_axis = 1
# The block shape is [x.shape[i] // y_scale.shape[i] for i in range(len(x.shape))] = (1, 2)
assert all(
x.shape[i] == y_scale.shape[i]
for i in range(len(x.shape))
if i != block_axis
)
assert x.shape[block_axis] % y_scale.shape[block_axis] == 0
repeats = x.shape[block_axis] // y_scale.shape[block_axis]
# Create element-wise scale and zero point
y_scale_elementwise = np.repeat(y_scale, repeats=repeats, axis=block_axis)
y_val = np.clip(
np.rint(x / y_scale_elementwise), a_min=-32768, a_max=32767
).astype(np.int16)
y = make_tensor(
"y",
TensorProto.INT16,
x.shape,
y_val,
)
expect(
node,
inputs=[x, y_scale],
outputs=[y],
name="test_quantizelinear_blocked_symmetric",
)