def v(depth, nPlanes): m = scn.Sequential() if depth == 1: for _ in range(reps): res(m, nPlanes, nPlanes, dropout_p) else: m = scn.Sequential() for _ in range(reps): res(m, nPlanes, nPlanes, dropout_p) if dropout_width: m.add(scn.ConcatTable().add(scn.Identity()).add( scn.Sequential().add(scn.BatchNormReLU(nPlanes)).add( #In place of Maxpooling scn.Convolution( dimension, nPlanes, nPlanes, 2, 2, False)).add(scn.Dropout(dropout_p)).add( v(depth - 1, nPlanes)).add( scn.BatchNormReLU(nPlanes)).add( scn.Deconvolution( dimension, nPlanes, nPlanes, 2, 2, False)))) else: m.add(scn.ConcatTable().add(scn.Identity()).add( scn.Sequential().add(scn.BatchNormReLU(nPlanes)).add( scn.Convolution(dimension, nPlanes, nPlanes, 2, 2, False)).add(v(depth - 1, nPlanes)).add( scn.BatchNormReLU(nPlanes)).add( scn.Deconvolution( dimension, nPlanes, nPlanes, 2, 2, False)))) m.add(scn.JoinTable()) for i in range(reps): res(m, 2 * nPlanes if i == 0 else nPlanes, nPlanes, dropout_p) return m
def block(self, nPlanes, n, reps, stride): m = scn.Sequential() for rep in range(reps): if rep == 0: m.add(scn.BatchNormReLU(nPlanes)) m.add(scn.ConcatTable().add(self.residual( nPlanes, n, stride)).add(scn.Sequential().add( scn.SubmanifoldConvolution(self.dimension, nPlanes, n, 3, False) if stride == 1 else scn.Convolution( self.dimension, nPlanes, n, 2, stride, False)).add( scn.BatchNormReLU(n)).add( scn.SubmanifoldConvolution( self.dimension, n, n, 3, False)))) else: m.add(scn.ConcatTable().add(scn.Sequential().add( scn.BatchNormReLU(nPlanes)).add( scn.SubmanifoldConvolution( self.dimension, nPlanes, n, 3, False)).add(scn.BatchNormReLU(n)).add( scn.SubmanifoldConvolution( self.dimension, n, n, 3, False))).add(scn.Identity())) m.add(scn.AddTable()) nPlanes = n return m
def SparseResNet(dimension, nInputPlanes, layers): import sparseconvnet as scn """ pre-activated ResNet e.g. layers = {{'basic',16,2,1},{'basic',32,2}} """ nPlanes = nInputPlanes m = scn.Sequential() def residual(nIn, nOut, stride): if stride > 1: return scn.Convolution(dimension, nIn, nOut, 2, stride, False) elif nIn != nOut: return scn.NetworkInNetwork(nIn, nOut, False) else: return scn.Identity() for n, reps, stride in layers: for rep in range(reps): if rep == 0: m.add(scn.BatchNormReLU(nPlanes)) tab = scn.ConcatTable() tab_seq = scn.Sequential() if stride == 1: tab_seq.add( scn.SubmanifoldConvolution(dimension, nPlanes, n, 3, False)) else: tab_seq.add( scn.Convolution(dimension, nPlanes, n, 2, stride, False)) tab_seq.add(scn.BatchNormReLU(n)) tab_seq.add( scn.SubmanifoldConvolution(dimension, n, n, 3, False)) tab.add(tab_seq) tab.add(residual(nPlanes, n, stride)) m.add(tab) else: tab = scn.ConcatTable() tab_seq = scn.Sequential() tab_seq.add(scn.BatchNormReLU(nPlanes)) tab_seq.add( scn.SubmanifoldConvolution(dimension, nPlanes, n, 3, False)) tab_seq.add(scn.BatchNormReLU(n)) tab_seq.add( scn.SubmanifoldConvolution(dimension, n, n, 3, False)) tab.add(tab_seq) tab.add(scn.Identity()) m.add(tab) nPlanes = n m.add(scn.AddTable()) m.add(scn.BatchNormReLU(nPlanes)) return m
def block(self, m, a, b, dimension=3, residual_blocks=False, leakiness=0, kernel_size=3, use_batch_norm=True): # default using residual_block if use_batch_norm: Activation = lambda channels: scn.BatchNormLeakyReLU( channels, leakiness=leakiness) else: Activation = lambda channels: scn.LeakyReLU(leakiness) if residual_blocks: #ResNet style blocks m.add(scn.ConcatTable().add(scn.Identity( ) if a == b else scn.NetworkInNetwork(a, b, False)).add( scn.Sequential().add(Activation(a)).add( scn.SubmanifoldConvolution(dimension, a, b, kernel_size, False)).add(Activation(b)).add( scn.SubmanifoldConvolution( dimension, b, b, kernel_size, False)))).add( scn.AddTable()) else: #VGG style blocks m.add(scn.Sequential().add(Activation(a)).add( scn.SubmanifoldConvolution(dimension, a, b, kernel_size, False)))
def block(self, n_in, n_out): m = scn.Sequential() if self.residual_blocks: # ResNet style blocks m.add(scn.ConcatTable().add( scn.Identity() if n_in == n_out else scn.NetworkInNetwork(n_in, n_out, False)).add( scn.Sequential().add( scn.BatchNormLeakyReLU( n_in, leakiness=self.leakiness)).add( scn.SubmanifoldConvolution( self.dimension, n_in, n_out, 3, False)).add( scn.BatchNormLeakyReLU( n_out, leakiness=self.leakiness)).add( scn.SubmanifoldConvolution( self.dimension, n_out, n_out, 3, False)))) m.add(scn.AddTable()) else: # VGG style blocks m.add(scn.BatchNormLeakyReLU(n_in, leakiness=self.leakiness)) m.add( scn.SubmanifoldConvolution(self.dimension, n_in, n_out, 3, False)) return m
def sparse_residual(inner_block, residual_changer, activation): layer = scn.Sequential( scn.ConcatTable(residual_changer, inner_block), scn.AddTable()) if activation is not None: layer.append(activation) return layer
def MultiscaleShapeContext(dimension, n_features=1, n_layers=3, shape_context_size=3, downsample_size=2, downsample_stride=2, bn=True): m = sparseconvnet.Sequential() if n_layers == 1: m.add( sparseconvnet.ShapeContext(dimension, n_features, shape_context_size)) else: m.add(sparseconvnet.ConcatTable().add( sparseconvnet.ShapeContext( dimension, n_features, shape_context_size)).add( sparseconvnet.Sequential( sparseconvnet.AveragePooling(dimension, downsample_size, downsample_stride), MultiscaleShapeContext(dimension, n_features, n_layers - 1, shape_context_size, downsample_size, downsample_stride, False), sparseconvnet.UnPooling(dimension, downsample_size, downsample_stride)))).add( sparseconvnet.JoinTable()) if bn: m.add( sparseconvnet.BatchNormalization(shape_context_size**dimension * n_features * n_layers)) return m
def U(nPlanes, n_input_planes=-1): #Recursive function m = scn.Sequential() for i in range(reps): block(m, n_input_planes if n_input_planes != -1 else nPlanes[0], nPlanes[0]) n_input_planes = -1 if len(nPlanes) > 1: m.add(scn.ConcatTable().add(scn.Identity()).add( scn.Sequential().add( scn.BatchNormLeakyReLU( nPlanes[0], leakiness=leakiness)).add( scn.Convolution(dimension, nPlanes[0], nPlanes[1], downsample[0], downsample[1], False)).add(U(nPlanes[1:])).add( scn.BatchNormLeakyReLU( nPlanes[1], leakiness=leakiness)).add( scn.Deconvolution( dimension, nPlanes[1], nPlanes[0], downsample[0], downsample[1], False)))) m.add(scn.JoinTable()) for i in range(reps): block(m, nPlanes[0] * (2 if i == 0 else 1), nPlanes[0]) return m
def residual_block(m, ninputchs, noutputchs, leakiness=0.01, dimensions=2): """ Residual Modulae Block intention is to append to a sequence module (m) produce output of [identity,3x3+3x3] then add together inputs ------ m [scn.Sequential module] network to add layers to ninputchs [int]: number of input channels noutputchs [int]: number of output channels leakiness [float]: leakiness of ReLU activations dimensions [int]: dimensions of input sparse tensor modifies -------- m: adds layers """ inoutsame = ninputchs == noutputchs m.add(scn.ConcatTable().add( scn.Identity() if inoutsame else scn. NetworkInNetwork(ninputchs, noutputchs, False)).add( scn.Sequential().add( scn.BatchNormLeakyReLU(ninputchs, leakiness=leakiness)).add( scn.SubmanifoldConvolution( dimensions, ninputchs, noutputchs, 3, False)).add( scn.BatchNormLeakyReLU( noutputchs, leakiness=leakiness)).add( scn.SubmanifoldConvolution( dimensions, noutputchs, noutputchs, 3, False)))).add(scn.AddTable())
def block(m, a, b): if residual_blocks: #ResNet style blocks m.add(scn.ConcatTable().add(scn.Identity( ) if a == b else scn.NetworkInNetwork(a, b, False)).add( scn.Sequential().add( scn.BatchNormLeakyReLU( a, momentum=bn_momentum, leakiness=leakiness, track_running_stats=track_running_stats) ).add(scn.SubmanifoldConvolution( dimension, a, b, 3, False)).add( scn.BatchNormLeakyReLU( b, momentum=bn_momentum, leakiness=leakiness, track_running_stats=track_running_stats)).add( scn.SubmanifoldConvolution( dimension, b, b, 3, False)))).add(scn.AddTable()) else: #VGG style blocks m.add(scn.Sequential().add( scn.BatchNormLeakyReLU( a, momentum=bn_momentum, leakiness=leakiness, track_running_stats=track_running_stats)).add( scn.SubmanifoldConvolution(dimension, a, b, 3, False))) operation = {'kernel': [1, 1, 1], 'stride': [1, 1, 1]} return operation
def __init__(self, nf_in, nf, input_sparsetensor, return_sparsetensor, max_data_size): nn.Module.__init__(self) data_dim = 3 self.nf_in = nf_in self.nf = nf self.input_sparsetensor = input_sparsetensor self.return_sparsetensor = return_sparsetensor self.max_data_size = max_data_size if not self.input_sparsetensor: self.p0 = scn.InputLayer(data_dim, self.max_data_size, mode=0) self.p1 = scn.SubmanifoldConvolution(data_dim, nf_in, nf, filter_size=FSIZE0, bias=False) self.p2 = scn.Sequential() self.p2.add(scn.ConcatTable().add(scn.Identity()).add( scn.Sequential().add(scn.BatchNormReLU(nf)).add( scn.SubmanifoldConvolution( data_dim, nf, nf, FSIZE0, False)).add(scn.BatchNormReLU(nf)).add( scn.SubmanifoldConvolution(data_dim, nf, nf, FSIZE0, False)))).add( scn.AddTable()) self.p2.add(scn.BatchNormReLU(nf)) # downsample space by factor of 2 self.p3 = scn.Sequential().add( scn.Convolution(data_dim, nf, nf, FSIZE1, 2, False)) self.p3.add(scn.BatchNormReLU(nf)) if not self.return_sparsetensor: self.p4 = scn.SparseToDense(data_dim, nf)
def residual_block(m, a, b, leakiness=0.01, dimensions=2): """ append to a sequence module: produce output of [identity,3x3+3x3] then add together inputs ------ m [scn.Sequential module] network to add layers to a [int]: number of input channels b [int]: number of output channels leakiness [float]: leakiness of ReLU activations dimensions [int]: dimensions of input sparse tensor modifies -------- m: adds layers """ m.add(scn.ConcatTable().add(scn.Identity( ) if a == b else scn.NetworkInNetwork(a, b, False)).add( scn.Sequential().add(scn.BatchNormLeakyReLU( a, leakiness=leakiness)).add( scn.SubmanifoldConvolution(dimensions, a, b, 3, False)).add( scn.BatchNormLeakyReLU(b, leakiness=leakiness)).add( scn.SubmanifoldConvolution( dimensions, b, b, 3, False)))).add(scn.AddTable())
def SparseResNet(dimension, nInputPlanes, layers, mom=0.99): """ pre-activated ResNet e.g. layers = {{'basic',16,2,1},{'basic',32,2}} """ nPlanes = nInputPlanes m = scn.Sequential() def residual(nIn, nOut, stride): if stride > 1: return scn.Convolution(dimension, nIn, nOut, 3, stride, False) elif nIn != nOut: return scn.NetworkInNetwork(nIn, nOut, False) else: return scn.Identity() for blockType, n, reps, stride in layers: for rep in range(reps): if blockType[0] == 'b': # basic block if rep == 0: m.add(scn.BatchNormReLU(nPlanes, momentum=mom, eps=1e-5)) m.add(scn.ConcatTable().add(scn.Sequential().add( scn.SubmanifoldConvolution(dimension, nPlanes, n, 3, False) if stride == 1 else scn.Convolution( dimension, nPlanes, n, 3, stride, False)).add( scn.BatchNormReLU( n, momentum=mom, eps=1e-5)).add( scn.SubmanifoldConvolution( dimension, n, n, 3, False))).add( residual(nPlanes, n, stride))) else: m.add(scn.ConcatTable().add(scn.Sequential().add( scn.BatchNormReLU( nPlanes, momentum=mom, eps=1e-5)).add( scn.SubmanifoldConvolution( dimension, nPlanes, n, 3, False)).add( scn.BatchNormReLU( n, momentum=mom, eps=1e-5)).add( scn.SubmanifoldConvolution( dimension, n, n, 3, False))).add( scn.Identity())) nPlanes = n m.add(scn.AddTable()) m.add(scn.BatchNormReLU(nPlanes, momentum=mom, eps=1e-5)) return m
def block(m, a, b): # ResNet style blocks m.add(scn.ConcatTable() .add(scn.Identity() if a == b else scn.NetworkInNetwork(a, b, False)) .add(scn.Sequential() .add(scn.BatchNormLeakyReLU(a, leakiness=leakiness)) .add(scn.SubmanifoldConvolution(self._dimension, a, b, 3, False)) .add(scn.BatchNormLeakyReLU(b, leakiness=leakiness)) .add(scn.SubmanifoldConvolution(self._dimension, b, b, 3, False))) ).add(scn.AddTable())
def __init__(self, *, inplanes, params): nn.Module.__init__(self) self.concat = scn.ConcatTable() self.bottleneck = scn.SubmanifoldConvolution(3, nIn=2 * inplanes, nOut=inplanes, filter_size=1, bias=params.use_bias)
def res(m, dimension, a, b): m.add(scn.ConcatTable() .add(scn.Identity() if a == b else scn.NetworkInNetwork(a, b, False)) .add(scn.Sequential() .add(scn.BatchNormReLU(a)) .add(scn.SubmanifoldConvolution(dimension, a, b, 3, False)) .add(scn.BatchNormReLU(b)) .add(scn.SubmanifoldConvolution(dimension, b, b, 3, False))))\ .add(scn.AddTable())
def baz(depth, nPlanes): if depth == 1: return scn.Sequential().add(foo(nPlanes)).add(bar(nPlanes, True)) else: return scn.Sequential().add(foo(nPlanes)).add(scn.ConcatTable().add(bar(nPlanes,False)).add( scn.Sequential()\ .add(scn.BatchNormReLU(nPlanes))\ .add(scn.Convolution(dimension, nPlanes, l(nPlanes), 2, 2, False))\ .add(baz(depth-1,l(nPlanes)))\ .add(scn.UnPooling(dimension, 2, 2)) )).add(scn.AddTable())
def f(m, a, b): m.add(scn.ConcatTable().add(scn.Identity( ) if a == b else scn.NetworkInNetwork(a, b, self.allow_bias)).add( scn.Sequential().add(norm_layer( a, leakiness=self.leakiness)).add( scn.SubmanifoldConvolution( self.dimension, a, b, 3, self.allow_bias)).add( norm_layer(b, leakiness=self.leakiness)).add( scn.SubmanifoldConvolution( self.dimension, b, b, 3, self.allow_bias)))).add(scn.AddTable()) return m
def block(m, a, b): if residual_blocks: #ResNet style blocks m.add(scn.ConcatTable().add(scn.Identity( ) if a == b else scn.NetworkInNetwork(a, b, False)).add( scn.Sequential().add(scn.BatchNormReLU(a)).add( scn.SubmanifoldConvolution(dimension, a, b, 3, False)).add( scn.BatchNormReLU(b)).add( scn.SubmanifoldConvolution(dimension, b, b, 3, False)))).add( scn.AddTable()) else: #VGG style blocks m.add(scn.Sequential().add(scn.BatchNormReLU(a)).add( scn.SubmanifoldConvolution(dimension, a, b, 3, False)))
def decoder_block(self, nPlanes, n, reps, stride): m = scn.Sequential() for rep in range(reps): m.add(scn.ConcatTable().add( scn.Sequential().add(scn.BatchNormReLU(nPlanes)).add( scn.SubmanifoldConvolution(self.dimension, nPlanes, n, 3, False)) # .add(scn.BatchNormReLU(n)) # .add(scn.SubmanifoldConvolution(dimension, n, n, 3, False)) ).add(scn.Identity())) m.add(scn.AddTable()) nPlanes = n return m
def foo(m,np): for _ in range(reps): if residual: #ResNet style blocks m.add(scn.ConcatTable() .add(scn.Identity()) .add(scn.Sequential() .add(scn.BatchNormLeakyReLU(np,leakiness=leakiness)) .add(scn.SubmanifoldConvolution(dimension, np, np, 3, False)) .add(scn.BatchNormLeakyReLU(np,leakiness=leakiness)) .add(scn.SubmanifoldConvolution(dimension, np, np, 3, False))) ).add(scn.AddTable()) else: #VGG style blocks m.add(scn.BatchNormLeakyReLU(np,leakiness=leakiness) ).add(scn.SubmanifoldConvolution(dimension, np, np, 3, False))
def block(self, m, a, b, dimension=3, residual_blocks=False, leakiness=0): # default using residual_block if residual_blocks: #ResNet style blocks m.add(scn.ConcatTable() .add(scn.Identity() if a == b else scn.NetworkInNetwork(a, b, False)) .add(scn.Sequential() .add(scn.BatchNormLeakyReLU(a,leakiness=leakiness)) .add(scn.SubmanifoldConvolution(dimension, a, b, 3, False)) .add(scn.BatchNormLeakyReLU(b,leakiness=leakiness)) .add(scn.SubmanifoldConvolution(dimension, b, b, 3, False))) ).add(scn.AddTable()) else: #VGG style blocks m.add(scn.Sequential() .add(scn.BatchNormLeakyReLU(a,leakiness=leakiness)) .add(scn.SubmanifoldConvolution(dimension, a, b, 3, False)))
def baz(depth, nPlanes): m = scn.Sequential() foo(m, nPlanes[0]) if len(nPlanes) == 1: bar(m, nPlanes[0], True) else: a = scn.Sequential() bar(a, nPlanes, False) b = scn.Sequential( scn.BatchNormLeakyReLU(nPlanes, leakiness=leakiness), scn.Convolution(dimension, nPlanes[0], nPlanes[1], downsample[0], downsample[1], False), baz(nPlanes[1:]), scn.UnPooling(dimension, downsample[0], downsample[1])) m.add(scn.ConcatTable(a, b)) m.add(scn.AddTable()) return baz(depth, nPlanes)
def U(nPlanes): #Recursive function m = scn.Sequential() if len(nPlanes) == 1: for _ in range(reps): block(m, nPlanes[0], nPlanes[0]) else: m = scn.Sequential() for _ in range(reps): block(m, nPlanes[0], nPlanes[0]) m.add(scn.ConcatTable().add(scn.Identity()).add( scn.Sequential().add(scn.BatchNormReLU(nPlanes[0])).add( scn.Convolution(dimension, nPlanes[0], nPlanes[1], downsample[0], downsample[1], False)).add(U(nPlanes[1:])).add( scn.UnPooling(dimension, downsample[0], downsample[1])))) m.add(scn.JoinTable()) return m
def resnet_block(dimension, n_in, n_out, kernel, leakiness=0, computation='convolution'): '''Build and return ResNet block ''' assert computation in [ 'submanifoldconvolution', 'convolution', 'fullconvolution', 'deconvolution' ] if computation == 'convolution': computation = lambda n_in, n_out: scn.Convolution( dimension, n_in, n_out, kernel[0], kernel[1], False) elif computation == 'submanifoldconvolution': assert type( kernel ) == int, f"`kernel` must be int, {type(kernel)} was provided" computation = lambda n_in, n_out: scn.SubmanifoldConvolution( dimension, n_in, n_out, kernel, False) elif computation == 'deconvolution': assert type( kernel ) == int, f"`kernel` must be int, {type(kernel)} was provided" computation = lambda n_in, n_out: scn.Deconvolution( dimension, n_in, n_out, kernel, kernel, False) else: computation = lambda n_in, n_out: scn.FullConvolution( dimension, n_in, n_out, kernel[0], kernel[1], False) block = scn.Sequential() block.add(scn.ConcatTable( ).add(scn.NetworkInNetwork(n_in, n_out, False)).add(scn.Sequential().add( # scn.BatchNormLeakyReLU(n_in, leakiness=leakiness) scn.LeakyReLU(leakiness)).add(computation(n_in, n_out)).add( # scn.BatchNormLeakyReLU(n_out, leakiness=leakiness) scn.LeakyReLU(leakiness)).add(computation(n_out, n_out)))).add( scn.AddTable()) return block
def _resnet_block(self, module, a, b): ''' Utility Method for attaching ResNet-Style Blocks. INPUTS: - module (scn Module): network module to attach ResNet block. - a (int): number of input feature dimension - b (int): number of output feature dimension RETURNS: None (operation is in-place) ''' module.add(scn.ConcatTable().add(scn.Identity( ) if a == b else scn.NetworkInNetwork(a, b, self.allow_bias)).add( scn.Sequential().add( scn.BatchNormLeakyReLU(a, leakiness=self.leakiness)).add( scn.SubmanifoldConvolution( self.dimension, a, b, 3, self.allow_bias)).add( scn.BatchNormLeakyReLU( b, leakiness=self.leakiness)).add( scn.SubmanifoldConvolution( self.dimension, b, b, 3, self.allow_bias)))).add(scn.AddTable())
def SparseVggNet(dimension, nInputPlanes, layers): """ VGG style nets Use submanifold convolutions Also implements 'Plus'-augmented nets """ nPlanes = nInputPlanes m = scn.Sequential() for x in layers: if x == 'MP': m.add(scn.MaxPooling(dimension, 3, 2)) elif x[0] == 'MP': m.add(scn.MaxPooling(dimension, x[1], x[2])) elif x == 'C3/2': m.add(scn.Convolution(dimension, nPlanes, nPlanes, 3, 2, False)) m.add(scn.BatchNormReLU(nPlanes)) elif x[0] == 'C3/2': m.add(scn.Convolution(dimension, nPlanes, x[1], 3, 2, False)) nPlanes = x[1] m.add(scn.BatchNormReLU(nPlanes)) elif x[0] == 'C' and len(x) == 2: m.add( scn.SubmanifoldConvolution(dimension, nPlanes, x[1], 3, False)) nPlanes = x[1] m.add(scn.BatchNormReLU(nPlanes)) elif x[0] == 'C' and len(x) == 3: m.add(scn.ConcatTable().add( scn.SubmanifoldConvolution( dimension, nPlanes, x[1], 3, False)).add(scn.Sequential().add( scn.Convolution( dimension, nPlanes, x[2], 3, 2, False)).add(scn.BatchNormReLU(x[2])).add( scn.SubmanifoldConvolution( dimension, x[2], x[2], 3, False)).add(scn.BatchNormReLU(x[2])).add( scn.Deconvolution( dimension, x[2], x[2], 3, 2, False)))).add(scn.JoinTable()) nPlanes = x[1] + x[2] m.add(scn.BatchNormReLU(nPlanes)) elif x[0] == 'C' and len(x) == 4: m.add(scn.ConcatTable().add( scn.SubmanifoldConvolution( dimension, nPlanes, x[1], 3, False)).add(scn.Sequential().add( scn.Convolution( dimension, nPlanes, x[2], 3, 2, False)).add(scn.BatchNormReLU(x[2])).add( scn.SubmanifoldConvolution( dimension, x[2], x[2], 3, False)).add(scn.BatchNormReLU(x[2])).add( scn.Deconvolution( dimension, x[2], x[2], 3, 2, False))). add(scn.Sequential().add( scn.Convolution( dimension, nPlanes, x[3], 3, 2, False)).add(scn.BatchNormReLU(x[3])).add( scn.SubmanifoldConvolution( dimension, x[3], x[3], 3, False)).add(scn.BatchNormReLU(x[3])).add( scn.Convolution(dimension, x[3], x[3], 3, 2, False)). add(scn.BatchNormReLU(x[3])).add( scn.SubmanifoldConvolution( dimension, x[3], x[3], 3, False)).add(scn.BatchNormReLU(x[3])).add( scn.Deconvolution( dimension, x[3], x[3], 3, 2, False)).add(scn.BatchNormReLU(x[3])).add( scn.SubmanifoldConvolution( dimension, x[3], x[3], 3, False)).add( scn.BatchNormReLU(x[3])).add( scn.Deconvolution( dimension, x[3], x[3], 3, 2, False)))).add( scn.JoinTable()) nPlanes = x[1] + x[2] + x[3] m.add(scn.BatchNormReLU(nPlanes)) elif x[0] == 'C' and len(x) == 5: m.add(scn.ConcatTable().add( scn.SubmanifoldConvolution( dimension, nPlanes, x[1], 3, False)).add(scn.Sequential().add( scn.Convolution( dimension, nPlanes, x[2], 3, 2, False)).add(scn.BatchNormReLU(x[2])).add( scn.SubmanifoldConvolution( dimension, x[2], x[2], 3, False)).add(scn.BatchNormReLU(x[2])).add( scn.Deconvolution( dimension, x[2], x[2], 3, 2, False))). add(scn.Sequential().add( scn.Convolution( dimension, nPlanes, x[3], 3, 2, False)).add(scn.BatchNormReLU(x[3])).add( scn.SubmanifoldConvolution( dimension, x[3], x[3], 3, False)).add(scn.BatchNormReLU(x[3])).add( scn.Convolution(dimension, x[3], x[3], 3, 2, False)). add(scn.BatchNormReLU(x[3])).add( scn.SubmanifoldConvolution( dimension, x[3], x[3], 3, False)).add(scn.BatchNormReLU(x[3])).add( scn.Deconvolution( dimension, x[3], x[3], 3, 2, False)).add(scn.BatchNormReLU(x[3])).add( scn.SubmanifoldConvolution( dimension, x[3], x[3], 3, False)).add( scn.BatchNormReLU(x[3])).add( scn.Deconvolution( dimension, x[3], x[3], 3, 2, False))). add(scn.Sequential().add( scn.Convolution( dimension, nPlanes, x[4], 3, 2, False)).add(scn.BatchNormReLU(x[4])).add( scn.SubmanifoldConvolution( dimension, x[4], x[4], 3, False)).add(scn.BatchNormReLU(x[4])).add( scn.Convolution( dimension, x[4], x[4], 3, 2, False)).add( scn.BatchNormReLU(x[4])).add( scn.SubmanifoldConvolution( dimension, x[4], x[4], 3, False)).add( scn.BatchNormReLU( x[4])). add(scn.Convolution( dimension, x[4], x[4], 3, 2, False)).add(scn.BatchNormReLU(x[4])).add( scn.SubmanifoldConvolution( dimension, x[4], x[4], 3, False)).add(scn.BatchNormReLU(x[4])).add( scn.Deconvolution( dimension, x[4], x[4], 3, 2, False)).add( scn.BatchNormReLU(x[4])).add( scn.SubmanifoldConvolution( dimension, x[4], x[4], 3, False)). add(scn.BatchNormReLU(x[4])).add( scn.Deconvolution( dimension, x[4], x[4], 3, 2, False)).add(scn.BatchNormReLU(x[4])).add( scn.SubmanifoldConvolution( dimension, x[4], x[4], 3, False)).add(scn.BatchNormReLU(x[4])).add( scn.Deconvolution( dimension, x[4], x[4], 3, 2, False)))).add(scn.JoinTable()) nPlanes = x[1] + x[2] + x[3] + x[4] m.add(scn.BatchNormReLU(nPlanes)) return m