| 222 | |
| 223 | namespace { |
| 224 | SymbolVarArray make_pyramids(Network& network, size_t batch, DType out_dtype) { |
| 225 | SymbolVarArray pyramids; |
| 226 | auto data = network.add_var("data", {batch, 3, 256, 256}); |
| 227 | data = data + (-128.f); |
| 228 | if (out_dtype.category() == DTypeCategory::QUANTIZED) |
| 229 | data = network.add_type_cvt(data, dtype::QuantizedS8{1.f}); |
| 230 | auto first = out_dtype; |
| 231 | if (out_dtype.category() == DTypeCategory::QUANTIZED) |
| 232 | first = dtype::QuantizedS8{1.f}; |
| 233 | auto f = network.add_conv(data, 16, {3, 3}, first, true, {2, 2}, {1, 1}); |
| 234 | f = network.add_conv(f, 16, {3, 3}, first, true, {1, 1}, {1, 1}); |
| 235 | f = network.add_conv(f, 32, {3, 3}, first, true, {2, 2}, {1, 1}); |
| 236 | if (out_dtype.enumv() == DTypeEnum::QuantizedS4 || |
| 237 | out_dtype.enumv() == DTypeEnum::Quantized4Asymm) { |
| 238 | f = network.add_type_cvt(f, out_dtype); |
| 239 | } |
| 240 | |
| 241 | using Vector = SmallVector<size_t, 4>; |
| 242 | Vector stages = {3, 6, 6, 3}; |
| 243 | Vector mid_outputs = {32, 64, 128, 256}; |
| 244 | Vector enable_stride = {0, 1, 1, 1}; |
| 245 | for (size_t i = 0; i < 4; ++i) { |
| 246 | auto s = stages[i]; |
| 247 | auto o = mid_outputs[i]; |
| 248 | auto es = enable_stride[i]; |
| 249 | for (size_t j = 0; j < s; ++j) { |
| 250 | size_t stride = !es || j > 0 ? 1 : 2; |
| 251 | bool has_proj = j > 0 ? false : true; |
| 252 | f = create_block(network, f, stride, o, has_proj, out_dtype); |
| 253 | } |
| 254 | pyramids.push_back(f); |
| 255 | } |
| 256 | |
| 257 | for (size_t i = 0; i < pyramids.size(); ++i) { |
| 258 | pyramids[i] = network.add_type_cvt(pyramids[i], first); |
| 259 | } |
| 260 | return pyramids; |
| 261 | } |
| 262 | |
| 263 | SymbolVarArray fusion_pyramids_feature( |
| 264 | Network& network, SymbolVarArray pyramids, size_t fpn_conv_channels) { |