300 lines
11 KiB
Python
300 lines
11 KiB
Python
# 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 ir as I
|
|
from tvm.script import relax as R
|
|
|
|
|
|
@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.TensorType((N, C), "float32")
|
|
targets = relax.TensorType((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_ty
|
|
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: 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.TensorType((N, C), "float32")
|
|
targets = relax.TensorType((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_ty
|
|
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: 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.TensorType((N, C), "float32")
|
|
targets = relax.TensorType((N,), "int64")
|
|
weights = relax.TensorType((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.TensorType((N, C), "float32")
|
|
targets = relax.TensorType((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_ty
|
|
N = s.shape[0]
|
|
C = s.shape[1]
|
|
targets = relax.TensorType((N,), "int64")
|
|
weights = relax.TensorType((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: 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.TensorType((N, C), "float32")
|
|
targets = relax.TensorType((N, C), "int64")
|
|
weights = relax.TensorType((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.TensorType((N, C), "float32")
|
|
targets = relax.TensorType((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.TensorType((N, C), "float32")
|
|
targets = relax.TensorType((N, C), "int64")
|
|
weights = relax.TensorType((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.ty.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()
|