예제 #1
0
        public FeatureExpander(string network, string[] outputs, int[] num_filters, bool use_1x1_transition = true,
                               bool use_bn     = true, float reduce_ratio = 1, int min_depth      = 128, bool global_pool       = false,
                               bool pretrained = false, Context ctx       = null, string[] inputs = null, ParameterDict @params = null) : base(null, null, @params)
        {
            var(p_i, p_o, p_p) = __internal__.ParseNetwork(network, outputs, inputs, pretrained, ctx);
            // append more layers
            var y           = p_o.Last();
            var weight_init = new Xavier(rnd_type: "gaussian", factor_type: "out", magnitude: 2);

            foreach (var _tup_2 in num_filters.Select((_p_1, _p_2) => Tuple.Create(_p_2, _p_1)))
            {
                var i = _tup_2.Item1;
                var f = _tup_2.Item2;
                if (use_1x1_transition)
                {
                    var num_trans = Math.Max(min_depth, Convert.ToInt32(Math.Round(f * reduce_ratio)));

                    y = sym.Convolution(y, weight_init.InitWeight("weight"), null, num_filter: num_trans, kernel: new Shape(1, 1), no_bias: use_bn, symbol_name: $"expand_trans_conv{i}");

                    if (use_bn)
                    {
                        y = sym.BatchNorm(y, null, null, null, null, symbol_name: $"expand_trans_bn{i}");
                    }

                    y = sym.Activation(y, act_type: ActivationType.Relu, symbol_name: $"expand_trans_relu{i}");
                }

                y = sym.Convolution(y, weight_init.InitWeight("weight"), null, num_filter: f, kernel: new Shape(3, 3), pad: new Shape(1, 1), stride: new Shape(2, 2), no_bias: use_bn, symbol_name: $"expand_conv{i}");
                if (use_bn)
                {
                    y = sym.BatchNorm(y, null, null, null, null, symbol_name: $"expand_bn{i}");
                }

                y = sym.Activation(y, act_type: ActivationType.Relu, symbol_name: $"expand_reu{i}");
                p_o.Add(y);
            }
            if (global_pool)
            {
                p_o.Add(sym.Pooling(y, pool_type: PoolingType.Avg, global_pool: true, kernel: new Shape(1, 1)));
            }

            base.Construct(p_o, p_i, p_p);
        }
