maxPooling.py 3.82 KB
Newer Older
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
1
2
3
4
5
6
# Copyright 2016-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the license found in the
# LICENSE file in the root directory of this source tree.

7
import sparseconvnet.SCN
8
from torch.autograd import Function
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
9
10
11
12
from torch.nn import Module
from .utils import *
from .sparseConvNetTensor import SparseConvNetTensor

13

Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
14
15
16
17
18
19
20
21
22
23
24
25
class MaxPoolingFunction(Function):
    @staticmethod
    def forward(
            ctx,
            input_features,
            input_metadata,
            input_spatial_size,
            output_spatial_size,
            dimension,
            pool_size,
            pool_stride,
            nFeaturesToDrop):
26
        ctx.input_metadata = input_metadata
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
27
28
        ctx.dimension = dimension
        ctx.nFeaturesToDrop = nFeaturesToDrop
29
        output_features = input_features.new()
30
        sparseconvnet.SCN.MaxPooling_updateOutput(
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
31
32
33
34
            input_spatial_size,
            output_spatial_size,
            pool_size,
            pool_stride,
35
            input_metadata,
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
36
            input_features,
37
            output_features,
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
38
            nFeaturesToDrop)
39
40
41
42
43
44
45
46
        ctx.save_for_backward(
            input_features,
            output_features,
            input_spatial_size,
            output_spatial_size,
            pool_size,
            pool_stride)
        return output_features
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
47
48
49

    @staticmethod
    def backward(ctx, grad_output):
50
51
52
53
54
55
56
        input_features,\
            output_features,\
            input_spatial_size,\
            output_spatial_size,\
            pool_size,\
            pool_stride = ctx.saved_tensors
        grad_input = grad_output.new()
57
        sparseconvnet.SCN.MaxPooling_updateGradInput(
58
59
60
61
            input_spatial_size,
            output_spatial_size,
            pool_size,
            pool_stride,
62
            ctx.input_metadata,
63
64
65
66
            input_features,
            grad_input,
            output_features,
            grad_output,
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
67
            ctx.nFeaturesToDrop)
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
68
69
70
71
72
73
74
75
76
77
        return grad_input, None, None, None, None, None, None, None


class MaxPooling(Module):
    def __init__(self, dimension, pool_size, pool_stride, nFeaturesToDrop=0):
        super(MaxPooling, self).__init__()
        self.dimension = dimension
        self.pool_size = toLongTensor(dimension, pool_size)
        self.pool_stride = toLongTensor(dimension, pool_stride)
        self.nFeaturesToDrop = nFeaturesToDrop
78

Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
79
80
81
82
83
    def forward(self, input):
        output = SparseConvNetTensor()
        output.metadata = input.metadata
        output.spatial_size = (
            input.spatial_size - self.pool_size) / self.pool_stride + 1
84
85
86
87
88
89
90
91
92
93
        assert ((output.spatial_size - 1) * self.pool_stride +
                self.pool_size == input.spatial_size).all()
        output.features = MaxPoolingFunction.apply(
            input.features,
            input.metadata,
            input.spatial_size,
            output.spatial_size,
            self.dimension,
            self.pool_size,
            self.pool_stride,
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
94
95
            self.nFeaturesToDrop)
        return output
96

Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
97
98
    def input_spatial_size(self, out_size):
        return (out_size - 1) * self.pool_stride + self.pool_size
99

Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
100
101
    def __repr__(self):
        s = 'MaxPooling'
Benjamin Thomas Graham's avatar
tidy  
Benjamin Thomas Graham committed
102
103
        if self.pool_size.max().item() == self.pool_size.min().item() and\
                self.pool_stride.max().item() == self.pool_stride.min().item():
104
105
            s = s + str(self.pool_size[0].item()) + \
                '/' + str(self.pool_stride[0].item())
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
106
        else:
107
            s = s + '(' + str(self.pool_size[0].item())
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
108
            for i in self.pool_size[1:]:
Benjamin Thomas Graham's avatar
tidy  
Benjamin Thomas Graham committed
109
                s = s + ',' + str(i.item())
110
            s = s + ')/(' + str(self.pool_stride[0].item())
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
111
            for i in self.pool_stride[1:]:
Benjamin Thomas Graham's avatar
tidy  
Benjamin Thomas Graham committed
112
                s = s + ',' + str(i.item())
Benjamin Thomas Graham's avatar
Benjamin Thomas Graham committed
113
114
115
116
117
            s = s + ')'

        if self.nFeaturesToDrop > 0:
            s = s + ' nFeaturesToDrop = ' + self.nFeaturesToDrop
        return s