def upsample_merge(n, data, to_upsample, width, iters): deconv = L.Deconvolution(to_upsample, convolution_param=dict(num_output=width, kernel_size=2, stride=2, weight_filler=get_filler(), bias_filler=dict([ ('type', 'constant'), ('value', 0) ])), param=[{ "lr_mult": 1, "decay_mult": 1 }, { "lr_mult": 2, "decay_mult": 0 }]) prelu = L.PReLU(deconv) concat = L.Concat(data, prelu) netset(n, "concat_up_" + str(width), concat) left = left_branch(concat, width * 2, iters) netset(n, "left_branch_up_" + str(width), left) eltwise = L.Eltwise(concat, left, operation=P.Eltwise.SUM) netset(n, "elementwise_up_" + str(width), eltwise) return L.PReLU(eltwise, in_place=True)
def make_downsample(n, width, iters, data): conv = make_conv(data, width, 2, 0, 2) prelu = L.PReLU(conv, in_place=True) # left conv = left_branch(prelu, width, iters) eltwise = L.Eltwise(prelu, conv, operation=P.Eltwise.SUM) netset(n, "elementwise_down_" + str(width), eltwise) return L.PReLU(eltwise, in_place=True)
def densenet(nlayer, nclass, first_nout=16, growth_rate=16, dropout=0.2): net = caffe.NetSpec() net.data = L.Input(input_param=dict(shape=dict(dim=[1, 3, 224, 224]))) pre_fmap = 0 # total number of previous feature maps # first convolution -------------------------------------------------------- net.conv_1 = L.Convolution(net.data, num_output=first_nout, kernel_size=7, stride=2, pad=3) net.relu_1 = L.PReLU(net.conv_1, in_place=True) net.pool_1 = L.Pooling(net.relu_1, pool=P.Pooling.MAX, kernel_size=3, stride=2) pre_layer = net.pool_1 pre_fmap += first_nout # DB + TD ------------------------------------------------------------------ # +1 in order to make the index values from 1 for major in xrange(len(nlayer) - 1): # DB for minor in xrange(nlayer[major]): pre_layer = cat_layer(net, major + 1, minor + 1, pre_layer, growth_rate, dropout) pre_fmap += growth_rate # TD pre_layer = transition_down(net, major + 1, pre_layer, pre_fmap, dropout) pre_fmap = pre_fmap // 2 # last DB, without TD major = len(nlayer) for minor in xrange(nlayer[-1]): pre_layer = cat_layer(net, major, minor + 1, pre_layer, growth_rate, dropout) pre_fmap += growth_rate # final layers ------------------------------------------------------------- net.bn_final = L.BatchNorm(pre_layer, in_place=False, batch_norm_param=dict(use_global_stats=True)) net.scale_finel = L.Scale(net.bn_final, bias_term=True, in_place=True) net.relu_final = L.PReLU(net.scale_finel, in_place=True) net.pool_final = L.Pooling(net.relu_final, pool=P.Pooling.AVE, global_pooling=True) net.fc_class = L.InnerProduct(net.pool_final, num_output=nclass) return str(net.to_proto())
def resUnit2(bottom, kernelSize=3, numberOfOutput=16, stride=1, pad=1): bn1 = L.BatchNorm(bottom) relu1 = L.PReLU(bn1) conv1 = L.Convolution(relu1, convolution_param={"engine": 2, "kernel_size": kernelSize, "stride": stride, "num_output": numberOfOutput, "pad": pad, "group": 1}) bn2 = L.BatchNorm(conv1) relu2 = L.PReLU(bn2) conv2 = L.Convolution(relu2, convolution_param={"engine": 2, "kernel_size": kernelSize, "stride": stride, "num_output": numberOfOutput, "pad": pad, "group": 1}) add = L.Eltwise(bottom, conv2) return bn1, relu1, conv1, bn2, relu2, conv2, add
def add_block_1x1_3x3_1x1_bn(self, bottom, num_output): model = self.conv(bottom, num_output, kernel_size=1, pad=0) model = L.BatchNorm(model, use_global_stats=False, in_place=True) model = L.Scale(model, bias_term=True, in_place=True) model = L.PReLU(model, in_place=True) model = self.conv(model, num_output) model = L.BatchNorm(model, use_global_stats=False, in_place=True) model = L.Scale(model, bias_term=True, in_place=True) model = L.PReLU(model, in_place=True) model = self.conv(model, num_output * 4, kernel_size=1, pad=0) model = L.BatchNorm(model, use_global_stats=False, in_place=True) model = L.Scale(model, bias_term=True, in_place=True) model = L.PReLU(model, in_place=True) output = L.Eltwise(bottom, model, eltwise_param=dict(operation=1)) return output
def test_prelu(): # type: ()->caffe.NetSpec n = caffe.NetSpec() n.input1 = L.Input(shape=make_shape([10, 4, 64, 64])) n.relu1 = L.PReLU(n.input1) return n
def bn_relu_conv(net, flag, bottom, ks, nout, stride, pad, dropout): suffix = '{}x{}'.format(ks, ks) flag_bn = '{}_{}_bn'.format(flag, suffix) flag_scale = '{}_{}_scale'.format(flag, suffix) flag_relu = '{}_{}_relu'.format(flag, suffix) flag_conv = '{}_{}_conv'.format(flag, suffix) flag_drop = '{}_{}_dropout'.format(flag, suffix) net[flag_bn] = L.BatchNorm(bottom, in_place=False, batch_norm_param=dict(use_global_stats=True)) net[flag_scale] = L.Scale(net[flag_bn], bias_term=True, in_place=True) net[flag_relu] = L.PReLU(net[flag_scale], in_place=True) net[flag_conv] = L.Convolution(net[flag_relu], num_output=nout, kernel_size=ks, stride=stride, pad=pad, bias_term=False) if dropout > 0: net[flag_drop] = L.Dropout(net[flag_conv], dropout_ratio=dropout) return net[flag_drop] return net[flag_conv]
def conv_prelu(self, bottom, num_out, kernel_size=3, stride=1, pad=1, is_bias=False, wf=gaussian_constant, in_place=False): if is_bias: learn_param = [ dict(lr_mult=1, decay_mult=1), dict(lr_mult=2, decay_mult=0) ] else: learn_param = [ dict(lr_mult=1, decay_mult=1), dict(lr_mult=0, decay_mult=0) ] conv = L.Convolution(bottom, kernel_size=kernel_size, stride=stride, num_output=num_out, pad=pad, param=learn_param, weight_filler=wf, bias_filler=dict(type='constant', value=0), in_place=in_place, engine=1) prelu = L.PReLU(conv, in_place=True) return prelu
def conv_relu(bottom, nout, ks=3, stride=1, pad=1): conv = L.Convolution(bottom, kernel_size=ks, stride=stride, num_output=nout, pad=pad, param=[dict(lr_mult=1, decay_mult=1), dict(lr_mult=2, decay_mult=0)], weight_filler=dict(type='xavier'),bias_filler=dict(type='constant')) #return conv, L.PReLU(conv, in_place=True)#in_place为同址运算 return conv, L.PReLU(conv, in_place=True)#in_place为同址运算
def bn_relu_conv(net, mode, flag, bottom, ks, nout, stride, pad, dropout): suffix = '{}x{}'.format(ks, ks) flag_bn = '{}_{}_bn'.format(flag, suffix) flag_scale = '{}_{}_scale'.format(flag, suffix) flag_relu = '{}_{}_relu'.format(flag, suffix) flag_conv = '{}_{}_conv'.format(flag, suffix) flag_drop = '{}_{}_dropout'.format(flag, suffix) use_global_stats = False if mode == 1: # TEST phase use_global_stats = True net[flag_bn] = L.BatchNorm(bottom, in_place=False, batch_norm_param = dict(use_global_stats=use_global_stats), param=[dict(lr_mult=0, decay_mult=0), dict(lr_mult=0, decay_mult=0), dict(lr_mult=0, decay_mult=0)]) net[flag_scale] = L.Scale(net[flag_bn], bias_term=True, in_place=True, filler=dict(value=1), bias_filler=dict(value=0)) net[flag_relu] = L.PReLU(net[flag_scale], in_place=True) net[flag_conv] = L.Convolution(net[flag_relu], num_output=nout, kernel_size=ks, stride=stride, pad=pad, weight_filler=dict(type='msra'), bias_term=False) if dropout > 0: net[flag_drop] = L.Dropout(net[flag_conv], dropout_ratio=dropout) return net[flag_drop] return net[flag_conv]
def test_prelu2(): # type: ()->caffe.NetSpec n = caffe.NetSpec() n.input1 = L.Input(shape=make_shape([10, 4, 64, 64])) n.relu1 = L.PReLU(n.input1, channel_shared=True) return n
def relu_net(self,in_data, weight, prelu_type = False, channel_shared=False): cin,h,w = in_data.shape; model_path = 'temp/'; if not os.path.exists(model_path): os.mkdir(model_path) n = caffe.NetSpec(); n.data0 = L.Input(shape=[dict(dim=[n1, cin, h, w])]) if prelu_type: n.out = L.PReLU(n.data0,channel_shared = channel_shared); else: n.out = L.ReLU(n.data0); def_file = model_path + 'internal.prototxt' with open(def_file, 'w') as f: f.write(str(n.to_proto())); f.close() net = caffe.Net(def_file, caffe.TEST); in_data = np.float32(in_data.reshape([1, cin, h, w])); p = in_data if prelu_type: pw = np.float32(weight.reshape(net.params['out'][0].data.shape)); net.params['out'][0].data[:] = pw; net.blobs['data0'].data[...] = p output = net.forward() pa = np.float32(output['out'][0]); if not os.path.exists(model_path): os.remove(model_path) return pa;
def BR(caffe_net, layer_idx, bottom_blob): names = ['bn{}'.format(layer_idx), 'prelu{}'.format(layer_idx)] caffe_net[names[0]] = L.BatchNorm(bottom_blob) caffe_net[names[1]] = L.PReLU(caffe_net[names[0]]) return caffe_net[names[1]], layer_idx + 1
def residual_block(ns_, in_, name_prefix_, weight_prefix_, dim_, phase_): fc = L.InnerProduct(in_, name=name_prefix_ + '_fc', inner_product_param={ 'bias_term': True, 'num_output': dim_, 'axis': -1, 'weight_filler': { 'type': 'gaussian', 'std': 0.001 }, 'bias_filler': { 'type': 'constant', 'value': 0 } }, param=[{ 'lr_mult': 1, 'decay_mult': 1, 'name': weight_prefix_ + '_fc_w' }, { 'lr_mult': 2, 'decay_mult': 0, 'name': weight_prefix_ + '_fc_b' }]) ns_.__setattr__(name_prefix_ + '_fc', fc) bn = L.BatchNorm( fc, name=name_prefix_ + '_bn', batch_norm_param={'use_global_stats': phase_ == caffe.TEST}, param=[{ 'name': weight_prefix_ + '_bn_mu', 'lr_mult': 0, 'decay_mult': 0 }, { 'name': weight_prefix_ + '_bn_sig', 'lr_mult': 0, 'decay_mult': 0 }, { 'name': weight_prefix_ + '_bn_eps', 'lr_mult': 0, 'decay_mult': 0 }]) ns_.__setattr__(name_prefix_ + '_bn', bn) prelu = L.PReLU(bn, name=name_prefix_ + '_prelu', prelu_param={ 'channel_shared': False, 'filler': { 'type': 'constant', 'value': 0.01 } }, param={ 'lr_mult': 1, 'decay_mult': 20, 'name': weight_prefix_ + '_prelu' }) ns_.__setattr__(name_prefix_ + '_prelu', prelu) return ns_, prelu, name_prefix_ + '_prelu'
def DownSampler( caffe_net, layer_idx, bottom_blob1, bottom_blob2, # always not none bottom_blob2_down_times, nin, nout, k=4, r_lim=9, reinf=True): config_inp_reinf = 3 nout_new = nout - nin # TODO: fix needed # caffe_net['pool{}'.format(layer_idx)] = L.Pooling(bottom_blob1, pool=P.Pooling.AVE, kernel_size=3, pad=1, stride=2) caffe_net['pool{}'.format(layer_idx)] = L.Pooling(bottom_blob1, pool=P.Pooling.AVE, kernel_size=3, stride=2) avg_out = caffe_net['pool{}'.format(layer_idx)] layer_idx += 1 eesp_out, layer_idx = EESP(caffe_net, layer_idx, bottom_blob1, nin, nout_new, stride=2, k=k, r_lim=r_lim, down_method='avg') caffe_net['cat{}'.format(layer_idx)] = L.Concat(*[eesp_out, avg_out], axis=1) output = caffe_net['cat{}'.format(layer_idx)] # need to know how many downsampling we need to do for i in range(bottom_blob2_down_times): # TODO: fix needed # caffe_net['pool{}'.format(layer_idx + i)] = L.Pooling(bottom_blob2, pool=P.Pooling.AVE, kernel_size=3, pad=1, stride=2) caffe_net['pool{}'.format(layer_idx + i)] = L.Pooling( bottom_blob2, pool=P.Pooling.AVE, kernel_size=3, stride=2) bottom_blob2 = caffe_net['pool{}'.format(layer_idx + i)] layer_idx += 1 bottom_blob, layer_idx = CBR(caffe_net, layer_idx, bottom_blob2, config_inp_reinf, 3, 1) bottom_blob, layer_idx = CB(caffe_net, layer_idx, bottom_blob, nout, 1, 1) caffe_net['add{}'.format(layer_idx)] = L.Eltwise(bottom_blob, output, operation=P.Eltwise.SUM, coeff=[1, 1]) output = caffe_net['add{}'.format(layer_idx)] layer_idx += 1 caffe_net['prelu{}'.format(layer_idx)] = L.PReLU(output) return caffe_net['prelu{}'.format(layer_idx)], layer_idx + 1
def make_tiles(n, data): n_splits = 16 result = netset(n, "split", L.Split(data, ntop=n_splits)) tiles = netset(n, "merge", L.Concat(*result, axis=1)) conv = make_conv(data, n_splits, 5, 2, 1) eltwise = L.Eltwise(tiles, conv, operation=P.Eltwise.SUM) prelu = L.PReLU(eltwise, in_place=True) return n_splits, prelu
def conv_relu(bottom, ks, nout, stride=1, pad=0, group=1, param=learned_param): conv = L.Convolution(bottom, kernel_size=ks, stride=stride, num_output=nout, pad=pad, group=group, param=param, weight_filler=dict(type='xavier', std=0.1), bias_filler=dict(type='constant', value=0.2)) return conv, L.PReLU(conv, in_place=True)
def left_branch(data, width, iters): input = data for i in range(0, iters - 1): conv = make_conv(input, width, 5, 2, 1) input = L.PReLU(conv, in_place=True) # input = max_pool(input,3) input = make_conv(input, width, 5, 2, 1) return input
def deploy_net(conf, batch_size, class_num): ''' :param conf: the data_set_config information, defined in data_info_set.item :param batch_size: the batch_size of prototxt :param class_num: the class_num of the data_set :param channels: the channels of hyperspectral data, maybe it is 224,448 or 103,206 :param kernel_size: the kernel_size of the convolution layer, often is 1/9 of the channels :return: deploy file handle ''' n = caffe.NetSpec() if conf.use_CK is True: n.data, n.label = L.DummyData( shape={'dim': [batch_size, 1, conf.CK_channels, 1]}, ntop=2) n.conv1 = L.Convolution(n.data, kernel_h=conf.CK_kernel_size, kernel_w=1, num_output=20, weight_filler=dict(type='gaussian', std=0.05), bias_filler=dict(type='constant', value=0.1)) else: n.data, n.label = L.DummyData( shape={'dim': [batch_size, 1, conf.channels, 1]}, ntop=2) n.conv1 = L.Convolution(n.data, kernel_h=conf.kernel_size, kernel_w=1, num_output=20, weight_filler=dict(type='gaussian', std=0.05), bias_filler=dict(type='constant', value=0.1)) n.bn1 = L.BatchNorm(n.conv1, use_global_stats=1, in_place=True) n.relu1 = L.PReLU(n.bn1, in_place=True) n.ip1 = L.InnerProduct(n.relu1, num_output=100, weight_filler=dict(type='gaussian', std=0.05), bias_filler=dict(type='constant', value=0.1)) n.drop1 = L.Dropout(n.ip1, dropout_ratio=0.1, in_place=True) n.relu2 = L.PReLU(n.drop1, in_place=True) n.ip2 = L.InnerProduct(n.relu2, num_output=class_num, weight_filler=dict(type='gaussian', std=0.05), bias_filler=dict(type='constant', value=0.1)) return n.to_proto()
def add_block_bn_c_bn(self, bottom, num_output): bn1 = L.BatchNorm(bottom, use_global_stats=False, in_place=False) bn1 = L.Scale(bn1, bias_term=True) conv1 = self.conv(bn1, num_output) bn2 = L.BatchNorm(conv1, use_global_stats=False, in_place=False) bn2 = L.Scale(bn2, bias_term=True) pr2 = L.PReLU(bn2, in_place=True) conv2 = self.conv(pr2, num_output) bn3 = L.BatchNorm(conv2, use_global_stats=False, in_place=False) bn3 = L.Scale(bn3, bias_term=True) output = L.Eltwise(bottom, bn3, eltwise_param=dict(operation=1)) return output
def add_block_bn_c_bn_se(self, bottom, num_output): bn1 = L.BatchNorm(bottom, use_global_stats=False, in_place=False) bn1 = L.Scale(bn1, bias_term=True, in_place=True) conv1 = self.conv(bn1, num_output) bn2 = L.BatchNorm(conv1, use_global_stats=False, in_place=True) bn2 = L.Scale(bn2, bias_term=True, in_place=True) pr2 = L.PReLU(bn2, in_place=True) conv2 = self.conv(pr2, num_output) bn3 = L.BatchNorm(conv2, use_global_stats=False, in_place=True) bn3 = L.Scale(bn3, bias_term=True, in_place=True) pool = L.Pooling(bn3, pool=1, global_pooling=True) conv3 = self.conv(pool, num_output / 16, kernel_size=1, stride=1, pad=0) pr3 = L.PReLU(conv3, in_place=True) conv4 = self.conv(pr3, num_output, kernel_size=1, stride=1, pad=0) prob = L.Sigmoid(conv4, in_place=True) output = L.Axpy(prob, bn3, bottom) return output
def add_block_se(self, bottom, num_output): layer1 = self.conv_prelu(bottom, num_output) layer2 = self.conv_prelu(layer1, num_output) pool = L.Pooling(layer2, pool=1, global_pooling=True) conv3 = self.conv(pool, num_output / 16, kernel_size=1, stride=1, pad=0) pr3 = L.PReLU(conv3, in_place=True) conv4 = self.conv(pr3, num_output, kernel_size=1, stride=1, pad=0) prob = L.Sigmoid(conv4, in_place=True) output = L.Axpy(prob, layer2, bottom) return output
def net(): n = caffe.NetSpec() n.data = L.Input(input_param=dict(shape=dict(dim=data_shape))) n.dataout = L.Convolution(n.data, param=[ dict(lr_mult=1, decay_mult=1), dict(lr_mult=2, decay_mult=0) ], kernel_size=7, stride=2, num_output=64, weight_filler=dict(type="xavier", std=0.03)) n.prelu = L.PReLU(n.dataout, in_place=True) return n.to_proto()
def compile_time_operation(self, learning_option, cluster): """ define parame rectified-linear unit(ReLU) operation for input tensor It follows: f(x) = alpha * x for x < 0, f(x) = x for x >= 0, where alpha is a learned array with the same shape as x. """ # get input input_ = self.get_input('input') indim = self.get_dimension('input') # get attr # optional field initializer = self.get_attr('initializer', default={ 'weight': {}, 'bias': {} }) # default will set later regularizer = self.get_attr('regularizer', default={}) # default will set later ch_shared = self.get_attr('channel_shared', default=False) # get weight for convolution alpha_init = get_initializer(initializer.get('weight'), is_bias=False) alpha_reg, alpha_reg_type = get_regularizer(regularizer, is_bias=False) # check regularizer type tmp_reg = learning_option.get('caffe_reg_type') if tmp_reg is None: learning_option['caffe_reg_type'] = alpha_reg_type else: if tmp_reg != alpha_reg_type: raise Exception( '[DLMDL ERROR]: In caffe, regularizer type of all layers must be equal' ) prelu = L.PReLU(input_, name=self.name, weight_filler=alpha_init, channel_shared=ch_shared, param=[alpha_reg]) #set output dimension outdim = indim self.set_output('output', prelu) self.set_dimension('output', outdim)
def conv_relu(bottom, nout, ks=3, stride=1, pad=1): #nout: 卷积核(filter)的个数 #ks: 卷积核的大小 #stride: 卷积核的步长,默认为1 #pad: 扩充边缘,默认为0,不扩充。 扩充的时候是左右、上下对称的 #lr_mult: 学习率的系数,最终的学习率是这个数乘以solver.prototxt配置文件中的base_lr。 #如果有两个lr_mult, 则第一个表示权值的学习率,第二个表示偏置项的学习率。 #一般偏置项的学习率是权值学习率的两倍 conv = L.Convolution( bottom, kernel_size=ks, stride=stride, num_output=nout, pad=pad, param=[dict(lr_mult=1, decay_mult=1), dict(lr_mult=2, decay_mult=0)], weight_filler=dict(type='xavier'), bias_filler=dict(type='constant')) return conv, L.PReLU(conv, in_place=True) #in_place为同址运算
def Convolution_PReLU(bottom, num_output=64, kernel_size=3, stride=1, pad=1, weight_filler=dict(type='gaussian', std=0.001), bias_filler=dict(type='constant', value=0), param=[dict(lr_mult=1), dict(lr_mult=0.1)]): conv = L.Convolution(bottom, num_output=num_output, kernel_size=kernel_size, stride=stride, pad=pad, weight_filler=weight_filler, bias_filler=bias_filler, param=param) relu = L.PReLU(conv, in_place=True) return conv, relu
def back_improper_prelu(bottom_dY, bottom_X, relu_type): if relu_type == 'gradient': prelu_filler = 1 elif relu_type == 'guided': prelu_filler = 0 else: prelu_filler = 1 # todo: are the params _always_ learned? prelu = L.PReLU(bottom_dY, prelu_param=dict(filler=dict(value=prelu_filler)), channel_shared=1) backrelu = L.Python(prelu, bottom_X, module='backward_improper_relu_layers', layer='MultiplyWithSwitch', ntop=1) # switch_X = L.Threshold(bottom_X) # switch_X_fullchannel = L.Convolution(switch_X, num_output=20, kernel_size=1, param=dict(lr_mult=0, decay_mult=0), # weight_filler=dict(value=1), # bias_filler=dict(value=0)) # backrelu = L.Eltwise(switch_X_fullchannel, prelu, operation=0, stable_prod_grad=True) return backrelu, prelu
def conv_prelu(net, from_layer, out_layer, lr_mult1, decay_mult1, lr_mult2, decay_mult2, num_output_, kernel_size_, weight_std, bias_value): kwargs = { 'param': [ dict(lr_mult=lr_mult1, decay_mult=decay_mult1), dict(lr_mult=lr_mult2, decay_mult=decay_mult2) ], 'convolution_param': dict(num_output=num_output_, kernel_size=kernel_size_, weight_filler=dict(type="gaussian", std=weight_std), bias_filler=dict(type="constant", value=bias_value)) } conv_name = out_layer net[conv_name] = L.Convolution(net[from_layer], **kwargs) prelu_name = 'relu{}'.format(conv_name[-1]) net[prelu_name] = L.PReLU( net[conv_name], prelu_param=dict(filler=dict(type="gaussian", std=0.03)), in_place=True) return prelu_name
def CBR( caffe_net, layer_idx, bottom_blob, out_planes, kernel_size=3, stride=1, groups=1, ): padding = int((kernel_size - 1) / 2) names = ['conv{}'.format(layer_idx), 'prelu{}'.format(layer_idx)] caffe_net[names[0]] = L.Convolution(bottom_blob, num_output=out_planes, bias_term=False, pad=padding, kernel_size=kernel_size, stride=stride, group=groups) caffe_net[names[1]] = L.PReLU(caffe_net[names[0]]) return caffe_net[names[1]], layer_idx + 1
def initial_block(n): bn_mode = 0 if args.mode == 'test': bn_mode = 1 n.conv0_1 = L.Convolution(n.data, num_output=13, bias_term=1, pad=1, kernel_size=3, stride=2, weight_filler=dict(type='msra')) n.pool0_1 = L.Pooling(n.data, kernel_size=2, stride=2, pool=P.Pooling.MAX) n.concat0_1 = L.Concat(n.conv0_1, n.pool0_1, axis=1) n.bn0_1 = L.BN( n.concat0_1, scale_filler=dict(type='constant', value=1), bn_mode=bn_mode, shift_filler=dict(type='constant', value=0.001), param=[dict(lr_mult=1, decay_mult=1), dict(lr_mult=1, decay_mult=0)]) n.prelu0_1 = L.PReLU(n.bn0_1) last_layer = 'prelu0_1' return n.to_proto(), last_layer