diff --git a/api/ccapi/include/layer.h b/api/ccapi/include/layer.h index 2e42a8cbfa..e1a6885c7c 100644 --- a/api/ccapi/include/layer.h +++ b/api/ccapi/include/layer.h @@ -45,7 +45,9 @@ enum LayerType { LAYER_SWIGLU = ML_TRAIN_LAYER_TYPE_SWIGLU, /**< Swiglu Layer type */ LAYER_BN = ML_TRAIN_LAYER_TYPE_BN, /**< Batch Normalization Layer type */ LAYER_CONV2D = ML_TRAIN_LAYER_TYPE_CONV2D, /**< Convolution 2D Layer type */ - LAYER_CONV2D_TRANSPOSE = ML_TRAIN_LAYER_TYPE_CONV2D_TRANSPOSE, /**< Convolution 2D Transpose Layer type */ + LAYER_CONV2D_TRANSPOSE = + ML_TRAIN_LAYER_TYPE_CONV2D_TRANSPOSE, /**< Convolution 2D Transpose Layer + type */ LAYER_POOLING2D = ML_TRAIN_LAYER_TYPE_POOLING2D, /**< Pooling 2D Layer type */ LAYER_FLATTEN = ML_TRAIN_LAYER_TYPE_FLATTEN, /**< Flatten Layer type */ LAYER_ACTIVATION = diff --git a/api/nntrainer-api-common.h b/api/nntrainer-api-common.h index 393d853d8e..23e94a20e8 100644 --- a/api/nntrainer-api-common.h +++ b/api/nntrainer-api-common.h @@ -62,15 +62,16 @@ typedef enum { 27, /**< Layer Normalization Layer type (Since 7.0) */ ML_TRAIN_LAYER_TYPE_POSITIONAL_ENCODING = 28, /**< Positional Encoding Layer type (Since 7.0) */ - ML_TRAIN_LAYER_TYPE_IDENTITY = 29, /**< Identity Layer type (Since 8.0) */ - ML_TRAIN_LAYER_TYPE_SWIGLU = 30, /**< Swiglu Layer type */ - ML_TRAIN_LAYER_TYPE_WEIGHT = 31, /**< Weight Layer type (Since 9.0)*/ - ML_TRAIN_LAYER_TYPE_ADD = 32, /**< Add Layer type (Since 9.0)*/ - ML_TRAIN_LAYER_TYPE_SUBTRACT = 33, /**< Subtract Layer type (Since 9.0)*/ - ML_TRAIN_LAYER_TYPE_MULTIPLY = 34, /**< Multiply Layer type (Since 9.0)*/ - ML_TRAIN_LAYER_TYPE_DIVIDE = 35, /**< Divide Layer type (Since 9.0)*/ + ML_TRAIN_LAYER_TYPE_IDENTITY = 29, /**< Identity Layer type (Since 8.0) */ + ML_TRAIN_LAYER_TYPE_SWIGLU = 30, /**< Swiglu Layer type */ + ML_TRAIN_LAYER_TYPE_WEIGHT = 31, /**< Weight Layer type (Since 9.0)*/ + ML_TRAIN_LAYER_TYPE_ADD = 32, /**< Add Layer type (Since 9.0)*/ + ML_TRAIN_LAYER_TYPE_SUBTRACT = 33, /**< Subtract Layer type (Since 9.0)*/ + ML_TRAIN_LAYER_TYPE_MULTIPLY = 34, /**< Multiply Layer type (Since 9.0)*/ + ML_TRAIN_LAYER_TYPE_DIVIDE = 35, /**< Divide Layer type (Since 9.0)*/ ML_TRAIN_LAYER_TYPE_TRANSPOSE = 36, /**< Transpose Layer type */ - ML_TRAIN_LAYER_TYPE_CONV2D_TRANSPOSE = 37, /**< Convolution 2D Transpose Layer (Since 10.0) */ + ML_TRAIN_LAYER_TYPE_CONV2D_TRANSPOSE = + 37, /**< Convolution 2D Transpose Layer (Since 9.0) */ ML_TRAIN_LAYER_TYPE_PREPROCESS_FLIP = 300, /**< Preprocess flip Layer (Since 6.5) */ ML_TRAIN_LAYER_TYPE_PREPROCESS_TRANSLATE = diff --git a/test/unittest/layers/unittest_layers_convolution2d_transpose.cpp b/test/unittest/layers/unittest_layers_convolution2d_transpose.cpp new file mode 100644 index 0000000000..cea4b93d1a --- /dev/null +++ b/test/unittest/layers/unittest_layers_convolution2d_transpose.cpp @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: Apache-2.0 +/** + * Copyright (C) 2024 UGyeong Song + * + * @file unittest_layers_convolution.cpp + * @date 21 November 2024 + * @brief Conv2dTranspose Layer Test + * @see https://github.com/nnstreamer/nntrainer + * @author UGyeong Song + * @bug No known bugs except for NYI items + */ +#include + +#include + +#include +#include + +auto semantic_conv2d_transpose = LayerSemanticsParamType( + nntrainer::createLayer, + nntrainer::Conv2DTransposeLayer::type, + {"filters=1", "kernel_size=1,1", "padding=1,1"}, + LayerCreateSetPropertyOptions::AVAILABLE_FROM_APP_CONTEXT, false, 1); + +GTEST_PARAMETER_TEST(Convolution2DTranspose, LayerSemantics, + ::testing::Values(semantic_conv2d_transpose)); + +auto conv2d_transpose_sb_minimum = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=3", "kernel_size=2,2"}, "1:1:4:4", + "conv2d_transpose_sb_minimum.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_mb_minimum = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=3", "kernel_size=2,2"}, "3:1:4:4", + "conv2d_transpose_mb_minimum.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_sb_same_remain = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=2", "kernel_size=3,3", "padding=same"}, "1:1:4:4", + "conv2d_transpose_sb_same_remain.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_mb_same_remain = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=2", "kernel_size=3,3", "padding=same"}, "3:1:4:4", + "conv2d_transpose_mb_same_remain.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_sb_same_uneven_remain_1 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=same", + }, + "1:3:4:4", "conv2d_transpose_sb_same_uneven_remain.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_sb_same_uneven_remain_2 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=0,1,0,1", + }, + "1:3:4:4", "conv2d_transpose_sb_same_uneven_remain.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_mb_same_uneven_remain_1 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=same", + }, + "3:3:4:4", "conv2d_transpose_mb_same_uneven_remain.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_mb_same_uneven_remain_2 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=0,1,0,1", + }, + "3:3:4:4", "conv2d_transpose_mb_same_uneven_remain.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_sb_valid_drop_last = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=valid", + }, + "1:3:7:7", "conv2d_transpose_sb_valid_drop_last.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_mb_valid_drop_last = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=valid", + }, + "3:3:7:7", "conv2d_transpose_mb_valid_drop_last.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_sb_no_overlap = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=3", "kernel_size=2,2", "stride=3,3"}, "1:2:5:5", + "conv2d_transpose_sb_no_overlap.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_mb_no_overlap = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=3", + "kernel_size=2,2", + "stride=3,3", + }, + "3:2:5:5", "conv2d_transpose_mb_no_overlap.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_sb_1x1_kernel = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=3", "kernel_size=1,1", "stride=2,2"}, "1:2:5:5", + "conv2d_transpose_sb_1x1_kernel.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_mb_1x1_kernel = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=3", + "kernel_size=1,1", + "stride=2,2", + }, + "3:2:5:5", "conv2d_transpose_mb_1x1_kernel.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_sb_dilation = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "dilation=2,2", + }, + "1:3:11:11", "conv2d_transpose_sb_dilation.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_mb_dilation = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "dilation=2,2", + }, + "3:3:11:11", "conv2d_transpose_mb_dilation.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_sb_same_dilation = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "padding=same", + "dilation=2,2", + }, + "1:3:11:11", "conv2d_transpose_sb_same_dilation.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +auto conv2d_transpose_mb_same_dilation = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "padding=same", + "dilation=2,2", + }, + "3:3:11:11", "conv2d_transpose_mb_same_dilation.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp32", "fp32"); + +GTEST_PARAMETER_TEST( + Convolution2DTranspose, LayerGoldenTest, + ::testing::Values( + conv2d_transpose_sb_minimum, conv2d_transpose_mb_minimum, + conv2d_transpose_sb_same_remain, conv2d_transpose_mb_same_remain, + conv2d_transpose_sb_same_uneven_remain_1, + conv2d_transpose_sb_same_uneven_remain_2, + conv2d_transpose_mb_same_uneven_remain_1, + conv2d_transpose_mb_same_uneven_remain_2, + conv2d_transpose_sb_valid_drop_last, conv2d_transpose_mb_valid_drop_last, + conv2d_transpose_sb_no_overlap, conv2d_transpose_mb_no_overlap, + conv2d_transpose_sb_1x1_kernel, conv2d_transpose_mb_1x1_kernel, + conv2d_transpose_sb_dilation, conv2d_transpose_mb_dilation, + conv2d_transpose_sb_same_dilation, conv2d_transpose_mb_same_dilation)); + +#ifdef ENABLE_FP16 +auto conv2d_transpose_sb_minimum_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=3", "kernel_size=2,2"}, "1:1:4:4", + "conv2d_transpose_sb_minimum_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_mb_minimum_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=3", "kernel_size=2,2"}, "3:1:4:4", + "conv2d_transpose_mb_minimum_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_sb_same_remain_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=2", "kernel_size=3,3", "padding=same"}, "1:1:4:4", + "conv2d_transpose_sb_same_remain_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_mb_same_remain_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=2", "kernel_size=3,3", "padding=same"}, "3:1:4:4", + "conv2d_transpose_mb_same_remain_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_sb_same_uneven_remain_1_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=same", + }, + "1:3:4:4", "conv2d_transpose_sb_same_uneven_remain_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_sb_same_uneven_remain_2_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=0,1,0,1", + }, + "1:3:4:4", "conv2d_transpose_sb_same_uneven_remain_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_mb_same_uneven_remain_1_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=same", + }, + "3:3:4:4", "conv2d_transpose_mb_same_uneven_remain_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_mb_same_uneven_remain_2_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=0,1,0,1", + }, + "3:3:4:4", "conv2d_transpose_mb_same_uneven_remain_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_sb_valid_drop_last_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=valid", + }, + "1:3:7:7", "conv2d_transpose_sb_valid_drop_last_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_mb_valid_drop_last_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "stride=2,2", + "padding=valid", + }, + "3:3:7:7", "conv2d_transpose_mb_valid_drop_last_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_sb_no_overlap_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=3", "kernel_size=2,2", "stride=3,3"}, "1:2:5:5", + "conv2d_transpose_sb_no_overlap_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_mb_no_overlap_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=3", + "kernel_size=2,2", + "stride=3,3", + }, + "3:2:5:5", "conv2d_transpose_mb_no_overlap_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_sb_1x1_kernel_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + {"filters=3", "kernel_size=1,1", "stride=2,2"}, "1:2:5:5", + "conv2d_transpose_sb_1x1_kernel_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_mb_1x1_kernel_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=3", + "kernel_size=1,1", + "stride=2,2", + }, + "3:2:5:5", "conv2d_transpose_mb_1x1_kernel_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_sb_dilation_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "dilation=2,2", + }, + "1:3:11:11", "conv2d_transpose_sb_dilation_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_mb_dilation_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "dilation=2,2", + }, + "3:3:11:11", "conv2d_transpose_mb_dilation_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_sb_same_dilation_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "padding=same", + "dilation=2,2", + }, + "1:3:11:11", "conv2d_transpose_sb_same_dilation_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +auto conv2d_transpose_mb_same_dilation_w16a16 = LayerGoldenTestParamType( + nntrainer::createLayer, + { + "filters=2", + "kernel_size=3,3", + "padding=same", + "dilation=2,2", + }, + "3:3:11:11", "conv2d_transpose_mb_same_dilation_w16a16.nnlayergolden", + LayerGoldenTestParamOptions::DEFAULT, "nchw", "fp16", "fp16"); + +GTEST_PARAMETER_TEST( + Convolution2DTranspose16, LayerGoldenTest, + ::testing::Values(conv2d_transpose_sb_minimum_w16a16, + conv2d_transpose_mb_minimum_w16a16, + conv2d_transpose_sb_same_remain_w16a16, + conv2d_transpose_mb_same_remain_w16a16, + conv2d_transpose_sb_same_uneven_remain_1_w16a16, + conv2d_transpose_sb_same_uneven_remain_2_w16a16, + conv2d_transpose_mb_same_uneven_remain_1_w16a16, + conv2d_transpose_mb_same_uneven_remain_2_w16a16, + conv2d_transpose_sb_valid_drop_last_w16a16, + conv2d_transpose_mb_valid_drop_last_w16a16, + conv2d_transpose_sb_no_overlap_w16a16, + conv2d_transpose_mb_no_overlap_w16a16, + conv2d_transpose_sb_1x1_kernel_w16a16, + conv2d_transpose_mb_1x1_kernel_w16a16, + conv2d_transpose_sb_dilation_w16a16, + conv2d_transpose_mb_dilation_w16a16, + conv2d_transpose_sb_same_dilation_w16a16, + conv2d_transpose_mb_same_dilation_w16a16)); +#endif