示例#1
0
        /// <summary>
        /// Spatials the maximum pooling forward.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="output">The output.</param>
        /// <param name="indices">The indices.</param>
        /// <param name="cd">The cd.</param>
        /// <param name="ceilMode">if set to <c>true</c> [ceil mode].</param>
        /// <exception cref="ArgumentException">input must be a 4D tensor</exception>
        /// <exception cref="InvalidOperationException">
        /// input image is smaller than kernel size
        /// or
        /// pad should be smaller than half of the kernel size
        /// </exception>
        public static void SpatialMaxPoolingForward(NDArray input, NDArray output, NDArray indices, ConvolutionDesc2d cd, bool ceilMode)
        {
            if (input.DimensionCount != 4)
            {
                throw new ArgumentException("input must be a 4D tensor");
            }

            var dimw = 3;
            var dimh = 2;
            var dimc = 1;

            if (input.Shape[dimw] < cd.kW - cd.padW || input.Shape[dimh] < cd.kH - cd.padH)
            {
                throw new InvalidOperationException("input image is smaller than kernel size");
            }

            if (cd.padW > cd.kW / 2 || cd.padH > cd.kH / 2)
            {
                throw new InvalidOperationException("pad should be smaller than half of the kernel size");
            }

            var nbatch  = input.Shape[0];
            var nslices = input.Shape[dimc];
            var iheight = input.Shape[dimh];
            var iwidth  = input.Shape[dimw];

            long owidth;
            long oheight;

            if (ceilMode)
            {
                oheight = (long)(Math.Ceiling((float)(iheight - cd.kH + 2 * cd.padH) / cd.dH)) + 1;
                owidth  = (long)(Math.Ceiling((float)(iwidth - cd.kW + 2 * cd.padW) / cd.dW)) + 1;
            }
            else
            {
                oheight = (long)(Math.Floor((float)(iheight - cd.kH + 2 * cd.padH) / cd.dH)) + 1;
                owidth  = (long)(Math.Floor((float)(iwidth - cd.kW + 2 * cd.padW) / cd.dW)) + 1;
            }

            if (cd.padW != 0 || cd.padH != 0)
            {
                // ensure that the last pooling starts inside the image
                if ((oheight - 1) * cd.dH >= iheight + cd.padH)
                {
                    --oheight;
                }
                if ((owidth - 1) * cd.dW >= iwidth + cd.padW)
                {
                    --owidth;
                }
            }

            using (var inputContig = Ops.AsContiguous(input))
            {
                for (int i = 0; i < nbatch; ++i)
                {
                    using (var input_i = inputContig.Select(0, i))
                        using (var output_i = output.Select(0, i))
                            using (var indices_i = indices.Select(0, i))
                            {
                                IntPtr input_iPtr, output_iPtr, indices_iPtr;
                                using (NativeWrapper.BuildTensorRefPtr(input_i, out input_iPtr))
                                    using (NativeWrapper.BuildTensorRefPtr(output_i, out output_iPtr))
                                        using (NativeWrapper.BuildTensorRefPtr(indices_i, out indices_iPtr))
                                        {
                                            CpuOpsNative.TS_SpatialMaxPooling_updateOutput_frame(input_iPtr, output_iPtr, indices_iPtr,
                                                                                                 nslices, iwidth, iheight,
                                                                                                 owidth, oheight,
                                                                                                 cd.kW, cd.kH, cd.dW, cd.dH, cd.padW, cd.padH);
                                        }
                            }
                }
            }
        }