You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

add-custom-layer.zh.md 2.9 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. # NCNN增加自定义层
  2. ## 举例
  3. 这里举个例子添加自定义层次 如Relu6,即 std::min(6.f, std::max(0.f, val))
  4. ```
  5. Input input 0 1 input
  6. Convolution conv2d 1 1 input conv2d 0=32 1=1 2=1 3=1 4=0 5=0 6=768
  7. Relu6 relu6 1 1 conv2d relu6
  8. Pooling maxpool 1 1 relu6 maxpool 0=0 1=3 2=2 3=-233 4=0
  9. ```
  10. ## 定义源码h文件:src/layer/relu6.h
  11. ```CPP
  12. #ifndef LAYER_RELU6_H
  13. #define LAYER_RELU6_H
  14. #include "layer.h"
  15. namespace ncnn {
  16. class Relu6 : public Layer
  17. {
  18. public:
  19. Relu6();
  20. virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const;
  21. };
  22. } // namespace ncnn
  23. #endif // LAYER_RELU6_H
  24. ```
  25. ## 定义源码CPP文件:src/layer/relu6.cpp
  26. ```CPP
  27. #include "relu6.h"
  28. #include <math.h>
  29. namespace ncnn {
  30. Relu6::Relu6()
  31. {
  32. one_blob_only = true;
  33. support_inplace = true;
  34. }
  35. int Relu6::forward_inplace(Mat& bottom_top_blob, const Option& opt) const
  36. {
  37. int w = bottom_top_blob.w;
  38. int h = bottom_top_blob.h;
  39. int channels = bottom_top_blob.c;
  40. int size = w * h;
  41. #pragma omp parallel for num_threads(opt.num_threads)
  42. for (int q=0; q < channels; q++)
  43. {
  44. float* ptr = bottom_top_blob.channel(q);
  45. for (int i=0; i<size; i++)
  46. {
  47. ptr[i] = std::min(6.f, std::max(0.f, ptr[i]));
  48. }
  49. }
  50. return 0;
  51. }
  52. } // namespace ncnn
  53. ```
  54. ## 修改 src/CMakeLists.txt 注册Relu6
  55. ```CPP
  56. ncnn_add_layer(GroupNorm)
  57. ncnn_add_layer(LayerNorm)
  58. ncnn_add_layer(Relu6)
  59. ```
  60. ## 定义测试用例CPP文件 tests/test_relu6.cpp
  61. ```CPP
  62. #include "layer/relu6.h"
  63. #include "testutil.h"
  64. static int test_relu6(const ncnn::Mat& a)
  65. {
  66. ncnn::ParamDict pd;
  67. std::vector<ncnn::Mat> weights(0);
  68. int ret = test_layer<ncnn::Relu6>("Relu6", pd, weights, a);
  69. if (ret != 0)
  70. {
  71. fprintf(stderr, "test_relu6 failed a.dims=%d a=(%d %d %d)\n", a.dims, a.w, a.h, a.c);
  72. }
  73. return ret;
  74. }
  75. static int test_relu6_0()
  76. {
  77. return 0
  78. || test_relu6(RandomMat(5, 7, 24))
  79. || test_relu6(RandomMat(7, 9, 12))
  80. || test_relu6(RandomMat(3, 5, 13));
  81. }
  82. static int test_relu6_1()
  83. {
  84. return 0
  85. || test_relu6(RandomMat(15, 24))
  86. || test_relu6(RandomMat(17, 12))
  87. || test_relu6(RandomMat(19, 15));
  88. }
  89. static int test_relu6_2()
  90. {
  91. return 0
  92. || test_relu6(RandomMat(128))
  93. || test_relu6(RandomMat(124))
  94. || test_relu6(RandomMat(127));
  95. }
  96. int main()
  97. {
  98. SRAND(7767517);
  99. return 0
  100. || test_relu6_0()
  101. || test_relu6_1()
  102. || test_relu6_2();
  103. }
  104. ```
  105. ## 修改tests/CMakeLists.txt 注册Relu6测试用例
  106. ```CPP
  107. ncnn_add_layer_test(LSTM)
  108. ncnn_add_layer_test(Yolov3DetectionOutput)
  109. ncnn_add_layer_test(Relu6)
  110. ```
  111. ## 编译
  112. ```
  113. 按原NCNN步骤编译
  114. ```
  115. ## 单元测试
  116. ```
  117. ./test_relu6
  118. ```