# NCNN增加自定义层 ## 举例 这里举个例子添加自定义层次 如Relu6,即 std::min(6, std::max(0, val)) ``` Input input 0 1 input Convolution conv2d 1 1 input conv2d 0=32 1=1 2=1 3=1 4=0 5=0 6=768 Relu6 relu6 1 1 conv2d relu6 Pooling maxpool 1 1 relu6 maxpool 0=0 1=3 2=2 3=-233 4=0 ``` ## 定义源码h文件:src/layer/relu6.h ```CPP #ifndef LAYER_RELU6_H #define LAYER_RELU6_H #include "layer.h" namespace ncnn { class Relu6 : public Layer { public: Relu6(); virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const; }; } // namespace ncnn #endif // LAYER_RELU6_H ``` ## 定义源码CPP文件:src/layer/relu6.cpp ```CPP #include "relu6.h" #include namespace ncnn { Relu6::Relu6() { one_blob_only = true; support_inplace = true; } int Relu6::forward_inplace(Mat& bottom_top_blob, const Option& opt) const { int w = bottom_top_blob.w; int h = bottom_top_blob.h; int channels = bottom_top_blob.c; int size = w * h; #pragma omp parallel for num_threads(opt.num_threads) for (int q=0; q < channels; q++) { float* ptr = bottom_top_blob.channel(q); for (int i=0; i weights(0); int ret = test_layer("Relu6", pd, weights, a); if (ret != 0) { fprintf(stderr, "test_relu6 failed a.dims=%d a=(%d %d %d)\n", a.dims, a.w, a.h, a.c); } return ret; } static int test_relu6_0() { return 0 || test_relu6(RandomMat(5, 7, 24)) || test_relu6(RandomMat(7, 9, 12)) || test_relu6(RandomMat(3, 5, 13)); } static int test_relu6_1() { return 0 || test_relu6(RandomMat(15, 24)) || test_relu6(RandomMat(17, 12)) || test_relu6(RandomMat(19, 15)); } static int test_relu6_2() { return 0 || test_relu6(RandomMat(128)) || test_relu6(RandomMat(124)) || test_relu6(RandomMat(127)); } int main() { SRAND(7767517); return 0 || test_relu6_0() || test_relu6_1() || test_relu6_2(); } ``` ## 修改tests/CMakeLists.txt 注册Relu6测试用例 ```CPP ncnn_add_layer_test(LSTM) ncnn_add_layer_test(Yolov3DetectionOutput) ncnn_add_layer_test(Relu6) ``` ## 编译 ``` 按原NCNN步骤编译 ``` ## 单元测试 ``` ./test_relu6 ```