def conv_decoder(output_side=32, n_channels=3, representation_dim=256, activation='relu'):
    nf = 64
    Slicer = Lambda(lambda x, slice_size: x[:, :slice_size, :slice_size, :], output_shape=(output_side, output_side, n_channels),
               name="slice_layer")  # Define your lambda layer
    Slicer.arguments = {'slice_size': output_side}  # Update extra arguments to F

    rep_in = Input(shape=(representation_dim,))

    if output_side == 21:
        height, width, feat_mult = (3, 3, 4)
    else:
        height, width, feat_mult = (4, 4, 4)
    g = Dense(nf * feat_mult * height * width)(rep_in)

    g = BatchNormalization(axis=-1)(g)
    g = Activation(activation)(g)

    conv_shape = (nf * feat_mult, height, width) if get_channels_axis() == 1 else (height, width, nf * feat_mult)
    g = Reshape(conv_shape)(g)

    # upsample x2
    g = Conv2DTranspose(nf * 2, kernel_size=(3, 3), strides=(2, 2), padding='same')(g)
    g = BatchNormalization(axis=get_channels_axis())(g)
    g = Activation(activation)(g)

    # upsample x2
    g = Conv2DTranspose(nf, kernel_size=(3, 3), strides=(2, 2), padding='same')(g)
    g = BatchNormalization(axis=get_channels_axis())(g)
    g = Activation(activation)(g)

    if output_side == 64:
        # upsample x2
        g = Conv2DTranspose(nf, kernel_size=(3, 3), strides=(2, 2), padding='same')(g)
        g = BatchNormalization(axis=get_channels_axis())(g)
        g = Activation(activation)(g)

    # upsample x2
    g = Conv2DTranspose(n_channels, kernel_size=(3, 3), strides=(2, 2), padding='same')(g)
    g = Activation('tanh')(g)

    g = Slicer(g)

    return Model(rep_in, g)
Beispiel #2
0
    def __init__(self, vector_len, dimension):
        def connection(x, i):
            return x[:, i, :]

        v = Input(shape=(vector_len, dimension))
        m = Input(shape=(memory_len, ))
        alphas = []
        weight_input = Dense(1, activation='tanh')
        weight_memory = Dense(1, activation='tanh')
        weight_hidden = Dense(1, activation='softmax')
        multiplication = multiply
        extraction = Lambda(connection, arguments={'i': 0})
        for i in range(vector_len):
            if i % 1000 == 0:
                print(i)
            extraction.arguments = {'i': i}
            vi = extraction(v)
            hidden = multiplication([weight_input(vi), weight_memory(m)])
            alpha = weight_hidden(hidden)
            alphas.append(alpha)
        alphas = concatenate(alphas)
        attented_v = Lambda(apply_weights, arguments={'length':
                                                      dimension})([v, alphas])
        self.model = Model([v, m], outputs=attented_v)
Beispiel #3
0
    def __init__(self,
                 data_dims,
                 latent_dims,
                 network_architecture='synthetic'):
        """
        Args:
            data_dims: tuple, flattened data dimension for each dataset
            latent_dims: tuple, flattened latent dimensions for each private latent space and the dimension
                of the shared space.
            network_architecture: str, the codename of the encoder network architecture (will be the same for all)
        """
        assert len(latent_dims) == len(data_dims) + 1, \
            "Expected too receive {} private latent spaces and one shared for {} data inputs " \
            "but got {} instead.".format(len(data_dims) + 1, len(data_dims), len(latent_dims))

        # NOTE: this encoder is better off not having BaseEncoder as super class.
        # This might be refactored in the future if multiple variations of the conjoint model are to be implemented,
        # and this class can be used as a base class for them.
        name = 'Reparametrised Gaussian Conjoint Encoder'
        logger.info(
            "Initialising {} model with {}-dimensional data inputs "
            "and {}-dimensional latent outputs (last one is shared)".format(
                name, data_dims, latent_dims))

        def lin_transform_standard_gaussian(params):
            from keras.backend import exp
            mu, log_sigma, z = params
            transformed_z = mu + exp(log_sigma / 2.0) * z
            return transformed_z

        inputs, latent_space, latent_means, latent_log_vars, features = [], [], [], [], []
        for i in range(len(data_dims)):
            data_input = Input(shape=(data_dims[i], ),
                               name="enc_data_input_{}".format(i))
            features_i = get_network_by_name['conjoint_encoder'][
                network_architecture](data_input, 'conj_{}'.format(i))
            private_latent_mean = Dense(
                latent_dims[i], activation=None,
                name='enc_mean_{}'.format(i))(features_i)
            # since the variance must be positive and this is not easy to restrict, take it in the log domain
            # and exponentiate it during the reparametrisation
            private_latent_log_var = Dense(
                latent_dims[i],
                activation=None,
                name='enc_log_var_{}'.format(i))(features_i)

            inputs.append(data_input)
            latent_means.append(private_latent_mean)
            latent_log_vars.append(private_latent_log_var)
            features.append(features_i)

        features = Concatenate(axis=-1,
                               name='enc_concat_all_features')(features)

        shared_latent_mean = Dense(latent_dims[-1],
                                   activation=None,
                                   name='enc_shared_mean')(features)
        shared_latent_log_var = Dense(latent_dims[-1],
                                      activation=None,
                                      name='enc_shared_log_var')(features)
        total_latent_mean = Concatenate(
            axis=-1,
            name='enc_total_mean')(latent_means + [shared_latent_mean])
        total_latent_log_var = Concatenate(
            axis=-1, name='enc_total_log_var')(latent_log_vars +
                                               [shared_latent_log_var])

        # introduce the noise and reparametrise it
        standard_normal_sampler = Lambda(sample_standard_normal_noise,
                                         name='enc_normal_sampler')
        standard_normal_sampler.arguments = {
            'data_dim': sum(data_dims),
            'noise_dim': sum(latent_dims),
            'seed': config['seed']
        }
        noise = standard_normal_sampler(total_latent_mean)

        total_latent_space = Lambda(lin_transform_standard_gaussian,
                                    name='enc_latent')([
                                        total_latent_mean,
                                        total_latent_log_var, noise
                                    ])

        self.encoder_inference_model = Model(inputs=inputs,
                                             outputs=total_latent_space,
                                             name='encoder_inference')
        self.encoder_learning_model = Model(inputs=inputs,
                                            outputs=[
                                                total_latent_space,
                                                total_latent_mean,
                                                total_latent_log_var
                                            ],
                                            name='encoder_learning')
