File: conv.py

package info (click to toggle)
pytorch 1.13.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 139,252 kB
  • sloc: cpp: 1,100,274; python: 706,454; ansic: 83,052; asm: 7,618; java: 3,273; sh: 2,841; javascript: 612; makefile: 323; xml: 269; ruby: 185; yacc: 144; objc: 68; lex: 44
file content (135 lines) | stat: -rw-r--r-- 5,050 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
## @package conv
# Module caffe2.python.layers.conv





from caffe2.python import schema
from caffe2.python.layers.layers import (
    ModelLayer,
)
import numpy as np


class Conv(ModelLayer):
    """
        Convolutional layer
        Input:
        - input_record: at least has the shape info of C (num_channels)
        - output_dim: number of convolutional filters
        - kernel_h, kernel_w: kernel size for h and w
        - stride_h, stride_w: stride for h and w
        - pad_b, pad_l, pad_r, pad_t: padding sizes, if stride == 1,
                                      'None' value will do auto padding
        - order: either 'NHWC' or 'NCHW'
    """

    def __init__(self, model, input_record, output_dim, kernel_h, kernel_w,
                 stride_h, stride_w, pad_b=None, pad_l=None, pad_r=None,
                 pad_t=None, order='NHWC', kernel_init=None, bias_init=None,
                 kernel_optim=None, bias_optim=None,
                 name='conv', **kwargs):

        super(Conv, self).__init__(model, name, input_record, **kwargs)
        assert isinstance(input_record, schema.Scalar), "Incorrect input type"
        # input num_channels (C) is needed
        input_dims = input_record.field_type().shape

        assert (kernel_h > 0 and isinstance(kernel_h, int)), (
            "kernel_h should be positive integer")
        assert (kernel_w > 0 and isinstance(kernel_w, int)), (
            "kernel_w should be positive integer")
        self.kernel_h = kernel_h
        self.kernel_w = kernel_w

        assert (stride_h > 0 and isinstance(stride_h, int)), (
            "stride_h should be positive integer")
        assert (stride_w > 0 and isinstance(stride_w, int)), (
            "stride_w should be positive integer")
        self.stride_h = stride_h
        self.stride_w = stride_w

        # output_dim calculation (http://cs231n.github.io/convolutional-networks/)
        # output_dim_w = (input_dim_w - kernel_w + pad_r + pad_l) / stride_w + 1
        # so, do auto_padding requires
        # pad_r, pad_l = [(input_dim_w - 1) * stride_w - input_dim_w + kernel_w] / 2
        # similair for pad_t and pad_b to auto pad kernel_h
        # here we only do auto padding for stride = 1 case
        if stride_h == 1:
            pad_t = int((kernel_h - 1) / 2) if pad_t is None else pad_t
            pad_b = int((kernel_h - 1) / 2) if pad_b is None else pad_b
        else:
            pad_t = 0 if pad_t is None else pad_t
            pad_b = 0 if pad_b is None else pad_b

        if stride_w == 1:
            pad_r = int((kernel_w - 1) / 2) if pad_r is None else pad_r
            pad_l = int((kernel_w - 1) / 2) if pad_l is None else pad_l
        else:
            pad_r = 0 if pad_r is None else pad_r
            pad_l = 0 if pad_l is None else pad_l

        assert (pad_t >= 0 and isinstance(pad_t, int)), "pad_t should be int >= 0"
        assert (pad_b >= 0 and isinstance(pad_b, int)), "pad_b should be int >= 0"
        assert (pad_r >= 0 and isinstance(pad_r, int)), "pad_r should be int >= 0"
        assert (pad_l >= 0 and isinstance(pad_l, int)), "pad_l should be int >= 0"
        self.pad_t = pad_t
        self.pad_b = pad_b
        self.pad_r = pad_r
        self.pad_l = pad_l

        assert order in ['NHWC', 'NCHW'], "order should either 'NHWC' or 'NCHW'"
        self.order = order

        if order == 'NHWC':
            input_c = input_dims[-1]
            kernel_shape = [output_dim, kernel_h, kernel_w, input_c]
        elif order == 'NCHW':
            input_c = input_dims[0]
            kernel_shape = [output_dim, input_c, kernel_h, kernel_w]
        assert input_c > 0, (
            "Number of input channels in conv parameters should be positive")

        kernel_init = kernel_init if kernel_init else (
            'XavierFill', {}
        )
        bias_init = bias_init if bias_init else (
            'ConstantFill', {'value': 0.0}
        )

        self.kernel = self.create_param(
            param_name='conv_kernel',
            shape=kernel_shape,
            initializer=kernel_init,
            optimizer=kernel_optim,
        )

        self.bias = self.create_param(
            param_name='conv_bias',
            shape=[output_dim],
            initializer=bias_init,
            optimizer=bias_optim,
        )

        # the output_schema only has the num of output channels
        # output_h and output_w would be inferred internally
        self.output_schema = schema.Scalar(
            (np.float32, (output_dim,)),
            self.get_next_blob_reference('output')
        )

    def add_ops(self, net):
        net.Conv(
            self.input_record.field_blobs() + [self.kernel, self.bias],
            self.output_schema.field_blobs(),
            kernel_h=self.kernel_h,
            kernel_w=self.kernel_w,
            stride_h=self.stride_h,
            stride_w=self.stride_w,
            pad_t=self.pad_t,
            pad_l=self.pad_l,
            pad_b=self.pad_b,
            pad_r=self.pad_r,
            order=self.order
        )