Files
AnyImage/tools/models/onnx_weights.py
nan 198fcbf55b
Some checks failed
Test / test (push) Has been cancelled
Initial public release
2026-09-19 21:31:36 +08:00

50 lines
2.0 KiB
Python

"""Compress stored ONNX weights without changing graph arithmetic."""
import numpy as np
from onnx import TensorProto, helper, numpy_helper
def compress_weights(model):
casts = []
for initializer in model.graph.initializer:
if initializer.data_type != TensorProto.FLOAT:
continue
name = initializer.name
values = numpy_helper.to_array(initializer)
if not np.isfinite(values).all() or np.max(np.abs(values), initial=0) > np.finfo(np.float16).max:
continue
array = values.astype(np.float16)
stored_name = name + "__fp16_storage"
initializer.CopyFrom(numpy_helper.from_array(array, stored_name))
casts.append(helper.make_node(
"Cast", [stored_name], [name], to=TensorProto.FLOAT,
name=stored_name + "_restore",
))
nodes = list(model.graph.node)
del model.graph.node[:]
model.graph.node.extend(casts + nodes)
def compress_exact_constants(model):
"""Compress only constant tensors that round-trip without any value change."""
nodes = []
for node in model.graph.node:
nodes.append(node)
if node.op_type != "Constant":
continue
attribute = next((item for item in node.attribute if item.name == "value"), None)
if attribute is None or attribute.t.data_type != TensorProto.FLOAT:
continue
values = numpy_helper.to_array(attribute.t)
if not np.isfinite(values).all() or np.max(np.abs(values), initial=0) > np.finfo(np.float16).max:
continue
stored = values.astype(np.float16)
if values.nbytes < 64 or not np.array_equal(values, stored.astype(np.float32)):
continue
name = node.output[0]
node.output[0] = name + "__fp16_constant"
attribute.t.CopyFrom(numpy_helper.from_array(stored))
nodes.append(helper.make_node("Cast", [node.output[0]], [name], to=TensorProto.FLOAT))
del model.graph.node[:]
model.graph.node.extend(nodes)