88
99class BackwardsConvolutionCUDNN (df .Module ):
1010 def __init__ (self , nchan_in , nchan_out , filter_size , stride = 1 , border = 0 , mode = 'cross' , init = df .init .xavier (), bias = df .init .const (0 )):
11- # mode='cross' is the default in Lasagne[1], Torch[2], matConvNet[3], Caffee[4].
12- #
13- # 1: https://github.com/Lasagne/Lasagne/blob/63d44a0d/lasagne/layers/dnn.py#L299
14- # 2: https://github.com/soumith/cudnn.torch/blob/840f0228/SpatialConvolution.lua#L83
15- # 3: https://github.com/vlfeat/matconvnet/blob/b7dd9c96/matlab/src/bits/impl/nnconv_cudnn.cu#L133
16- # 4: https://github.com/BVLC/caffe/blob/50ab52cb/include/caffe/util/cudnn.hpp#L104
11+ """
12+ This is the backwards path through a convolution, sometimes is also
13+ referred to as transposed convolution and (wrongly) deconvolution.
14+
15+ This is usually used for upsampling an image. If you want the exact
16+ counterpart to another convolution earlier part of your model, consider
17+ using the `backward` function with that convolution instead.
18+
19+ - `nchan_in`: number of channels in the input.
20+ - `nchan_out`: number of filters and thus channels in the output.
21+ - `filter_size`: 2D or 3D tuple describing the filter size.
22+ - `stride`: the stride "dilates" the output, i.e. makes it larger.
23+ - `border`: The counterpart to `border` in forward convolution. This
24+ effectively crops the output, as opposed to padding it.
25+ - `mode`: `'cross'` or `'conv'`, see forward convolution documentation.
26+ - `init`: initializer for the weights/filters.
27+ - `bias`: initializer for the bias, or `None` or `False`.
28+ """
1729 df .Module .__init__ (self )
1830 self .nchan_in = nchan_in
1931 self .nchan_out = nchan_out
@@ -39,14 +51,15 @@ def __init__(self, nchan_in, nchan_out, filter_size, stride=1, border=0, mode='c
3951
4052
4153 def symb_forward (self , symb_input ):
42- """ creates dummy forward conv and uses its gradient as backwards pass """
43- """ This code is mostly taken from https://github.com/Newmu/dcgan_code/blob/master/lib/ops.py """
54+ # Calls directly into CUDNN's gradient methods to insert a backward-conv Op.
55+ # This code is originally taken from https://github.com/Newmu/dcgan_code/blob/master/lib/ops.py
56+ # and extended to more complex scenarios (stride, border)
4457 img = gpu_contiguous (symb_input )
4558 kerns = gpu_contiguous (self .W .param )
4659
47- alloc_shape = (img .shape [0 ], kerns .shape [1 ]) + tuple (i * d for i ,d in zip (img .shape [2 :],self .stride ))
48- desc = dnn .GpuDnnConvDesc (border_mode = self .border , subsample = self .stride , conv_mode = self .mode )(gpu_alloc_empty (* alloc_shape ).shape , kerns .shape )
60+ alloc_shape = (img .shape [0 ], self .nchan_out ) + tuple ((i - 1 )* s - 2 * b + f for i ,s ,b ,f in zip (img .shape [2 :], self .stride , self .border , self .filter_size ))
4961 out = gpu_alloc_empty (* alloc_shape )
62+ desc = dnn .GpuDnnConvDesc (border_mode = self .border , subsample = self .stride , conv_mode = self .mode )(out .shape , kerns .shape )
5063 grad = dnn .GpuDnnConv3dGradI if symb_input .ndim == 5 else dnn .GpuDnnConvGradI
5164 conv_output = grad ()(kerns , img , out , desc )
5265
0 commit comments