예제 #1
0
def build_model(input_layer=None):

    #################
    # Regular model #
    #################

    l_4ch = nn.layers.InputLayer(data_sizes["sliced:data:chanzoom:4ch"])
    l_2ch = nn.layers.InputLayer(data_sizes["sliced:data:chanzoom:2ch"])

    # Add an axis to concatenate over later
    l_4chr = nn.layers.ReshapeLayer(l_4ch, (
        batch_size,
        1,
    ) + l_4ch.output_shape[1:])
    l_2chr = nn.layers.ReshapeLayer(l_2ch, (
        batch_size,
        1,
    ) + l_2ch.output_shape[1:])

    # Cut the images in half, flip the left ones
    l_4ch_left = nn.layers.SliceLayer(l_4chr,
                                      indices=slice(image_size // 2 - 1, None,
                                                    -1),
                                      axis=-1)
    l_4ch_right = nn.layers.SliceLayer(l_4chr,
                                       indices=slice(image_size // 2, None, 1),
                                       axis=-1)
    l_2ch_left = nn.layers.SliceLayer(l_2chr,
                                      indices=slice(image_size // 2 - 1, None,
                                                    -1),
                                      axis=-1)
    l_2ch_right = nn.layers.SliceLayer(l_2chr,
                                       indices=slice(image_size // 2, None, 1),
                                       axis=-1)

    # Concatenate over second axis
    l_24lr = nn.layers.ConcatLayer(
        [l_4ch_left, l_4ch_right, l_2ch_left, l_2ch_right], axis=1)
    # b, 4, t, h, w

    # Subsample frames
    SUBSAMPLING_FACTOR = 2
    nr_subsampled_frames = nr_frames // SUBSAMPLING_FACTOR
    l_24lr_ss = nn.layers.SliceLayer(l_24lr,
                                     indices=slice(None, None,
                                                   SUBSAMPLING_FACTOR),
                                     axis=2)

    # Move frames and halves to batch, process them all in the same way, add channel axis
    l_halves = nn.layers.ReshapeLayer(l_24lr_ss,
                                      (batch_size * 4 * nr_subsampled_frames,
                                       1, image_size, image_size // 2))

    # First, do some convolutions in all directions
    l1a = nn.layers.dnn.Conv2DDNNLayer(l_halves,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(3, 3),
                                       num_filters=16,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l1b = nn.layers.dnn.Conv2DDNNLayer(l1a,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(3, 3),
                                       num_filters=16,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l1 = nn.layers.dnn.MaxPool2DDNNLayer(l1b, pool_size=(1, 2), stride=(1, 2))

    # Then, only use the last axis
    l2a = nn.layers.dnn.Conv2DDNNLayer(l1,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=32,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l2b = nn.layers.dnn.Conv2DDNNLayer(l2a,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=32,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l2 = nn.layers.dnn.MaxPool2DDNNLayer(l2b, pool_size=(1, 2), stride=(1, 2))

    l3a = nn.layers.dnn.Conv2DDNNLayer(l2,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=64,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l3b = nn.layers.dnn.Conv2DDNNLayer(l3a,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=64,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l3c = nn.layers.dnn.Conv2DDNNLayer(l3b,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=64,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l3 = nn.layers.dnn.MaxPool2DDNNLayer(l3c, pool_size=(1, 2), stride=(1, 2))

    l4a = nn.layers.dnn.Conv2DDNNLayer(l3,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=128,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l4b = nn.layers.dnn.Conv2DDNNLayer(l4a,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=128,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l4c = nn.layers.dnn.Conv2DDNNLayer(l4b,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=128,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l4 = nn.layers.dnn.MaxPool2DDNNLayer(l4c, pool_size=(1, 2), stride=(1, 2))

    # Now, process each row seperately, by flipping the channel and height axis, and then putting height in the batch
    l4shuffle = nn.layers.DimshuffleLayer(l4, pattern=(0, 2, 1, 3))
    l4rows = nn.layers.ReshapeLayer(
        l4shuffle, (batch_size * 4 * nr_subsampled_frames * image_size,
                    l4shuffle.output_shape[-2], l4shuffle.output_shape[-1]))

    # Systole
    ld1 = nn.layers.DenseLayer(l4rows,
                               num_units=256,
                               W=nn.init.Orthogonal("relu"),
                               b=nn.init.Constant(0.1),
                               nonlinearity=nn.nonlinearities.rectify)

    ld1drop = nn.layers.dropout(ld1, p=0.5)
    ld2 = nn.layers.DenseLayer(ld1drop,
                               num_units=256,
                               W=nn.init.Orthogonal("relu"),
                               b=nn.init.Constant(0.1),
                               nonlinearity=nn.nonlinearities.rectify)

    ld2drop = nn.layers.dropout(ld2, p=0.5)
    ld3mu = nn.layers.DenseLayer(ld2drop,
                                 num_units=1,
                                 W=nn.init.Orthogonal("relu"),
                                 b=nn.init.Constant(16.0),
                                 nonlinearity=None)
    ld3sigma = nn.layers.DenseLayer(ld2drop,
                                    num_units=1,
                                    W=nn.init.Orthogonal("relu"),
                                    b=nn.init.Constant(4.0),
                                    nonlinearity=lb_softplus(.01))
    ld3musigma = nn.layers.ConcatLayer([ld3mu, ld3sigma], axis=1)

    # Get the four halves back
    l_24lr_musigma = nn.layers.ReshapeLayer(
        ld3musigma, (batch_size, 4, nr_subsampled_frames, image_size, 2))
    l_24lr_musigma_shuffle = nn.layers.DimshuffleLayer(l_24lr_musigma,
                                                       pattern=(0, 2, 1, 3, 4))
    l_24lr_musigma_re = nn.layers.ReshapeLayer(
        l_24lr_musigma_shuffle,
        (batch_size * nr_subsampled_frames, 4, image_size, 2))

    l_4ch_left_musigma = nn.layers.SliceLayer(l_24lr_musigma_re,
                                              indices=0,
                                              axis=1)
    l_4ch_right_musigma = nn.layers.SliceLayer(l_24lr_musigma_re,
                                               indices=1,
                                               axis=1)
    l_2ch_left_musigma = nn.layers.SliceLayer(l_24lr_musigma_re,
                                              indices=2,
                                              axis=1)
    l_2ch_right_musigma = nn.layers.SliceLayer(l_24lr_musigma_re,
                                               indices=3,
                                               axis=1)

    l_4ch_musigma = layers.SumGaussLayer(
        [l_4ch_left_musigma, l_4ch_right_musigma])
    l_2ch_musigma = layers.SumGaussLayer(
        [l_2ch_left_musigma, l_2ch_right_musigma])

    l_musigma_frames = layers.IraLayerNoTime(l_4ch_musigma, l_2ch_musigma)

    # Minmax over time
    print l_musigma_frames.output_shape
    l_musigmas = nn.layers.ReshapeLayer(l_musigma_frames,
                                        (-1, nr_subsampled_frames, 2))
    l_musigma_sys = layers.ArgmaxAndMaxLayer(l_musigmas, mode='min')
    l_musigma_dia = layers.ArgmaxAndMaxLayer(l_musigmas, mode='max')

    l_systole = layers.MuSigmaErfLayer(l_musigma_sys)
    l_diastole = layers.MuSigmaErfLayer(l_musigma_dia)

    return {
        "inputs": {
            "sliced:data:chanzoom:4ch": l_4ch,
            "sliced:data:chanzoom:2ch": l_2ch,
        },
        "outputs": {
            "systole": l_systole,
            "diastole": l_diastole,
        },
        "regularizable": {},
        "meta_outputs": {}
    }
def build_model(input_layer=None):

    #################
    # Regular model #
    #################

    l_4ch = nn.layers.InputLayer(data_sizes["sliced:data:chanzoom:4ch"])
    l_2ch = nn.layers.InputLayer(data_sizes["sliced:data:chanzoom:2ch"])

    # Add an axis to concatenate over later
    l_4chr = nn.layers.ReshapeLayer(l_4ch, (
        -1,
        1,
    ) + l_4ch.output_shape[1:])
    l_2chr = nn.layers.ReshapeLayer(l_2ch, (
        -1,
        1,
    ) + l_2ch.output_shape[1:])

    # Cut the images in half, flip the left ones
    l_4ch_left = nn.layers.SliceLayer(l_4ch,
                                      indices=slice(image_size // 2 - 1, None,
                                                    -1),
                                      axis=-1)
    l_4ch_right = nn.layers.SliceLayer(l_4ch,
                                       indices=slice(image_size // 2, None, 1),
                                       axis=-1)
    l_2ch_left = nn.layers.SliceLayer(l_2ch,
                                      indices=slice(image_size // 2 - 1, None,
                                                    -1),
                                      axis=-1)
    l_2ch_right = nn.layers.SliceLayer(l_2ch,
                                       indices=slice(image_size // 2, None, 1),
                                       axis=-1)

    # Concatenate over second axis
    l_24lr = nn.layers.ConcatLayer(
        [l_4ch_left, l_4ch_right, l_2ch_left, l_2ch_right], axis=1)

    # Move second axis to batch, process them all in the same way
    l_halves = nn.layers.ReshapeLayer(
        l_24lr, (-1, nr_frames, image_size, image_size // 2))

    # First, do some convolutions in all directions
    l1a = nn.layers.dnn.Conv2DDNNLayer(l_halves,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(3, 3),
                                       num_filters=32,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l1b = nn.layers.dnn.Conv2DDNNLayer(l1a,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(3, 3),
                                       num_filters=32,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l1 = nn.layers.dnn.MaxPool2DDNNLayer(l1b, pool_size=(1, 2), stride=(1, 2))

    # Then, only use the last axis
    l2a = nn.layers.dnn.Conv2DDNNLayer(l1,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=64,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l2b = nn.layers.dnn.Conv2DDNNLayer(l2a,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=64,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l2 = nn.layers.dnn.MaxPool2DDNNLayer(l2b, pool_size=(1, 2), stride=(1, 2))

    l3a = nn.layers.dnn.Conv2DDNNLayer(l2,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=128,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l3b = nn.layers.dnn.Conv2DDNNLayer(l3a,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=128,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l3c = nn.layers.dnn.Conv2DDNNLayer(l3b,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=128,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l3 = nn.layers.dnn.MaxPool2DDNNLayer(l3c, pool_size=(1, 2), stride=(1, 2))

    l4a = nn.layers.dnn.Conv2DDNNLayer(l3,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=256,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l4b = nn.layers.dnn.Conv2DDNNLayer(l4a,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=256,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l4c = nn.layers.dnn.Conv2DDNNLayer(l4b,
                                       W=nn.init.Orthogonal("relu"),
                                       filter_size=(1, 3),
                                       num_filters=256,
                                       stride=(1, 1),
                                       pad="same",
                                       nonlinearity=nn.nonlinearities.rectify)
    l4 = nn.layers.dnn.MaxPool2DDNNLayer(l4c, pool_size=(1, 2), stride=(1, 2))

    # Now, process each row seperately, by flipping the channel and height axis, and then putting height in the batch
    l4shuffle = nn.layers.DimshuffleLayer(l4, pattern=(0, 2, 1, 3))
    l4rows = nn.layers.ReshapeLayer(
        l4shuffle,
        (-1, l4shuffle.output_shape[-2], l4shuffle.output_shape[-1]))

    # Systole
    ldsys1 = nn.layers.DenseLayer(l4rows,
                                  num_units=256,
                                  W=nn.init.Orthogonal("relu"),
                                  b=nn.init.Constant(0.1),
                                  nonlinearity=nn.nonlinearities.rectify)

    ldsys1drop = nn.layers.dropout(ldsys1, p=0.5)
    ldsys2 = nn.layers.DenseLayer(ldsys1drop,
                                  num_units=256,
                                  W=nn.init.Orthogonal("relu"),
                                  b=nn.init.Constant(0.1),
                                  nonlinearity=nn.nonlinearities.rectify)

    ldsys2drop = nn.layers.dropout(ldsys2, p=0.5)
    ldsys3mu = nn.layers.DenseLayer(ldsys2drop,
                                    num_units=1,
                                    W=nn.init.Orthogonal("relu"),
                                    b=nn.init.Constant(16.0),
                                    nonlinearity=None)
    ldsys3sigma = nn.layers.DenseLayer(ldsys2drop,
                                       num_units=1,
                                       W=nn.init.Orthogonal("relu"),
                                       b=nn.init.Constant(4.0),
                                       nonlinearity=lb_softplus(.01))
    ldsys3musigma = nn.layers.ConcatLayer([ldsys3mu, ldsys3sigma], axis=1)

    l_24lr_sys_musigma = nn.layers.ReshapeLayer(ldsys3musigma,
                                                (-1, 4, image_size, 2))
    l_4ch_left_sys_musigma = nn.layers.SliceLayer(l_24lr_sys_musigma,
                                                  indices=0,
                                                  axis=1)
    l_4ch_right_sys_musigma = nn.layers.SliceLayer(l_24lr_sys_musigma,
                                                   indices=1,
                                                   axis=1)
    l_2ch_left_sys_musigma = nn.layers.SliceLayer(l_24lr_sys_musigma,
                                                  indices=2,
                                                  axis=1)
    l_2ch_right_sys_musigma = nn.layers.SliceLayer(l_24lr_sys_musigma,
                                                   indices=3,
                                                   axis=1)

    l_4ch_sys_musigma = layers.SumGaussLayer(
        [l_4ch_left_sys_musigma, l_4ch_right_sys_musigma])
    l_2ch_sys_musigma = layers.SumGaussLayer(
        [l_2ch_left_sys_musigma, l_2ch_right_sys_musigma])

    l_sys_musigma = layers.IraLayerNoTime(l_4ch_sys_musigma, l_2ch_sys_musigma)

    l_systole = layers.MuSigmaErfLayer(l_sys_musigma)

    # Systole
    lddia1 = nn.layers.DenseLayer(l4rows,
                                  num_units=256,
                                  W=nn.init.Orthogonal("relu"),
                                  b=nn.init.Constant(0.1),
                                  nonlinearity=nn.nonlinearities.rectify)

    lddia1drop = nn.layers.dropout(lddia1, p=0.5)
    lddia2 = nn.layers.DenseLayer(lddia1drop,
                                  num_units=256,
                                  W=nn.init.Orthogonal("relu"),
                                  b=nn.init.Constant(0.1),
                                  nonlinearity=nn.nonlinearities.rectify)

    lddia2drop = nn.layers.dropout(lddia2, p=0.5)
    lddia3mu = nn.layers.DenseLayer(lddia2drop,
                                    num_units=1,
                                    W=nn.init.Orthogonal("relu"),
                                    b=nn.init.Constant(16.0),
                                    nonlinearity=None)
    lddia3sigma = nn.layers.DenseLayer(lddia2drop,
                                       num_units=1,
                                       W=nn.init.Orthogonal("relu"),
                                       b=nn.init.Constant(4.0),
                                       nonlinearity=lb_softplus(.01))
    lddia3musigma = nn.layers.ConcatLayer([lddia3mu, lddia3sigma], axis=1)

    l_24lr_dia_musigma = nn.layers.ReshapeLayer(lddia3musigma,
                                                (-1, 4, image_size, 2))
    l_4ch_left_dia_musigma = nn.layers.SliceLayer(l_24lr_dia_musigma,
                                                  indices=0,
                                                  axis=1)
    l_4ch_right_dia_musigma = nn.layers.SliceLayer(l_24lr_dia_musigma,
                                                   indices=1,
                                                   axis=1)
    l_2ch_left_dia_musigma = nn.layers.SliceLayer(l_24lr_dia_musigma,
                                                  indices=2,
                                                  axis=1)
    l_2ch_right_dia_musigma = nn.layers.SliceLayer(l_24lr_dia_musigma,
                                                   indices=3,
                                                   axis=1)

    l_4ch_dia_musigma = layers.SumGaussLayer(
        [l_4ch_left_dia_musigma, l_4ch_right_dia_musigma])
    l_2ch_dia_musigma = layers.SumGaussLayer(
        [l_2ch_left_dia_musigma, l_2ch_right_dia_musigma])

    l_dia_musigma = layers.IraLayerNoTime(l_4ch_dia_musigma, l_2ch_dia_musigma)

    l_diastole = layers.MuSigmaErfLayer(l_dia_musigma)

    return {
        "inputs": {
            "sliced:data:chanzoom:4ch": l_4ch,
            "sliced:data:chanzoom:2ch": l_2ch,
        },
        "outputs": {
            "systole": l_systole,
            "diastole": l_diastole,
        },
        "regularizable": {},
        "meta_outputs": {}
    }
def build_model(input_layer = None):

    #################
    # Regular model #
    #################

    l_4ch = nn.layers.InputLayer(data_sizes["sliced:data:chanzoom:4ch"])
    l_2ch = nn.layers.InputLayer(data_sizes["sliced:data:chanzoom:2ch"])

    # Add an axis to concatenate over later
    l_4chr = nn.layers.ReshapeLayer(l_4ch, (batch_size, 1, ) + l_4ch.output_shape[1:])
    l_2chr = nn.layers.ReshapeLayer(l_2ch, (batch_size, 1, ) + l_2ch.output_shape[1:])
    
    # Cut the images in half, flip the left ones
    l_4ch_left = nn.layers.SliceLayer(l_4chr, indices=slice(image_size//2-1, None, -1), axis=-1)
    l_4ch_right = nn.layers.SliceLayer(l_4chr, indices=slice(image_size//2, None, 1), axis=-1)
    l_2ch_left = nn.layers.SliceLayer(l_2chr, indices=slice(image_size//2-1, None, -1), axis=-1)
    l_2ch_right = nn.layers.SliceLayer(l_2chr, indices=slice(image_size//2, None, 1), axis=-1)

    # Concatenate over second axis
    l_24lr = nn.layers.ConcatLayer([l_4ch_left, l_4ch_right, l_2ch_left, l_2ch_right], axis=1)
    # b, 4, t, h, w

    # Subsample frames
    SUBSAMPLING_FACTOR = 2
    nr_subsampled_frames = nr_frames // SUBSAMPLING_FACTOR
    l_24lr_ss = nn.layers.SliceLayer(l_24lr, indices=slice(None, None, SUBSAMPLING_FACTOR), axis=2)

    # Move frames and halves to batch, process them all in the same way, add channel axis
    l_halves = nn.layers.ReshapeLayer(l_24lr_ss, (batch_size * 4 * nr_subsampled_frames, 1, image_size, image_size//2))

    # First, do some convolutions in all directions
    num_channels = 64
    l1a = nn.layers.dnn.Conv2DDNNLayer(l_halves,  W=nn.init.Orthogonal("relu"), filter_size=(3,3), num_filters=num_channels, stride=(1,1), pad="same", nonlinearity=nn.nonlinearities.rectify)
    l1b = nn.layers.dnn.Conv2DDNNLayer(l1a, W=nn.init.Orthogonal("relu"), filter_size=(3,3), num_filters=num_channels, stride=(1,1), pad="same", nonlinearity=nn.nonlinearities.rectify)
    
    # Then, put an rnn over the last axis
    l1_shuffle = nn.layers.DimshuffleLayer(l1b, pattern=(0, 2, 3, 1))
    l1_r = nn.layers.ReshapeLayer(l1_shuffle, (batch_size * 4 * nr_subsampled_frames * image_size, image_size//2, num_channels))

    l_rnn = rnn_layer(l1_r, 1024)

    ld3mu = nn.layers.DenseLayer(l_rnn, num_units=1, W=nn.init.Orthogonal("relu"), b=nn.init.Constant(16.0), nonlinearity=None)
    ld3sigma = nn.layers.DenseLayer(l_rnn, num_units=1, W=nn.init.Orthogonal("relu"), b=nn.init.Constant(4.0), nonlinearity=lb_softplus(.01))
    ld3musigma = nn.layers.ConcatLayer([ld3mu, ld3sigma], axis=1)

    # Get the four halves back
    l_24lr_musigma = nn.layers.ReshapeLayer(ld3musigma, (batch_size, 4, nr_subsampled_frames, image_size, 2))
    l_24lr_musigma_shuffle = nn.layers.DimshuffleLayer(l_24lr_musigma, pattern=(0, 2, 1, 3, 4))
    l_24lr_musigma_re = nn.layers.ReshapeLayer(l_24lr_musigma_shuffle, (batch_size * nr_subsampled_frames, 4, image_size, 2))

    l_4ch_left_musigma = nn.layers.SliceLayer(l_24lr_musigma_re, indices=0, axis=1)   
    l_4ch_right_musigma = nn.layers.SliceLayer(l_24lr_musigma_re, indices=1, axis=1)   
    l_2ch_left_musigma = nn.layers.SliceLayer(l_24lr_musigma_re, indices=2, axis=1)   
    l_2ch_right_musigma = nn.layers.SliceLayer(l_24lr_musigma_re, indices=3, axis=1)

    l_4ch_musigma = layers.SumGaussLayer([l_4ch_left_musigma, l_4ch_right_musigma])
    l_2ch_musigma = layers.SumGaussLayer([l_2ch_left_musigma, l_2ch_right_musigma])

    l_musigma_frames = layers.IraLayerNoTime(l_4ch_musigma, l_2ch_musigma)

    # Minmax over time
    print(l_musigma_frames.output_shape)
    l_musigmas = nn.layers.ReshapeLayer(l_musigma_frames, (-1, nr_subsampled_frames, 2))
    l_musigma_sys = layers.ArgmaxAndMaxLayer(l_musigmas, mode='min')
    l_musigma_dia = layers.ArgmaxAndMaxLayer(l_musigmas, mode='max')

    l_systole = layers.MuSigmaErfLayer(l_musigma_sys)
    l_diastole = layers.MuSigmaErfLayer(l_musigma_dia)
 
    return {
        "inputs":{
            "sliced:data:chanzoom:4ch": l_4ch,
            "sliced:data:chanzoom:2ch": l_2ch,
        },
        "outputs": {
            "systole": l_systole,
            "diastole": l_diastole,
        },
        "regularizable": {
        },
        "meta_outputs": {
        }
    }