public static void SpatialMaxPoolingBackward(Tensor input, Tensor gradOutput, Tensor gradInput, Tensor indices, ConvolutionDesc2d cd, bool ceilMode) { int dimw = 3; int dimh = 2; int dimc = 1; long nbatch = input.Sizes[0]; long nslices = input.Sizes[dimc]; long iheight = input.Sizes[dimh]; long iwidth = input.Sizes[dimw]; long owidth = gradOutput.Sizes[dimw]; long oheight = gradOutput.Sizes[dimh]; Ops.Fill(gradInput, 0); using Tensor gradOutputContig = Ops.AsContiguous(gradOutput); for (int i = 0; i < nbatch; ++i) { using Tensor gradInput_i = gradInput.Select(0, i); using Tensor gradOutput_i = gradOutputContig.Select(0, i); using Tensor indices_i = indices.Select(0, i); using (NativeWrapper.BuildTensorRefPtr(gradInput_i, out IntPtr gradInput_iPtr)) using (NativeWrapper.BuildTensorRefPtr(gradOutput_i, out IntPtr gradOutput_iPtr)) using (NativeWrapper.BuildTensorRefPtr(indices_i, out IntPtr indices_iPtr)) { CpuOpsNative.TS_SpatialMaxPooling_updateGradInput_frame(gradInput_iPtr, gradOutput_iPtr, indices_iPtr, nslices, iwidth, iheight, owidth, oheight, cd.dW, cd.dH); } } }
private static void Conv2BackwardInputFrame(Tensor gradOutput, Tensor gradInput, Tensor weight, Tensor fgradInput, ConvolutionDesc2d cd) { using (Tensor gradOutput2d = gradOutput.View(gradOutput.Sizes[0], gradOutput.Sizes[1] * gradOutput.Sizes[2])) { Ops.Addmm(fgradInput, 0, fgradInput, 1, weight, gradOutput2d); } Ops.Fill(gradInput, 0); using (NativeWrapper.BuildTensorRefPtr(fgradInput, out IntPtr fgradInputPtr)) using (NativeWrapper.BuildTensorRefPtr(gradInput, out IntPtr gradInputPtr)) { CpuOpsNative.TS_Unfolded_Acc(fgradInputPtr, gradInputPtr, cd.kW, cd.kH, cd.dW, cd.dH, cd.padW, cd.padH, (int)gradInput.Sizes[0], (int)gradInput.Sizes[2], (int)gradInput.Sizes[1], (int)gradOutput.Sizes[2], (int)gradOutput.Sizes[1]); } }
/// <summary> /// Spatials the maximum pooling backward. /// </summary> /// <param name="input">The input.</param> /// <param name="gradOutput">The grad output.</param> /// <param name="gradInput">The grad input.</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> public static void SpatialMaxPoolingBackward(NDArray input, NDArray gradOutput, NDArray gradInput, NDArray indices, ConvolutionDesc2d cd, bool ceilMode) { var dimw = 3; var dimh = 2; var dimc = 1; var nbatch = input.Shape[0]; var nslices = input.Shape[dimc]; var iheight = input.Shape[dimh]; var iwidth = input.Shape[dimw]; var owidth = gradOutput.Shape[dimw]; var oheight = gradOutput.Shape[dimh]; Ops.Fill(gradInput, 0); using (var gradOutputContig = Ops.AsContiguous(gradOutput)) { for (int i = 0; i < nbatch; ++i) { using (var gradInput_i = gradInput.Select(0, i)) using (var gradOutput_i = gradOutputContig.Select(0, i)) using (var indices_i = indices.Select(0, i)) { IntPtr gradInput_iPtr, gradOutput_iPtr, indices_iPtr; using (NativeWrapper.BuildTensorRefPtr(gradInput_i, out gradInput_iPtr)) using (NativeWrapper.BuildTensorRefPtr(gradOutput_i, out gradOutput_iPtr)) using (NativeWrapper.BuildTensorRefPtr(indices_i, out indices_iPtr)) { CpuOpsNative.TS_SpatialMaxPooling_updateGradInput_frame(gradInput_iPtr, gradOutput_iPtr, indices_iPtr, nslices, iwidth, iheight, owidth, oheight, cd.dW, cd.dH); } } } } }
public static void SpatialMaxPoolingForward(Tensor input, Tensor output, Tensor 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.Sizes[dimw] < cd.kW - cd.padW || input.Sizes[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.Sizes[0]; var nslices = input.Sizes[dimc]; var iheight = input.Sizes[dimh]; var iwidth = input.Sizes[dimw]; long owidth; long oheight; if (ceilMode) { // ReSharper disable once ArrangeRedundantParentheses oheight = (long)(Math.Ceiling((float)(iheight - cd.kH + 2 * cd.padH) / cd.dH)) + 1; // ReSharper disable once ArrangeRedundantParentheses owidth = (long)(Math.Ceiling((float)(iwidth - cd.kW + 2 * cd.padW) / cd.dW)) + 1; } else { // ReSharper disable once ArrangeRedundantParentheses oheight = (long)(Math.Floor((float)(iheight - cd.kH + 2 * cd.padH) / cd.dH)) + 1; // ReSharper disable once ArrangeRedundantParentheses 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 (var 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); using (NativeWrapper.BuildTensorRefPtr(input_i, out var input_iPtr)) { using (NativeWrapper.BuildTensorRefPtr(output_i, out var output_iPtr)) { using (NativeWrapper.BuildTensorRefPtr(indices_i, out var 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); } } } } }