import numpy as np
import onnx
from onnx import TensorProto, helper, numpy_helper
import os
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "..", "fixtures")
def create_external_data_model():
X = helper.make_tensor_value_info("X", TensorProto.FLOAT, [1, 4])
Y = helper.make_tensor_value_info("Y", TensorProto.FLOAT, [1, 4])
weight_data = np.array(
[
[1.0, 0.0, 0.0, 0.0],
[0.0, 2.0, 0.0, 0.0],
[0.0, 0.0, 3.0, 0.0],
[0.0, 0.0, 0.0, 4.0],
],
dtype=np.float32,
)
bias_data = np.array([0.1, 0.2, 0.3, 0.4], dtype=np.float32)
weight_tensor = numpy_helper.from_array(weight_data, name="weight")
bias_tensor = numpy_helper.from_array(bias_data, name="bias")
matmul_node = helper.make_node(
"MatMul", ["X", "weight"], ["matmul_out"], name="matmul"
)
add_node = helper.make_node("Add", ["matmul_out", "bias"], ["Y"], name="add")
graph = helper.make_graph(
[matmul_node, add_node],
"external_data_test",
[X],
[Y],
[weight_tensor, bias_tensor],
)
model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 17)])
model.ir_version = 8
output_path = os.path.join(FIXTURES_DIR, "external_data.onnx")
external_data_path = "external_data.bin"
onnx.save_model(
model,
output_path,
save_as_external_data=True,
all_tensors_to_one_file=True,
location=external_data_path,
size_threshold=0, )
print(f"Created: {output_path}")
print(f"External data: {os.path.join(FIXTURES_DIR, external_data_path)}")
loaded = onnx.load(output_path)
onnx.checker.check_model(loaded)
print("Model validation passed!")
def create_external_data_with_offset():
X = helper.make_tensor_value_info("X", TensorProto.FLOAT, [2, 3])
Y = helper.make_tensor_value_info("Y", TensorProto.FLOAT, [2, 3])
const_data = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=np.float32)
const_tensor = numpy_helper.from_array(const_data, name="const")
add_node = helper.make_node("Add", ["X", "const"], ["Y"], name="add")
graph = helper.make_graph(
[add_node],
"external_data_offset_test",
[X],
[Y],
[const_tensor],
)
model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 17)])
model.ir_version = 8
output_path = os.path.join(FIXTURES_DIR, "external_data_offset.onnx")
external_data_path = "external_data_offset.bin"
onnx.save_model(
model,
output_path,
save_as_external_data=True,
all_tensors_to_one_file=True,
location=external_data_path,
size_threshold=0,
)
print(f"Created: {output_path}")
def create_mixed_data_model():
X = helper.make_tensor_value_info("X", TensorProto.FLOAT, [1, 64])
Y = helper.make_tensor_value_info("Y", TensorProto.FLOAT, [1, 64])
weight_data = np.random.randn(64, 64).astype(np.float32)
weight_tensor = numpy_helper.from_array(weight_data, name="weight")
bias_data = np.zeros(64, dtype=np.float32)
bias_tensor = numpy_helper.from_array(bias_data, name="bias")
matmul_node = helper.make_node(
"MatMul", ["X", "weight"], ["matmul_out"], name="matmul"
)
add_node = helper.make_node("Add", ["matmul_out", "bias"], ["Y"], name="add")
graph = helper.make_graph(
[matmul_node, add_node],
"mixed_data_test",
[X],
[Y],
[weight_tensor, bias_tensor],
)
model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 17)])
model.ir_version = 8
output_path = os.path.join(FIXTURES_DIR, "mixed_data.onnx")
external_data_path = "mixed_data.bin"
onnx.save_model(
model,
output_path,
save_as_external_data=True,
all_tensors_to_one_file=True,
location=external_data_path,
size_threshold=1024, )
print(f"Created: {output_path}")
def create_multiple_external_files_model():
X = helper.make_tensor_value_info("X", TensorProto.FLOAT, [1, 4])
Y = helper.make_tensor_value_info("Y", TensorProto.FLOAT, [1, 4])
weight_data = np.array(
[
[1.0, 0.0, 0.0, 0.0],
[0.0, 2.0, 0.0, 0.0],
[0.0, 0.0, 3.0, 0.0],
[0.0, 0.0, 0.0, 4.0],
],
dtype=np.float32,
)
bias_data = np.array([0.5, 0.5, 0.5, 0.5], dtype=np.float32)
weight_tensor = numpy_helper.from_array(weight_data, name="weight")
bias_tensor = numpy_helper.from_array(bias_data, name="bias")
matmul_node = helper.make_node(
"MatMul", ["X", "weight"], ["matmul_out"], name="matmul"
)
add_node = helper.make_node("Add", ["matmul_out", "bias"], ["Y"], name="add")
graph = helper.make_graph(
[matmul_node, add_node],
"multi_external_files_test",
[X],
[Y],
[weight_tensor, bias_tensor],
)
model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 17)])
model.ir_version = 8
output_path = os.path.join(FIXTURES_DIR, "multi_external_files.onnx")
weight_file = os.path.join(FIXTURES_DIR, "multi_external_weights.bin")
with open(weight_file, "wb") as f:
f.write(weight_data.tobytes())
bias_file = os.path.join(FIXTURES_DIR, "multi_external_bias.bin")
with open(bias_file, "wb") as f:
f.write(bias_data.tobytes())
for tensor in model.graph.initializer:
tensor.ClearField("raw_data")
tensor.ClearField("float_data")
tensor.data_location = TensorProto.EXTERNAL
del tensor.external_data[:]
if tensor.name == "weight":
tensor.external_data.append(
onnx.StringStringEntryProto(
key="location", value="multi_external_weights.bin"
)
)
tensor.external_data.append(
onnx.StringStringEntryProto(key="offset", value="0")
)
tensor.external_data.append(
onnx.StringStringEntryProto(key="length", value=str(weight_data.nbytes))
)
elif tensor.name == "bias":
tensor.external_data.append(
onnx.StringStringEntryProto(
key="location", value="multi_external_bias.bin"
)
)
tensor.external_data.append(
onnx.StringStringEntryProto(key="offset", value="0")
)
tensor.external_data.append(
onnx.StringStringEntryProto(key="length", value=str(bias_data.nbytes))
)
with open(output_path, "wb") as f:
f.write(model.SerializeToString())
print(f"Created: {output_path}")
print(f"External data files:")
print(f" - {weight_file}")
print(f" - {bias_file}")
with open(output_path, "rb") as f:
loaded = onnx.ModelProto()
loaded.ParseFromString(f.read())
for tensor in loaded.graph.initializer:
loc = next((e.value for e in tensor.external_data if e.key == "location"), None)
print(f" Tensor '{tensor.name}' -> {loc}")
if __name__ == "__main__":
os.makedirs(FIXTURES_DIR, exist_ok=True)
print("Generating external data test models...\n")
create_external_data_model()
print()
create_external_data_with_offset()
print()
create_mixed_data_model()
print()
create_multiple_external_files_model()
print()
print("Done!")