# Path: utils/layers.py
# def batch_norm2(layer, **kwargs):
#     nonlinearity = getattr(layer, 'nonlinearity', None)
#     if nonlinearity is not None:
#         layer.nonlinearity = nn.nonlinearities.identity
#     if hasattr(layer, 'b') and layer.b is not None:
#         del layer.params[layer.b]
#         layer.b = None
#     layer = BatchNormLayer(layer, **kwargs)
#     if nonlinearity is not None:
#         from lasagne.layers.special import NonlinearityLayer
#         layer = NonlinearityLayer(layer, nonlinearity, name='%s_nl' % layer.name)
#     return layer


import lasagne as nn
from lasagne.layers import dnn
from utils.layers import batch_norm2 as batch_norm

    for i in range(num_layers):
        if bottleneck:
            # Force then first and last layer to use 1x1 convolution
            if i == 0 or (i == (num_layers - 1)):
                actual_filter_size = (1, 1)
            else:
                actual_filter_size = filter_size

            # Only increase the filter size to the target size for
            # the last layer
            if i == (num_layers - 1):
                actual_num_filters = num_filters
            else:
                actual_num_filters = num_filters / bottleneck_factor
        else:
            actual_num_filters = num_filters
            actual_filter_size = filter_size

        # TODO the last layer should probably not be bn-ed..
        conv = conv2dbn(
            conv, name='%s_%s' % (name, i), num_filters=actual_num_filters,
            filter_size=actual_filter_size, pad=pad, W=W,
            # Remove nonlinearity for the last conv layer
            nonlinearity=nonlinearity if (i < num_layers - 1) else None,
            # Only apply stride for the first conv layer
            stride=stride if i == 0 else 1
        )

    l = nn.layers.merge.ElemwiseSumLayer([conv, layer], name='%s_elemsum' % name)

# Path: utils/layers.py
# def batch_norm2(layer, **kwargs):
#     nonlinearity = getattr(layer, 'nonlinearity', None)
#     if nonlinearity is not None:
#         layer.nonlinearity = nn.nonlinearities.identity
#     if hasattr(layer, 'b') and layer.b is not None:
#         del layer.params[layer.b]
#         layer.b = None
#     layer = BatchNormLayer(layer, **kwargs)
#     if nonlinearity is not None:
#         from lasagne.layers.special import NonlinearityLayer
#         layer = NonlinearityLayer(layer, nonlinearity, name='%s_nl' % layer.name)
#     return layer


# Path: utils/layer_macros.py
import lasagne as nn
from lasagne.layers import dnn
from utils.layers import batch_norm2 as batch_norm


    for i in range(num_layers):
        if bottleneck:
            # Force then first and last layer to use 1x1 convolution
            if i == 0 or (i == (num_layers - 1)):
                actual_filter_size = (1, 1)
            else:
                actual_filter_size = filter_size

            # Only increase the filter size to the target size for
            # the last layer
            if i == (num_layers - 1):
                actual_num_filters = num_filters
            else:
                actual_num_filters = num_filters / bottleneck_factor
        else:
            actual_num_filters = num_filters
            actual_filter_size = filter_size

        # TODO the last layer should probably not be bn-ed..
        conv = conv2dbn(
            conv, name='%s_%s' % (name, i), num_filters=actual_num_filters,
            filter_size=actual_filter_size, pad=pad, W=W,
            # Remove nonlinearity for the last conv layer
            nonlinearity=nonlinearity if (i < num_layers - 1) else None,
            # Only apply stride for the first conv layer
            stride=stride if i == 0 else 1
        )

    l = nn.layers.merge.ElemwiseSumLayer([conv, layer], name='%s_elemsum' % name)

    l = batch_norm(l)