예제 #2
0
        private void Construct(SymbolList outputs, SymbolList inputs, ParameterDict @params, int[] num_filters, bool use_1x1 = true, bool use_upsample = true,
                               bool use_elewadd = true, bool use_p6        = false, bool p6_conv = true, bool no_bias       = true,
                               bool pretrained  = false, string norm_layer = null, FuncArgs norm_kwargs = null, Context ctx = null)
        {
            Symbol y_p6 = null;

            // e.g. For ResNet50, the feature is :
            // outputs = ['stage1_activation2', 'stage2_activation3',
            //            'stage3_activation5', 'stage4_activation2']
            // with regard to [conv2, conv3, conv4, conv5] -> [C2, C3, C4, C5]
            // append more layers with reversed order : [P5, P4, P3, P2]
            var y             = outputs.Last();
            var base_features = outputs.Take(outputs.Length - 1).ToArray();
            var num_stages    = num_filters.Length + 1;
            var weight_init   = new Xavier(rnd_type: "uniform", factor_type: "in", magnitude: 1);
            var tmp_outputs   = new List <Symbol>();

            // num_filter is 256 in ori paper
            for (int i = 0; i < base_features.Length; i++)
            {
                var bf = base_features[i];
                var f  = num_filters[i];
                if (i == 0)
                {
                    if (use_1x1)
                    {
                        y = sym.Convolution(y, weight_init.InitWeight("weight"), null, num_filter: f, kernel: new Shape(1, 1), pad: new Shape(0, 0), stride: new Shape(1, 1), no_bias: no_bias, symbol_name: $"P{num_stages - i}_conv_lat");

                        if (norm_layer != null)
                        {
                            if (norm_layer == "SyncBatchNorm")
                            {
                                norm_kwargs["key"]  = $"P{num_stages - i}_lat_bn";
                                norm_kwargs["name"] = $"P{num_stages - i}_lat_bn";
                            }

                            var bn = LayerUtils.NormLayer(norm_layer, norm_kwargs);

                            y = bn.Call(y);
                        }
                    }
                    if (use_p6 && p6_conv)
                    {
                        // method 2 : use conv (Deformable use this)
                        y_p6 = sym.Convolution(y, weight_init.InitWeight("weight"), null, num_filter: f, kernel: new Shape(3, 3), pad: new Shape(1, 1), stride: new Shape(2, 2), no_bias: no_bias, symbol_name: $"P{num_stages + 1}_conv1");
                        if (norm_layer != null)
                        {
                            if (norm_layer == "SyncBatchNorm")
                            {
                                norm_kwargs["key"]  = $"P{num_stages - i}_pre_bn";
                                norm_kwargs["name"] = $"P{num_stages - i}_pre_bn";
                            }

                            var bn = LayerUtils.NormLayer(norm_layer, norm_kwargs);
                            y_p6 = bn.Call(y_p6);
                        }
                    }
                }
                else
                {
                    if (use_1x1)
                    {
                        bf = sym.Convolution(bf, weight_init.InitWeight("weight"), null, num_filter: f, kernel: new Shape(1, 1), pad: new Shape(0, 0), stride: new Shape(1, 1), no_bias: no_bias, symbol_name: $"P{num_stages - i}_conv_lat");

                        if (norm_layer != null)
                        {
                            if (norm_layer == "SyncBatchNorm")
                            {
                                norm_kwargs["key"]  = $"P{num_stages - i}_conv1_bn";
                                norm_kwargs["name"] = $"P{num_stages - i}_conv1_bn";
                            }

                            var bn = LayerUtils.NormLayer(norm_layer, norm_kwargs);
                            bf = bn.Call(bf);
                        }
                    }
                    if (use_upsample)
                    {
                        y = sym.UpSampling(y, scale: 2, num_args: 1, sample_type: UpsamplingSampleType.Nearest, symbol_name: $"P{num_stages - i}_upsp");
                    }

                    if (use_elewadd)
                    {
                        // make two symbol alignment
                        // method 1 : mx.sym.Crop
                        // y = mx.sym.Crop(*[y, bf], name="P{}_clip".format(num_stages-i))
                        // method 2 : mx.sym.slice_like
                        y = sym.SliceLike(y, bf, axes: new Shape(2, 3), symbol_name: $"P{num_stages - i}_clip");
                        y = sym.ElemwiseAdd(bf, y, symbol_name: $"P{num_stages - i}_sum");
                    }
                }
                // Reduce the aliasing effect of upsampling described in ori paper
                var @out = sym.Convolution(y, weight_init.InitWeight("weight"), null, num_filter: f, kernel: new Shape(3, 3), pad: new Shape(1, 1), stride: new Shape(1, 1), no_bias: no_bias, symbol_name: $"P{num_stages - i}_conv1");
                if (i == 0 && use_p6 && !p6_conv)
                {
                    // method 2 : use max pool (Detectron use this)
                    y_p6 = sym.Pooling(@out, pool_type: PoolingType.Max, kernel: new Shape(1, 1), pad: new Shape(0, 0), stride: new Shape(2, 2), symbol_name: $"P{num_stages + 1}_pre");
                }
                if (norm_layer != null)
                {
                    if (norm_layer == "SyncBatchNorm")
                    {
                        norm_kwargs["key"]  = $"P{num_stages - i}_bn";
                        norm_kwargs["name"] = $"P{num_stages - i}_bn";
                    }

                    var bn = LayerUtils.NormLayer(norm_layer, norm_kwargs);
                    @out = bn.Call(@out);
                }

                tmp_outputs.Add(@out);
            }

            if (use_p6)
            {
                outputs = tmp_outputs.Take(tmp_outputs.Count - 1).ToList();
                outputs.Add(y_p6);
            }
            else
            {
                outputs = tmp_outputs.Take(tmp_outputs.Count - 1).ToList();
            }

            base.Construct(outputs, inputs, @params);
        }