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

302 lines
10 KiB
Python

# Copyright (c) ONNX Project Contributors
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
import itertools
import numpy as np
from onnx.reference.op_run import OpRun
from onnx.reference.ops._op_common_indices import _get_index, _get_indices
def _get_pad_shape(
auto_pad: str,
input_spatial_shape: tuple[int],
kernel_spatial_shape: tuple[int],
strides_spatial: tuple[int],
output_spatial_shape: tuple[int],
) -> tuple[int]:
pad_shape = [0] * len(input_spatial_shape)
if auto_pad in ("SAME_UPPER", "SAME_LOWER"):
for i in range(len(input_spatial_shape)):
pad_shape[i] = (
(output_spatial_shape[i] - 1) * strides_spatial[i]
+ kernel_spatial_shape[i]
- input_spatial_shape[i]
)
elif auto_pad == "VALID":
pass
if len(pad_shape) == 0:
raise RuntimeError(
f"Unable to compute pad shape, auto_pad={auto_pad!r}, "
f"input_spatial_shape={input_spatial_shape!r}, "
f"kernel_spatial_shape={kernel_spatial_shape!r}, "
f"strides_spatial={strides_spatial!r}."
)
return tuple(pad_shape)
def _get_output_shape_no_ceil(
auto_pad: str,
input_spatial_shape: tuple[int],
kernel_spatial_shape: tuple[int],
strides_spatial: tuple[int],
) -> tuple[int]:
out_shape = [0] * len(input_spatial_shape)
if auto_pad in ("SAME_UPPER", "SAME_LOWER"):
for i in range(len(input_spatial_shape)):
out_shape[i] = int(
np.ceil(float(input_spatial_shape[i]) / float(strides_spatial[i]))
)
elif auto_pad == "VALID":
for i in range(len(input_spatial_shape)):
out_shape[i] = int(
np.ceil(
float(input_spatial_shape[i] - (kernel_spatial_shape[i] - 1))
/ float(strides_spatial[i])
)
)
return tuple(out_shape)
def _get_output_shape(
auto_pad: str,
input_spatial_shape: tuple[int],
kernel_spatial_shape: tuple[int],
strides_spatial: tuple[int],
pad_shape: tuple[int] | None = None,
ceil_mode: int | None = 0,
) -> tuple[int]:
if not ceil_mode:
out_shape = _get_output_shape_no_ceil(
auto_pad, input_spatial_shape, kernel_spatial_shape, strides_spatial
)
else:
round_fct = np.ceil if ceil_mode else np.floor
out_shape = [0] * len(input_spatial_shape)
if auto_pad in ("SAME_UPPER", "SAME_LOWER"):
for i in range(len(input_spatial_shape)):
out_shape[i] = int(
round_fct(float(input_spatial_shape[i]) / float(strides_spatial[i]))
)
elif auto_pad == "VALID":
if pad_shape is None:
raise ValueError( # pragma: no cogitver
"pad_shape cannot be None if auto_pad is "
"'VALID' and ceil_mode is 1."
)
for i in range(len(input_spatial_shape)):
out_shape[i] = int(
round_fct(
float(
input_spatial_shape[i]
+ pad_shape[i]
- kernel_spatial_shape[i]
)
/ float(strides_spatial[i])
+ 1
)
)
if len(out_shape) == 0:
raise RuntimeError(
f"Unable to compute output shape, auto_pad={auto_pad!r}, "
f"input_spatial_shape={input_spatial_shape!r}, "
f"kernel_spatial_shape={kernel_spatial_shape!r}, "
f"strides_spatial={strides_spatial!r}, ceil_mode={ceil_mode!r}."
)
if min(out_shape) <= 0:
raise RuntimeError(
f"output shape cannot be null or negative, out_shape={out_shape!r}, "
f"auto_pad={auto_pad!r}, input_spatial_shape={input_spatial_shape!r}, "
f"kernel_spatial_shape={kernel_spatial_shape!r}, "
f"strides_spatial={strides_spatial!r}, ceil_mode={ceil_mode!r}."
)
return tuple(out_shape)
def _pool(
padded: np.ndarray,
x_shape: tuple[int],
kernel_shape: tuple[int],
strides_shape: tuple[int],
out_shape: tuple[int],
pad_shape: tuple[int],
pooling_type: str,
count_include_pad: int | None = 0,
ceil_mode: int | None = 0,
indices: bool = False,
pads: np.ndarray | None = None,
) -> np.ndarray:
if pooling_type == "AVG":
fpool = np.average
elif pooling_type == "MAX":
fpool = np.max
else:
raise NotImplementedError(
f"Pooling type {pooling_type!r} does not support. Should be AVG, MAX."
)
spatial_size = len(x_shape) - 2
y = np.zeros([x_shape[0], x_shape[1], *list(out_shape)])
if indices:
z = np.full(y.shape, fill_value=-1, dtype=np.int64)
round_fct = np.ceil if ceil_mode else np.floor
def loop_range():
return [
range(
int(
round_fct(
float(x_shape[i + 2] + pad_shape[i] - kernel_shape[i])
/ float(strides_shape[i])
+ 1
)
)
)
for i in range(spatial_size)
]
for shape in itertools.product(range(x_shape[0]), range(x_shape[1]), *loop_range()):
window = padded[shape[0], shape[1]]
listi = [
range(
strides_shape[i] * shape[i + 2],
strides_shape[i] * shape[i + 2] + kernel_shape[i],
)
for i in range(spatial_size)
]
listi2 = list(itertools.product(*listi))
values = []
for i in listi2:
try:
values.append(window[i])
except IndexError: # noqa: PERF203
continue
window_vals = np.array(values)
if count_include_pad == 1 and pooling_type == "AVG":
y[shape] = fpool(window_vals)
else:
no_nan = window_vals[np.where(~np.isnan(window_vals))]
y[shape] = fpool(no_nan)
if indices:
try:
window_vals_min = np.nan_to_num(window_vals, nan=no_nan.min())
except TypeError:
# argument nan was introduced in numpy 1.17
window_vals_min = window_vals.copy()
window_vals_min[np.isnan(window_vals_min)] = no_nan.min()
arg = np.argmax(window_vals_min)
coordinates = _get_indices(arg, out_shape)
delta = shape[2:] - pads[:, 0]
coordinates += delta
new_arg = _get_index(coordinates, x_shape[2:])
z[shape] = new_arg
if indices:
return y.astype(padded.dtype), z
return y.astype(padded.dtype)
class CommonPool(OpRun):
def _run(
self,
pooling_type,
count_include_pad,
x,
auto_pad=None,
ceil_mode=None,
dilations=None,
kernel_shape=None,
pads=None,
storage_order=None, # noqa: ARG002
strides=None,
):
if pooling_type == "MAX" and dilations is None:
dilations = [1 for s in kernel_shape]
if pads is None:
pads = [0 for s in kernel_shape] * 2
if strides is None or len(strides) == 0:
strides = [1] * (len(x.shape) - 2)
kernel_shape = list(kernel_shape)
auto_pad = "VALID" if auto_pad == "NOTSET" else auto_pad
if pads is None or len(pads) == 0:
pad_shape = [0] * (len(x.shape) - 2)
x_shape = x.shape[2:]
padded = x
elif len(pads) == 4:
pad_top, pad_bottom, pad_left, pad_right = pads
pad_shape = [pad_top + pad_bottom, pad_left + pad_right]
x_shape = np.array(x.shape[2:]) + np.array(pad_shape)
const = np.nan if count_include_pad == 0 else 0
padded = np.pad(
x,
((0, 0), (0, 0), (pad_top, pad_bottom), (pad_left, pad_right)),
mode="constant",
constant_values=const,
)
else:
pad_shape = pads
x_shape = x.shape[2:]
padded = x
if auto_pad in ("SAME_LOWER", "SAME_UPPER"):
const = np.nan if count_include_pad == 0 else 0
out_shape = _get_output_shape(
auto_pad,
x_shape,
kernel_shape,
strides,
pad_shape,
ceil_mode,
)
pad_shape = _get_pad_shape(
auto_pad, x_shape, kernel_shape, strides, out_shape
)
if auto_pad == "SAME_LOWER":
pad_bottom = pad_shape[0] // 2
pad_top = pad_shape[0] - pad_bottom
pad_right = pad_shape[1] // 2
pad_left = pad_shape[1] - pad_right
else:
pad_top = pad_shape[0] // 2
pad_bottom = pad_shape[0] - pad_top
pad_left = pad_shape[1] // 2
pad_right = pad_shape[1] - pad_left
padded = np.pad(
padded,
((0, 0), (0, 0), (pad_top, pad_bottom), (pad_left, pad_right)),
mode="constant",
constant_values=const,
)
else:
out_shape = _get_output_shape(
auto_pad,
x_shape,
kernel_shape,
strides,
pad_shape,
ceil_mode,
)
n_dims = len(pads) // 2
new_pads = np.array([(pads[i], pads[i + n_dims]) for i in range(n_dims)])
res = _pool(
padded,
x.shape,
kernel_shape,
strides,
out_shape,
pad_shape,
pooling_type,
count_include_pad=count_include_pad,
ceil_mode=ceil_mode,
indices=len(self.output) > 1,
pads=new_pads,
)
if isinstance(res, tuple):
return res
return (res,)