public ParameterSet(PassIndex pass, float blendFactor = 0.7f)
 {
     Pass                = pass;
     BlendFactor         = blendFactor;
     Beta                = 0.5f;
     Eps                 = 0.00001f;
     IgnoreSingularValue = 0.00001f;
 }
        /// <summary>
        /// Create a Universal style transfer decoder. There are 5 decoders in UST, use index to specify which one to create.
        /// </summary>
        /// <param name="imageDimension">image dimension for the decoder to work with. Note that it might be different from  the decoder input dimemensions</param>
        /// <param name="index"></param>
        /// <returns></returns>
        protected Function CreateDecoders(Vector2Int imageDimension, PassIndex index)
        {
            Function   encoderLayers;
            int        ind       = (int)index + 1; //1 based index for the names
            Vector2Int inputDims = imageDimension;

            int[] xOffsets = new int[5];
            int[] yOffsets = new int[5];

            for (int i = 1; i < ind; ++i)
            {
                var temp = new Vector2Int(Mathf.CeilToInt(inputDims.x / 2.0f), Mathf.CeilToInt(inputDims.y / 2.0f));
                if (Mathf.Abs(inputDims.x / 2.0f - temp.x) > 0.00001f)
                {
                    xOffsets[i] = 1;
                }
                if (Mathf.Abs(inputDims.y / 2.0f - temp.y) > 0.00001f)
                {
                    yOffsets[i] = 1;
                }
                inputDims = temp;
            }

            //set the channel number
            int inputChannels = 64;

            switch (index)
            {
            case PassIndex.PassOne:
                inputChannels = 64;
                break;

            case PassIndex.PassTwo:
                inputChannels = 128;
                break;

            case PassIndex.PassThree:
                inputChannels = 256;
                break;

            case PassIndex.PassFour:
                inputChannels = 512;
                break;

            case PassIndex.PassFive:
                inputChannels = 512;
                break;

            default:
                inputChannels = 64;
                break;
            }

            //input variables
            Variable prev = Variable.InputVariable(new int[] { inputDims.x, inputDims.y, inputChannels }, DataType.Float, "input");

            //encoderLayers["input"] = prev;

            if (ind >= 5)
            {
                //decoder 5
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 512, 3, 3, device, 1, false, true, "de" + ind + "conv5_1");
                prev = CNTKLib.ReLU(prev);
                prev = Layers.Upsample2D2(prev, xOffsets[4], yOffsets[4]);
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 512, 3, 3, device, 1, false, true, "de" + ind + "conv4_4");
                prev = CNTKLib.ReLU(prev);
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 512, 3, 3, device, 1, false, true, "de" + ind + "conv4_3");
                prev = CNTKLib.ReLU(prev);
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 512, 3, 3, device, 1, false, true, "de" + ind + "conv4_2");
                prev = CNTKLib.ReLU(prev);
            }

            if (ind >= 4)
            {
                //decoder 4
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 256, 3, 3, device, 1, false, true, "de" + ind + "conv4_1");
                prev = CNTKLib.ReLU(prev);
                prev = Layers.Upsample2D2(prev, xOffsets[3], yOffsets[3]);
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 256, 3, 3, device, 1, false, true, "de" + ind + "conv3_4");
                prev = CNTKLib.ReLU(prev);
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 256, 3, 3, device, 1, false, true, "de" + ind + "conv3_3");
                prev = CNTKLib.ReLU(prev);
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 256, 3, 3, device, 1, false, true, "de" + ind + "conv3_2");
                prev = CNTKLib.ReLU(prev);
            }

            if (ind >= 3)
            {
                //decoder 3
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 128, 3, 3, device, 1, false, true, "de" + ind + "conv3_1");
                prev = CNTKLib.ReLU(prev);
                prev = Layers.Upsample2D2(prev, xOffsets[2], yOffsets[2]);
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 128, 3, 3, device, 1, false, true, "de" + ind + "conv2_2");
                prev = CNTKLib.ReLU(prev);
            }

            if (ind >= 2)
            {
                //decoder 2
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 64, 3, 3, device, 1, false, true, "de" + ind + "conv2_1");
                prev = CNTKLib.ReLU(prev);
                prev = Layers.Upsample2D2(prev, xOffsets[1], yOffsets[1]);
                prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
                prev = Layers.Convolution2D(prev, 64, 3, 3, device, 1, false, true, "de" + ind + "conv1_2");
                prev = CNTKLib.ReLU(prev);
            }

            //decoder 1
            prev = CNTKLib.Pad(prev, PaddingMode.REFLECTPAD, new SizeTVector(new uint[] { 1, 1, 0 }), new SizeTVector(new uint[] { 1, 1, 0 }));
            prev = Layers.Convolution2D(prev, 3, 3, 3, device, 1, false, true, "de" + ind + "conv1_1");
            prev = CNTKLib.ReLU(prev, "output");

            //encoderLayers["output"] = prev;
            encoderLayers = prev;
            return(encoderLayers);
        }