public Pooling(LayerBase inputLayer, int filterSize, int stride = 1, Tensor.PoolType type = Tensor.PoolType.Max) : base(inputLayer, Pooling.GetOutShape(inputLayer.OutputShape, filterSize, filterSize, stride)) { Type = type; FilterSize = filterSize; Stride = stride; }
private cudnnPoolingMode TensorPoolTypeToCuDNNPoolType(Tensor.PoolType type) { if (type == Tensor.PoolType.Max) { return(cudnnPoolingMode.Max); } return(cudnnPoolingMode.AverageCountIncludePadding); }
public override void Pool(Tensor t, int filterSize, int stride, Tensor.PoolType type, int paddingX, int paddingY, Tensor result) { t.CopyToDevice(); result.CopyToDevice(); using (var poolingDesc = new PoolingDescriptor()) using (var tDesc = new TensorDescriptor()) using (var resultDesc = new TensorDescriptor()) { poolingDesc.SetPooling2dDescriptor(TensorPoolTypeToCuDNNPoolType(type), cudnnNanPropagation.NotPropagateNan, filterSize, filterSize, paddingX, paddingY, stride, stride); tDesc.SetTensor4dDescriptor(cudnnTensorFormat.NCHW, cudnnDataType.Float, t.Shape.Dimensions[3], t.Shape.Dimensions[2], t.Shape.Dimensions[1], t.Shape.Dimensions[0]); resultDesc.SetTensor4dDescriptor(cudnnTensorFormat.NCHW, cudnnDataType.Float, result.Shape.Dimensions[3], result.Shape.Dimensions[2], result.Shape.Dimensions[1], result.Shape.Dimensions[0]); _CudnnContext.PoolingForward(poolingDesc, 1.0f, tDesc, t.GpuData.DeviceVar, 0.0f, resultDesc, result.GpuData.DeviceVar); } }
public override void Pool(Tensor t, int filterSize, int stride, Tensor.PoolType type, int paddingX, int paddingY, Tensor result) { t.CopyToHost(); result.CurrentLocation = Tensor.Location.Host; Parallel.For(0, t.BatchSize, outN => { Parallel.For(0, t.Depth, outD => { for (int outH = 0, h = -paddingY; outH < result.Height; h += stride, ++outH) { for (int outW = 0, w = -paddingX; outW < result.Width; w += stride, ++outW) { if (type == Tensor.PoolType.Max) { float value = float.MinValue; for (int poolY = 0; poolY < filterSize; ++poolY) { for (int poolX = 0; poolX < filterSize; ++poolX) { value = Math.Max(value, t.TryGet(float.MinValue, w + poolX, h + poolY, outD, outN)); } } result[outW, outH, outD, outN] = value; } else if (type == Tensor.PoolType.Avg) { float sum = 0; for (int poolY = 0; poolY < filterSize; ++poolY) { for (int poolX = 0; poolX < filterSize; ++poolX) { sum += t.TryGet(0, w + poolX, h + poolY, outD, outN); } } result[outW, outH, outD, outN] = sum / (filterSize * filterSize); } } } }); }); }
public virtual void Pool(Tensor t, int filterSize, int stride, Tensor.PoolType type, int paddingX, int paddingY, Tensor result) { for (int outN = 0; outN < t.BatchSize; ++outN) { for (int outD = 0; outD < t.Depth; ++outD) { for (int outH = 0, h = -paddingY; outH < result.Height; h += stride, ++outH) { for (int outW = 0, w = -paddingX; outW < result.Width; w += stride, ++outW) { if (type == Tensor.PoolType.Max) { float value = float.MinValue; for (int poolY = 0; poolY < filterSize; ++poolY) { for (int poolX = 0; poolX < filterSize; ++poolX) { value = Math.Max(value, t.TryGet(float.MinValue, w + poolX, h + poolY, outD, outN)); } } result[outW, outH, outD, outN] = value; } else if (type == Tensor.PoolType.Avg) { float sum = 0; for (int poolY = 0; poolY < filterSize; ++poolY) { for (int poolX = 0; poolX < filterSize; ++poolX) { sum += t.TryGet(0, w + poolX, h + poolY, outD, outN); } } result[outW, outH, outD, outN] = sum / (filterSize * filterSize); } } } } } }
public override void PoolGradient(Tensor output, Tensor input, Tensor outputGradient, int filterSize, int stride, Tensor.PoolType type, int paddingX, int paddingY, Tensor result) { Parallel.For(0, output.BatchSize, outN => { Parallel.For(0, output.Depth, outD => { for (int outH = 0, h = -paddingY; outH < output.Height; ++outH, h += stride) { for (int outW = 0, w = -paddingX; outW < output.Width; ++outW, w += stride) { if (type == Tensor.PoolType.Max) { // use 1 for all elements equal to max value in each pooled matrix and 0 for all others for (int poolH = 0; poolH < filterSize; ++poolH) { for (int poolW = 0; poolW < filterSize; ++poolW) { float value = input.TryGet(Single.MinValue, w + poolW, h + poolH, outD, outN); result.TrySet(value == output[outW, outH, outD, outN] ? outputGradient.Get(outW, outH, outD, outN) : 0, w + poolW, h + poolH, outD, outN); } } } else if (type == Tensor.PoolType.Avg) { float filterElementsNum = filterSize * filterSize; for (int poolH = 0; poolH < filterSize; ++poolH) { for (int poolW = 0; poolW < filterSize; ++poolW) { result.TrySet(outputGradient[outW, outH, outD, outN] / filterElementsNum, w + poolW, h + poolH, outD, outN); } } } } } }); }); }
public virtual void PoolGradient(Tensor output, Tensor input, Tensor outputGradient, int filterSize, int stride, Tensor.PoolType type, int paddingX, int paddingY, Tensor result) { for (int outN = 0; outN < output.BatchSize; ++outN) { for (int outD = 0; outD < output.Depth; ++outD) { for (int outH = 0, h = -paddingY; outH < output.Height; ++outH, h += stride) { for (int outW = 0, w = -paddingX; outW < output.Width; ++outW, w += stride) { if (type == Tensor.PoolType.Max) { for (int poolH = 0; poolH < filterSize; ++poolH) { for (int poolW = 0; poolW < filterSize; ++poolW) { float value = input.TryGet(Single.MinValue, w + poolW, h + poolH, outD, outN); result.TrySet(value == output[outW, outH, outD, outN] ? outputGradient[outW, outH, outD, outN] : 0, w + poolW, h + poolH, outD, outN); } } } else if (type == Tensor.PoolType.Avg) { float filterElementsNum = filterSize * filterSize; for (int poolH = 0; poolH < filterSize; ++poolH) { for (int poolW = 0; poolW < filterSize; ++poolW) { result.TrySet(outputGradient[outW, outH, outD, outN] / filterElementsNum, w + poolW, h + poolH, outD, outN); } } } } } } } }
private LayerBase CreateLayer(Tensor.PoolType poolType) { return(new Pooling(new Shape(6, 6, 3), 2, 2, poolType)); }