chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// ShuffleNetExpr.cpp
|
||||
// MNN
|
||||
// Reference paper: https://arxiv.org/pdf/1707.01083.pdf
|
||||
//
|
||||
// Created by MNN on 2019/06/25.
|
||||
// Copyright © 2018, Alibaba Group Holding Limited
|
||||
//
|
||||
|
||||
#include <map>
|
||||
#include "ShuffleNetExpr.hpp"
|
||||
#include <MNN/expr/ExprCreator.hpp>
|
||||
|
||||
using namespace MNN::Express;
|
||||
|
||||
// bottleNeckChannel = outputChannel / narrowRatio
|
||||
static VARP shuffleUnit(VARP x, int inputChannel, int outputChannel,
|
||||
int group, int stride, int narrowRatio) {
|
||||
int bottleNeckChannel = outputChannel / narrowRatio;
|
||||
int branchChannel = outputChannel;
|
||||
if (stride != 1) {
|
||||
branchChannel = outputChannel - inputChannel;
|
||||
}
|
||||
auto y = _Conv(0.0f, 0.0f, x, {inputChannel, bottleNeckChannel}, {1, 1}, VALID, {1, 1}, {1, 1}, group); // Group Conv
|
||||
y = _ChannelShuffle(y, group);
|
||||
y = _Conv(0.0f, 0.0f, y, {bottleNeckChannel, bottleNeckChannel}, {3, 3}, SAME, {stride, stride}, {1, 1}, bottleNeckChannel); // Depthwise Conv
|
||||
y = _Conv(0.0f, 0.0f, y, {bottleNeckChannel, branchChannel}, {1, 1}, VALID, {1, 1}, {1, 1}, group); // Group Conv
|
||||
if (stride != 1) {
|
||||
x = _AvePool(x, {3, 3}, {2, 2}, SAME);
|
||||
y = _Concat({x, y}, 1); // concat on channel axis (NCHW)
|
||||
} else {
|
||||
y = _Add(x, y);
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
static VARP shuffleBlock(VARP x, int inputChannel, int outputChannel,
|
||||
int group, int stride, int narrowRatio, int number) {
|
||||
x = shuffleUnit(x, inputChannel, outputChannel, group, stride, narrowRatio);
|
||||
for (int i = 1; i < number; ++i) {
|
||||
x = shuffleUnit(x, outputChannel, outputChannel, group, 1, narrowRatio);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
VARP shuffleNetExpr(int group, int numClass) {
|
||||
std::map<int, std::vector<int>> groupMap = {
|
||||
{1, {144, 288, 576}},
|
||||
{2, {200, 400, 800}},
|
||||
{3, {240, 480, 960}},
|
||||
{4, {272, 544, 1088}},
|
||||
{8, {384, 768, 1536}}
|
||||
};
|
||||
int outputChannelStage2 = groupMap[group][0];
|
||||
int outputChannelStage3 = groupMap[group][1];
|
||||
int outputChannelStage4 = groupMap[group][2];
|
||||
// Net Construction
|
||||
auto x = _Input({1, 3, 224, 224}, NC4HW4);
|
||||
x = _Conv(0.0f, 0.0f, x, {3, 24}, {3, 3}, SAME, {2, 2}, {1, 1}, 1);
|
||||
x = _MaxPool(x, {3, 3}, {2, 2}, SAME);
|
||||
x = shuffleBlock(x, 24, outputChannelStage2, group, 2, 4, 4);
|
||||
x = shuffleBlock(x, outputChannelStage2, outputChannelStage3, group, 2, 4, 8);
|
||||
x = shuffleBlock(x, outputChannelStage3, outputChannelStage4, group, 2, 4, 4);
|
||||
x = _AvePool(x, {7, 7}, {1, 1}, VALID);
|
||||
x = _Conv(0.0f, 0.0f, x, {outputChannelStage4, numClass}, {1, 1}, VALID, {1, 1}, {1, 1}, 1); // replace FC with Conv1x1
|
||||
return x;
|
||||
}
|
||||
Reference in New Issue
Block a user