Spaces:
Running
Running
# Copyright (c) ONNX Project Contributors | |
# SPDX-License-Identifier: Apache-2.0 | |
import numpy as np | |
import onnx | |
from onnx.backend.test.case.base import Base | |
from onnx.backend.test.case.model import expect | |
from onnx.defs import AI_ONNX_PREVIEW_TRAINING_DOMAIN, ONNX_DOMAIN | |
class Gradient(Base): | |
def export_gradient_scalar_add() -> None: | |
add_node = onnx.helper.make_node("Add", ["a", "b"], ["c"], name="my_add") | |
gradient_node = onnx.helper.make_node( | |
"Gradient", | |
["a", "b"], | |
["dc_da", "dc_db"], | |
name="my_gradient", | |
domain=AI_ONNX_PREVIEW_TRAINING_DOMAIN, | |
xs=["a", "b"], | |
y="c", | |
) | |
a = np.array(1.0).astype(np.float32) | |
b = np.array(2.0).astype(np.float32) | |
c = a + b | |
# dc / da = d(a+b) / da = 1 | |
dc_da = np.array(1).astype(np.float32) | |
# db / db = d(a+b) / db = 1 | |
dc_db = np.array(1).astype(np.float32) | |
graph = onnx.helper.make_graph( | |
nodes=[add_node, gradient_node], | |
name="GradientOfAdd", | |
inputs=[ | |
onnx.helper.make_tensor_value_info("a", onnx.TensorProto.FLOAT, []), | |
onnx.helper.make_tensor_value_info("b", onnx.TensorProto.FLOAT, []), | |
], | |
outputs=[ | |
onnx.helper.make_tensor_value_info("c", onnx.TensorProto.FLOAT, []), | |
onnx.helper.make_tensor_value_info("dc_da", onnx.TensorProto.FLOAT, []), | |
onnx.helper.make_tensor_value_info("dc_db", onnx.TensorProto.FLOAT, []), | |
], | |
) | |
opsets = [ | |
onnx.helper.make_operatorsetid(ONNX_DOMAIN, 12), | |
onnx.helper.make_operatorsetid(AI_ONNX_PREVIEW_TRAINING_DOMAIN, 1), | |
] | |
model = onnx.helper.make_model_gen_version( | |
graph, producer_name="backend-test", opset_imports=opsets | |
) | |
expect( | |
model, inputs=[a, b], outputs=[c, dc_da, dc_db], name="test_gradient_of_add" | |
) | |
def export_gradient_scalar_add_and_mul() -> None: | |
add_node = onnx.helper.make_node("Add", ["a", "b"], ["c"], name="my_add") | |
mul_node = onnx.helper.make_node("Mul", ["c", "a"], ["d"], name="my_mul") | |
gradient_node = onnx.helper.make_node( | |
"Gradient", | |
["a", "b"], | |
["dd_da", "dd_db"], | |
name="my_gradient", | |
domain=AI_ONNX_PREVIEW_TRAINING_DOMAIN, | |
xs=["a", "b"], | |
y="d", | |
) | |
a = np.array(1.0).astype(np.float32) | |
b = np.array(2.0).astype(np.float32) | |
c = a + b | |
# d = a * c = a * (a + b) | |
d = a * c | |
# dd / da = d(a*a+a*b) / da = 2 * a + b | |
dd_da = (2 * a + b).astype(np.float32) | |
# dd / db = d(a*a+a*b) / db = a | |
dd_db = a | |
graph = onnx.helper.make_graph( | |
nodes=[add_node, mul_node, gradient_node], | |
name="GradientOfTwoOperators", | |
inputs=[ | |
onnx.helper.make_tensor_value_info("a", onnx.TensorProto.FLOAT, []), | |
onnx.helper.make_tensor_value_info("b", onnx.TensorProto.FLOAT, []), | |
], | |
outputs=[ | |
onnx.helper.make_tensor_value_info("d", onnx.TensorProto.FLOAT, []), | |
onnx.helper.make_tensor_value_info("dd_da", onnx.TensorProto.FLOAT, []), | |
onnx.helper.make_tensor_value_info("dd_db", onnx.TensorProto.FLOAT, []), | |
], | |
) | |
opsets = [ | |
onnx.helper.make_operatorsetid(ONNX_DOMAIN, 12), | |
onnx.helper.make_operatorsetid(AI_ONNX_PREVIEW_TRAINING_DOMAIN, 1), | |
] | |
model = onnx.helper.make_model_gen_version( | |
graph, producer_name="backend-test", opset_imports=opsets | |
) | |
expect( | |
model, | |
inputs=[a, b], | |
outputs=[d, dd_da, dd_db], | |
name="test_gradient_of_add_and_mul", | |
) | |