blob: 0d456ceb3873d9131e50d77441b1c3d50ce27100 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import tvm.testing
from tvm import relax
from tvm.ir.base import assert_structural_equal
from tvm.script import relax as R, ir as I
@I.ir_module
class Module:
@R.function
def forward(
x: R.Tensor((2, 4), "float32"),
w: R.Tensor((4, 4), "float32"),
b: R.Tensor((2, 4), "float32"),
) -> R.Tensor((2, 4), "float32"):
with R.dataflow():
lv: R.Tensor((2, 4), "float32") = R.matmul(x, w)
out: R.Tensor((2, 4), "float32") = R.add(lv, b)
R.output(out)
return out
def test_l1_loss():
N = 3
C = 5
predictions = relax.TensorStructInfo((N, C), "float32")
targets = relax.TensorStructInfo((N, C), "float32")
l1_loss = relax.training.loss.L1Loss()
@R.function
def expected(
predictions: R.Tensor((3, 5), "float32"), targets: R.Tensor((3, 5), "float32")
) -> R.Tensor((), "float32"):
R.func_attr({"global_symbol": "l1_loss"})
with R.dataflow():
lv: R.Tensor((3, 5), "float32") = R.subtract(predictions, targets)
lv1: R.Tensor((3, 5), "float32") = R.abs(lv)
gv: R.Tensor((), "float32") = R.mean(lv1, axis=None, keepdims=False)
R.output(gv)
return gv
assert_structural_equal(l1_loss(predictions, targets), expected)
def test_l1_loss_append():
s = Module["forward"].ret_struct_info
l1_loss = relax.training.loss.L1Loss(reduction="sum")
After = relax.training.AppendLoss("forward", l1_loss(s, s), l1_loss.num_backbone_outputs)(
Module
)
@R.function
def expected(
x: R.Tensor((2, 4), "float32"),
w: R.Tensor((4, 4), "float32"),
b: R.Tensor((2, 4), "float32"),
targets: R.Tensor((2, 4), "float32"),
) -> R.Tensor((), "float32"):
R.func_attr({"global_symbol": "forward_loss"})
with R.dataflow():
lv: R.Tensor((2, 4), "float32") = R.matmul(x, w, out_dtype="")
out: R.Tensor((2, 4), "float32") = R.add(lv, b)
lv1: R.Tensor((2, 4), "float32") = R.subtract(out, targets)
lv11: R.Tensor((2, 4), "float32") = R.abs(lv1)
gv: R.Tensor((), "float32") = R.sum(lv11, axis=None, keepdims=False)
R.output(gv)
return gv
assert_structural_equal(After["forward_loss"], expected)
def test_mse_loss():
N = 3
C = 5
predictions = relax.TensorStructInfo((N, C), "float32")
targets = relax.TensorStructInfo((N, C), "float32")
mse_loss = relax.training.loss.MSELoss()
@R.function
def expected(
predictions: R.Tensor((3, 5), "float32"), targets: R.Tensor((3, 5), "float32")
) -> R.Tensor((), "float32"):
R.func_attr({"global_symbol": "mse_loss"})
with R.dataflow():
lv: R.Tensor((3, 5), "float32") = R.subtract(predictions, targets)
lv1: R.Tensor((3, 5), "float32") = R.multiply(lv, lv)
gv: R.Tensor((), "float32") = R.mean(lv1, axis=None, keepdims=False)
R.output(gv)
return gv
assert_structural_equal(mse_loss(predictions, targets), expected)
def test_mse_loss_append():
s = Module["forward"].ret_struct_info
mse_loss = relax.training.loss.MSELoss(reduction="sum")
After = relax.training.AppendLoss("forward", mse_loss(s, s), mse_loss.num_backbone_outputs)(
Module
)
@R.function
def expected(
x: R.Tensor((2, 4), "float32"),
w: R.Tensor((4, 4), "float32"),
b: R.Tensor((2, 4), "float32"),
targets: R.Tensor((2, 4), "float32"),
) -> R.Tensor((), "float32"):
R.func_attr({"global_symbol": "forward_loss"})
with R.dataflow():
lv: R.Tensor((2, 4), "float32") = R.matmul(x, w, out_dtype="")
out: R.Tensor((2, 4), "float32") = R.add(lv, b)
lv1: R.Tensor((2, 4), "float32") = R.subtract(out, targets)
lv11: R.Tensor((2, 4), "float32") = R.multiply(lv1, lv1)
gv: R.Tensor((), "float32") = R.sum(lv11, axis=None, keepdims=False)
R.output(gv)
return gv
assert_structural_equal(After["forward_loss"], expected)
def test_cross_entropy_loss():
N = 3
C = 5
predictions = relax.TensorStructInfo((N, C), "float32")
targets = relax.TensorStructInfo((N,), "int64")
weights = relax.TensorStructInfo((C,), "float32")
cross_entropy_loss = relax.training.loss.CrossEntropyLoss(reduction="sum", ignore_index=1)
@R.function
def expected(
predictions: R.Tensor((3, 5), "float32"),
targets: R.Tensor((3,), "int64"),
weights: R.Tensor((5,), "float32"),
) -> R.Tensor((), "float32"):
R.func_attr({"global_symbol": "cross_entropy_loss"})
with R.dataflow():
lv: R.Tensor((3, 5), "float32") = R.nn.log_softmax(predictions, axis=-1)
gv: R.Tensor((), "float32") = R.nn.nll_loss(
lv, targets, weights, reduction="sum", ignore_index=1
)
R.output(gv)
return gv
assert_structural_equal(cross_entropy_loss(predictions, targets, weights), expected)
def test_cross_entropy_loss_without_weights():
N = 3
C = 5
predictions = relax.TensorStructInfo((N, C), "float32")
targets = relax.TensorStructInfo((N,), "int64")
cross_entropy_loss = relax.training.loss.CrossEntropyLoss()
@R.function
def expected(
predictions: R.Tensor((3, 5), "float32"), targets: R.Tensor((3,), "int64")
) -> R.Tensor((), "float32"):
R.func_attr({"global_symbol": "cross_entropy_loss"})
with R.dataflow():
lv: R.Tensor((3, 5), "float32") = R.nn.log_softmax(predictions, axis=-1)
gv: R.Tensor((), "float32") = R.nn.nll_loss(
lv, targets, reduction="mean", ignore_index=-100
)
R.output(gv)
return gv
assert_structural_equal(cross_entropy_loss(predictions, targets), expected)
def test_cross_entropy_loss_append():
s = Module["forward"].ret_struct_info
N = s.shape[0]
C = s.shape[1]
targets = relax.TensorStructInfo((N,), "int64")
weights = relax.TensorStructInfo((C,), "float32")
cross_entropy_loss = relax.training.loss.CrossEntropyLoss(reduction="sum", ignore_index=1)
After = relax.training.AppendLoss(
"forward", cross_entropy_loss(s, targets, weights), cross_entropy_loss.num_backbone_outputs
)(Module)
@R.function
def expected(
x: R.Tensor((2, 4), "float32"),
w: R.Tensor((4, 4), "float32"),
b: R.Tensor((2, 4), "float32"),
targets: R.Tensor((2,), "int64"),
weights: R.Tensor((4,), "float32"),
) -> R.Tensor((), "float32"):
R.func_attr({"global_symbol": "forward_loss"})
with R.dataflow():
lv: R.Tensor((2, 4), "float32") = R.matmul(x, w, out_dtype="")
out: R.Tensor((2, 4), "float32") = R.add(lv, b)
lv1: R.Tensor((2, 4), "float32") = R.nn.log_softmax(out, axis=-1)
gv: R.Tensor((), "float32") = R.nn.nll_loss(
lv1, targets, weights, reduction="sum", ignore_index=1
)
R.output(gv)
return gv
assert_structural_equal(After["forward_loss"], expected)
def test_categorical_cross_entropy_loss():
N = 3
C = 5
predictions = relax.TensorStructInfo((N, C), "float32")
targets = relax.TensorStructInfo((N, C), "int64")
weights = relax.TensorStructInfo((C,), "float32")
categorical_cross_entropy_loss = relax.training.loss.CategoricalCrossEntropyLoss(
reduction="sum"
)
@R.function
def expected(
predictions: R.Tensor((3, 5), "float32"),
targets: R.Tensor((3, 5), "int64"),
weights: R.Tensor((5,), "float32"),
) -> R.Tensor((), "float32"):
R.func_attr({"global_symbol": "categorical_cross_entropy_loss"})
with R.dataflow():
lv: R.Tensor((3, 5), "float32") = R.nn.log_softmax(predictions, axis=-1)
lv: R.Tensor((), "float32") = -lv * targets.astype("float32")
gv: R.Tensor((), "float32") = R.sum(lv * weights)
R.output(gv)
return gv
assert_structural_equal(categorical_cross_entropy_loss(predictions, targets, weights), expected)
def test_categorical_cross_entropy_loss_without_weights():
N = 3
C = 5
predictions = relax.TensorStructInfo((N, C), "float32")
targets = relax.TensorStructInfo((N, C), "int64")
categorical_cross_entropy_loss = relax.training.loss.CategoricalCrossEntropyLoss()
@R.function
def expected(
predictions: R.Tensor((3, 5), "float32"), targets: R.Tensor((3, 5), "int64")
) -> R.Tensor((), "float32"):
R.func_attr({"global_symbol": "categorical_cross_entropy_loss"})
with R.dataflow():
lv: R.Tensor((3, 5), "float32") = R.nn.log_softmax(predictions, axis=-1)
gv: R.Tensor((), "float32") = R.mean(-lv * targets.astype("float32"))
R.output(gv)
return gv
assert_structural_equal(categorical_cross_entropy_loss(predictions, targets), expected)
def test_categorical_cross_entropy_loss_with_ignore_index():
N = 3
C = 5
predictions = relax.TensorStructInfo((N, C), "float32")
targets = relax.TensorStructInfo((N, C), "int64")
weights = relax.TensorStructInfo((C,), "float32")
categorical_cross_entropy_loss = relax.training.loss.CategoricalCrossEntropyLoss(
reduction="sum", ignore_index=1
)
@R.function
def expected(
predictions: R.Tensor((3, 5), "float32"),
targets: R.Tensor((3, 5), "int64"),
weights: R.Tensor((5,), "float32"),
) -> R.Tensor((), "float32"):
R.func_attr({"global_symbol": "categorical_cross_entropy_loss"})
with R.dataflow():
lv: R.Tensor((3, 5), "float32") = R.nn.log_softmax(predictions, axis=-1)
targets = relax.op.reshape(
relax.op.argmax(targets, axis=1), shape=(targets.struct_info.shape[0],)
)
gv: R.Tensor((), "float32") = R.nn.nll_loss(
lv, targets, weights, reduction="sum", ignore_index=1
)
R.output(gv)
return gv
assert_structural_equal(categorical_cross_entropy_loss(predictions, targets, weights), expected)
if __name__ == "__main__":
tvm.testing.main()