Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[layer] add pow operation layer @open sesame 12/06 20:13 #2801

Merged
merged 1 commit into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Applications/Custom/LayerClient/jni/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ int api_model_run() {
/// creating array of layers same as in `custom_layer_client.ini`
layers = std::vector<std::shared_ptr<ml::train::Layer>>{
ml::train::layer::Input({"name=inputlayer", "input_shape=1:1:100"}),
ml::train::createLayer("pow", {"name=powlayer", "exponent=3"}),
ml::train::createLayer("custom_pow", {"name=powlayer", "exponent=3"}),
ml::train::layer::FullyConnected(
{"name=outputlayer", "input_layers=powlayer", "unit=10",
"bias_initializer=zeros", "activation=softmax"}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Input_Shape = 1:1:100

[powlayer]
input_layers = inputlayer
Type = pow # AppContext sees PowLayer::getType() and use this to parse type
Type = custom_pow # AppContext sees PowLayer::getType() and use this to parse type
exponent = 3 # registering a custom property is done at int PowLayer::setProperty

[outputlayer]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

GTEST_PARAMETER_TEST(PowLayer, LayerPluginCommonTest,
::testing::Values(std::make_tuple("libpow_layer.so",
"pow")));
"custom_pow")));

auto semantic_pow =
LayerSemanticsParamType(nntrainer::createLayer<custom::PowLayer>,
Expand Down
12 changes: 6 additions & 6 deletions Applications/Custom/LayerPlugin/layer_plugin_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ TEST(AppContext, DlRegisterOpen_p) {

ac.registerLayer("libpow_layer.so", NNTRAINER_PATH);

auto layer = ac.createObject<nntrainer::Layer>("pow");
auto layer = ac.createObject<nntrainer::Layer>("custom_pow");

EXPECT_EQ(layer->getType(), "pow");
EXPECT_EQ(layer->getType(), "custom_pow");
}

TEST(AppContext, DlRegisterWrongPath_n) {
Expand All @@ -49,9 +49,9 @@ TEST(AppContext, DlRegisterDirectory_p) {

ac.registerPluggableFromDirectory(NNTRAINER_PATH);

auto layer = ac.createObject<nntrainer::Layer>("pow");
auto layer = ac.createObject<nntrainer::Layer>("custom_pow");

EXPECT_EQ(layer->getType(), "pow");
EXPECT_EQ(layer->getType(), "custom_pow");
}

TEST(AppContext, DlRegisterDirectory_n) {
Expand All @@ -64,8 +64,8 @@ TEST(AppContext, DlRegisterDirectory_n) {
TEST(AppContext, DefaultEnvironmentPath_p) {
/// as NNTRAINER_PATH is fed to the test, this should success without an
/// error
std::shared_ptr<ml::train::Layer> l = ml::train::createLayer("pow");
EXPECT_EQ(l->getType(), "pow");
std::shared_ptr<ml::train::Layer> l = ml::train::createLayer("custom_pow");
EXPECT_EQ(l->getType(), "custom_pow");
std::shared_ptr<nntrainer::LayerNode> lnode =
std::static_pointer_cast<nntrainer::LayerNode>(l);

Expand Down
2 changes: 1 addition & 1 deletion Applications/Custom/pow.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class PowLayer final : public nntrainer::Layer {
*/
void setProperty(const std::vector<std::string> &values) override;

inline static const std::string type = "pow";
inline static const std::string type = "custom_pow";

private:
float exponent;
Expand Down
9 changes: 9 additions & 0 deletions api/ccapi/include/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum LayerType {
LAYER_SUBTRACT = ML_TRAIN_LAYER_TYPE_SUBTRACT, /**< Subtract Layer type */
LAYER_MULTIPLY = ML_TRAIN_LAYER_TYPE_MULTIPLY, /**< Multiply Layer type */
LAYER_DIVIDE = ML_TRAIN_LAYER_TYPE_DIVIDE, /**< Divide Layer type */
LAYER_POW = ML_TRAIN_LAYER_TYPE_POW, /**< Pow Layer type */
LAYER_FC = ML_TRAIN_LAYER_TYPE_FC, /**< Fully Connected Layer type */
LAYER_SWIGLU = ML_TRAIN_LAYER_TYPE_SWIGLU, /**< Swiglu Layer type */
LAYER_BN = ML_TRAIN_LAYER_TYPE_BN, /**< Batch Normalization Layer type */
Expand Down Expand Up @@ -330,6 +331,14 @@ DivideLayer(const std::vector<std::string> &properties = {}) {
return createLayer(LayerType::LAYER_DIVIDE, properties);
}

/**
* @brief Helper function to create pow layer
*/
inline std::unique_ptr<Layer>
PowLayer(const std::vector<std::string> &properties = {}) {
return createLayer(LayerType::LAYER_POW, properties);
}

/**
* @brief Helper function to create fully connected layer
*/
Expand Down
1 change: 1 addition & 0 deletions api/nntrainer-api-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ typedef enum {
ML_TRAIN_LAYER_TYPE_TRANSPOSE = 36, /**< Transpose Layer type */
ML_TRAIN_LAYER_TYPE_CONV2D_TRANSPOSE =
37, /**< Convolution 2D Transpose Layer (Since 9.0) */
ML_TRAIN_LAYER_TYPE_POW = 38, /**< Pow Layer type (Since 9.0)*/
ML_TRAIN_LAYER_TYPE_PREPROCESS_FLIP =
300, /**< Preprocess flip Layer (Since 6.5) */
ML_TRAIN_LAYER_TYPE_PREPROCESS_TRANSLATE =
Expand Down
3 changes: 3 additions & 0 deletions nntrainer/app_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#include <plugged_optimizer.h>
#include <pooling2d_layer.h>
#include <positional_encoding_layer.h>
#include <pow_layer.h>
#include <preprocess_flip_layer.h>
#include <preprocess_l2norm_layer.h>
#include <preprocess_translate_layer.h>
Expand Down Expand Up @@ -273,6 +274,8 @@ static void add_default_object(AppContext &ac) {
LayerType::LAYER_MULTIPLY);
ac.registerFactory(nntrainer::createLayer<DivideLayer>, DivideLayer::type,
LayerType::LAYER_DIVIDE);
ac.registerFactory(nntrainer::createLayer<PowLayer>, PowLayer::type,
LayerType::LAYER_POW);
ac.registerFactory(nntrainer::createLayer<FullyConnectedLayer>,
FullyConnectedLayer::type, LayerType::LAYER_FC);
ac.registerFactory(nntrainer::createLayer<BatchNormalizationLayer>,
Expand Down
2 changes: 2 additions & 0 deletions nntrainer/layers/common_properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ InputConnection::InputConnection(const Connection &value) :

Epsilon::Epsilon(float value) { set(value); }

Exponent::Exponent(float value) { set(value); }

bool Epsilon::isValid(const float &value) const { return value > 0.0f; }

Momentum::Momentum(float value) { set(value); }
Expand Down
16 changes: 16 additions & 0 deletions nntrainer/layers/common_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,22 @@ class Epsilon : public nntrainer::Property<float> {
bool isValid(const float &value) const override;
};

/**
* @brief Exponent property, this is used for pow operation
*
*/
class Exponent : public nntrainer::Property<float> {

public:
/**
* @brief Construct a new Exponent object
*
*/
Exponent(float value = 1.0f);
static constexpr const char *key = "exponent"; /**< unique key to access */
using prop_tag = float_prop_tag; /**< property type */
};

/**
* @brief Momentum property, moving average in batch normalization layer
*
Expand Down
1 change: 1 addition & 0 deletions nntrainer/layers/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ layer_sources = [
'subtract_layer.cpp',
'multiply_layer.cpp',
'divide_layer.cpp',
'pow_layer.cpp',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a simple suggestion (not directly related to this PR though).
What about using prefix like 'op_' to operation layers?
It might reduce the confusion on the layer types (e.g., add_layer & addition_layer).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds good idea. I'll reflect it in later pr. thanks!

'addition_layer.cpp',
'attention_layer.cpp',
'mol_attention_layer.cpp',
Expand Down
50 changes: 50 additions & 0 deletions nntrainer/layers/pow_layer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: Apache-2.0
/**
* Copyright (C) 2024 SeungBaek Hong <[email protected]>
*
* @file pow_layer.cpp
* @date 20 Nov 2024
* @see https://github.com/nnstreamer/nntrainer
* @author SeungBaek Hong <[email protected]>
* @bug No known bugs except for NYI items
* @brief This is pow layer class (operation layer)
*
*/

#include "common_properties.h"
#include <nntrainer_error.h>
#include <nntrainer_log.h>
#include <node_exporter.h>
#include <pow_layer.h>
#include <util_func.h>

#include <layer_context.h>

namespace nntrainer {

void PowLayer::finalize(InitLayerContext &context) {
context.setOutputDimensions({context.getInputDimensions()[0]});
}

void PowLayer::forwarding_operation(const Tensor &input, Tensor &hidden) {
float exponent = std::get<props::Exponent>(pow_props).get();
input.pow(exponent, hidden);
}

void PowLayer::calcDerivative(RunLayerContext &context) {
float exp = std::get<props::Exponent>(pow_props).get();
context.getOutgoingDerivative(0).copy(
context.getIncomingDerivative(SINGLE_INOUT_IDX)
.multiply(exp)
.multiply(context.getInput(0).pow(exp - 1.0f)));
}

void PowLayer::setProperty(const std::vector<std::string> &values) {
auto remain_props = loadProperties(values, pow_props);
if (!remain_props.empty()) {
std::string msg = "[PowLayer] Unknown Layer Properties count " +
std::to_string(values.size());
throw exception::not_supported(msg);
}
}
} /* namespace nntrainer */
124 changes: 124 additions & 0 deletions nntrainer/layers/pow_layer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// SPDX-License-Identifier: Apache-2.0
/**
* Copyright (C) 2024 SeungBaek Hong <[email protected]>
*
* @file pow_layer.h
* @date 20 Nov 2024
* @see https://github.com/nnstreamer/nntrainer
* @author SeungBaek Hong <[email protected]>
* @bug No known bugs except for NYI items
* @brief This is pow layer class (operation layer)
*
*/

#ifndef __POW_LAYER_H__
#define __POW_LAYER_H__
#ifdef __cplusplus

#include <common_properties.h>
#include <layer_devel.h>
#include <operation_layer.h>

namespace nntrainer {

/**
* @class Pow Layer
* @brief Pow Layer
*/
class PowLayer : public UnaryOperationLayer {
public:
/**
* @brief Constructor of Pow Layer
*/
PowLayer() :
UnaryOperationLayer(),
pow_props(props::Print(), props::InPlaceProp(), props::Exponent()),
support_backwarding(true) {}

/**
* @brief Destructor of Pow Layer
*/
~PowLayer(){};

/**
* @brief Move constructor of Pow Layer.
* @param[in] PowLayer &&
*/
PowLayer(PowLayer &&rhs) noexcept = default;

/**
* @brief Move assignment operator.
* @parma[in] rhs PowLayer to be moved.
*/
PowLayer &operator=(PowLayer &&rhs) = default;

/**
* @copydoc Layer::finalize(InitLayerContext &context)
*/
void finalize(InitLayerContext &context) final;

/**
* @brief forwarding operation for pow
*
* @param input input tensor
* @param hidden tensor to store the result value
*/
void forwarding_operation(const Tensor &input, Tensor &hidden) final;

/**
* @copydoc Layer::calcDerivative(RunLayerContext &context)
*/
void calcDerivative(RunLayerContext &context) final;

/**
* @copydoc bool supportBackwarding() const
*/
bool supportBackwarding() const final { return support_backwarding; };

/**
* @brief Initialize the in-place settings of the layer
* @return InPlaceType
*/
InPlaceType initializeInPlace() final {
if (std::get<props::InPlaceProp>(pow_props).empty() ||
!std::get<props::InPlaceProp>(pow_props).get()) {
is_inplace = false;
support_backwarding = true;
} else {
is_inplace = true;
support_backwarding = false;
}

if (!supportInPlace())
return InPlaceType::NONE;
else
return InPlaceType::NON_RESTRICTING;
}

/**
* @copydoc Layer::exportTo(Exporter &exporter, ml::train::ExportMethods
* method)
*/
void exportTo(Exporter &exporter,
const ml::train::ExportMethods &method) const final {}

/**
* @copydoc Layer::setProperty(const std::vector<std::string> &values)
*/
void setProperty(const std::vector<std::string> &values) final;

/**
* @copydoc Layer::getType()
*/
const std::string getType() const final { return PowLayer::type; };

std::tuple<props::Print, props::InPlaceProp, props::Exponent> pow_props;
bool support_backwarding; /**< support backwarding */

inline static const std::string type = "pow";
};

} // namespace nntrainer

#endif /* __cplusplus */
#endif /* __POW_LAYER_H__ */
1 change: 1 addition & 0 deletions nntrainer/utils/node_exporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ class Packed;
class LossScaleForMixed;
class InPlaceProp;
class InPlaceDirectionProp;
class Exponent;
} // namespace props

class LayerNode;
Expand Down
Binary file modified packaging/unittest_models_v2.tar.gz
Binary file not shown.
23 changes: 23 additions & 0 deletions test/input_gen/genModelTests_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,19 @@ def forward(self, inputs, labels):
return out, loss


class PowOperation(torch.nn.Module):
def __init__(self):
super().__init__()
self.fc = torch.nn.Linear(2, 2)
self.loss = torch.nn.MSELoss()

def forward(self, inputs, labels):
out = self.fc(inputs[0])
out = out.pow(3)
loss = self.loss(out, labels[0])
return out, loss


if __name__ == "__main__":
record_v2(
ReduceMeanLast(),
Expand Down Expand Up @@ -836,6 +849,16 @@ def forward(self, inputs, labels):
name="multiply_operation",
)

pow_operation = PowOperation()
record_v2(
pow_operation,
iteration=2,
input_dims=[(1, 2)],
input_dtype=[float],
label_dims=[(1, 2)],
name="pow_operation",
)

# Function to check the created golden test file
inspect_file("add_operation.nnmodelgolden")
fc_mixed_training_nan_sgd = LinearMixedPrecisionNaNSGD()
Expand Down
1 change: 1 addition & 0 deletions test/unittest/layers/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ test_target = [
'unittest_layers_subtract.cpp',
'unittest_layers_multiply.cpp',
'unittest_layers_divide.cpp',
'unittest_layers_pow.cpp',
'unittest_layers_multiout.cpp',
'unittest_layers_rnn.cpp',
'unittest_layers_rnncell.cpp',
Expand Down
Loading
Loading