Beispiel #4
0
    def __init__(self,
                 data_dims,
                 noise_dim,
                 latent_dims,
                 network_architecture='synthetic',
                 noise_mode='add'):
        """
        Args:
            data_dims: tuple, flattened data dimension for each dataset
            noise_dim: int, flattened noise dimensionality
            latent_dims: tuple, flattened latent dimensions for each private latent space and the dimension
                of the shared space.
            network_architecture: str, the codename of the encoder network architecture (will be the same for all)
            noise_mode: str, the way the noise will be merged with the input('add', 'concat', 'product')
        """
        assert len(latent_dims) == len(data_dims) + 1, \
            "Expected too receive {} private latent spaces and one shared for {} data inputs " \
            "but got {} instead.".format(len(data_dims) + 1, len(data_dims), len(latent_dims))

        name = 'Standard Conjoint Encoder'
        logger.info(
            "Initialising {} model with {}-dimensional data inputs "
            "and {}-dimensional latent outputs (last one is shared)".format(
                name, data_dims, latent_dims))

        latent_space, features = [], []
        inputs = [
            Input(shape=(dim, ), name="enc_data_input_{}".format(i))
            for i, dim in enumerate(data_dims)
        ]
        standard_normal_sampler = Lambda(sample_standard_normal_noise,
                                         name='enc_normal_sampler')

        if noise_mode == 'concatenate':
            if network_architecture == 'mnist':
                assert ((noise_dim % sqrt(data_dims[0]) == 0) and (noise_dim % sqrt(data_dims[1]) == 0)), \
                    "Expected to receive a noise_dim that, when concatenated, can form a rectangle with " \
                    "the given inputs_dims. Received {} noise and {} data dimensions.".format(noise_dim, data_dims)
        elif noise_mode == 'product':
            assert data_dims[0] == noise_dim and data_dims[1] == noise_dim, \
                "Expected to receive a noise_dim that is equal to the given inputs dimensions. " \
                "Received {} noise and {} data dimensions.".format(noise_dim, data_dims)
        elif noise_mode != 'add':
            raise ValueError(
                "Only the noise modes 'add', 'concatenate' and 'product' are available."
            )
        standard_normal_sampler.arguments = {
            'seed': config['seed'],
            'noise_dim': noise_dim,
            'mode': noise_mode
        }

        for i, inp in enumerate(inputs):
            noise_input = standard_normal_sampler(inp)
            feature = get_network_by_name['conjoint_encoder'][
                network_architecture](noise_input, 'enc_feat_{}'.format(i))
            latent_factors = Dense(
                latent_dims[i],
                activation=None,
                name='enc_latent_private_{}'.format(i))(feature)
            latent_space.append(latent_factors)
            features.append(feature)

        merged_features = Concatenate(axis=-1,
                                      name='enc_concat_features')(features)
        shared_latent = Dense(latent_dims[-1],
                              activation=None,
                              name='enc_shared_latent')(merged_features)
        latent_space = Concatenate(
            axis=-1,
            name='enc_concat_all_features')(latent_space + [shared_latent])
        self.encoder_model = Model(inputs=inputs,
                                   outputs=latent_space,
                                   name='encoder')