Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How does LRP works when used in Autoencoders? #272

Open
HugoTex98 opened this issue Nov 11, 2021 · 5 comments
Open

How does LRP works when used in Autoencoders? #272

HugoTex98 opened this issue Nov 11, 2021 · 5 comments

Comments

@HugoTex98
Copy link

Hello everyone!

I decided to use this amazing toolbox in my Autoencoder model but I'm having doubts about how it works in this type of models...

How will relevance scores be calculated in this case? Is it done in my encoder or when input is reconstructed?

Can anyone help me in this question?

My model is the following:
`

def ConnectomeCNNAutoencoder(input_shape, keep_pr=0.65, n_filter=32, n_dense1=64, n_classes=2, # keep_pr=0.65, n_filter=32, n_dense1=64, mode="autoencoder", sign="neg"):
input_1 = Input(shape=input_shape)
# Convolutional Encoder 
bias_init = tf.constant_initializer(value=0.001)
conv1 = Conv2D(filters=n_filter , kernel_size=(1,input_shape[1]), strides=(1, 1),
                                 padding= "valid", activation="selu", # "selu"
                                 kernel_initializer="glorot_uniform",
                                 bias_initializer=bias_init, name="conv1")(input_1)

# dropout1 = Dropout(keep_pr, name="dropout1")(conv1)
dropout1 = SpatialDropout2D(keep_pr, name="dropout1")(conv1)
conv2 = Conv2D(filters=n_filter*2 , kernel_size=(input_shape[1],1), strides=(1, 1),
                                 padding= "valid", activation="selu", # "selu"
                                 kernel_initializer="glorot_uniform",
                                 bias_initializer=bias_init, name="conv2")(dropout1)
encoded = Dropout(keep_pr, name="dropout2")(conv2)

# Classification
reshape = Reshape((n_filter*2,), name="reshape1")(encoded)
dense1 = Dense(n_dense1, activation="selu", name="dense1", kernel_regularizer=keras.regularizers.l1_l2())(reshape) 
# dense1 = Dense(n_dense1, activation="selu", name="dense1", kernel_regularizer=keras.regularizers.l1_l2(l1=0.001,l2=0.001))(reshape) 
# dropout2 = Dropout(0.5, name="dropout2")

if n_classes == 1:
    activation = "sigmoid"
else:
    activation = "softmax"
output = Dense(n_classes, activation=activation, name="output")(dense1)


# Decoder
dim_reconstruct = tuple(encoded.get_shape().as_list())  # say, (1, 1, 60)
n_dense2 = np.product(dim_reconstruct[1:])  # will be 60
dense2 = Dense(n_dense2, activation="selu", name="dense2")(output)
reshape2 = Reshape(dim_reconstruct[1:], name="reshape2")(dense2)

# dropout3 = Dropout(keep_pr, name="dropout3")(reshape2)

conv3 = Conv2DTranspose(filters=n_filter*2 , kernel_size=(1,1), strides=(1, 1),
                                  padding= "valid", activation="selu", # "selu"
                                  kernel_initializer="glorot_uniform",
                                  bias_initializer=bias_init, name="conv3")(reshape2)
# dropout3 = Dropout(keep_pr, name="dropout3")(conv3)
conv4 = Conv2DTranspose(filters=n_filter , kernel_size=(input_shape[1],1), strides=(1, 1),
                                  padding= "valid", activation="selu", # "selu"
                                  kernel_initializer="glorot_uniform",
                                  bias_initializer=bias_init, name="conv4")(conv3)

if sign == "pos":
    reconstructed_activation = "sigmoid"
elif sign == "neg":
    reconstructed_activation = "tanh"
    
reconstructed_input = Conv2DTranspose(filters=input_shape[-1], kernel_size=(1,input_shape[1]), strides=(1, 1),
                                  padding= "valid", activation=reconstructed_activation, 
                                  kernel_initializer="glorot_uniform",
                                  bias_initializer=bias_init, name='autoencoder')(conv4)

if mode == "autoencoder":
    model = keras.models.Model(inputs=input_1, outputs=[output, reconstructed_input])
elif mode =="encoder":
    # Work as a feature extractor for others models
    model = keras.models.Model(inputs=input_1, outputs=encoded)
elif mode == "decoder":
    model = keras.models.Model(inputs=input_1, outputs=reconstructed_input)
return model

`

@enryH
Copy link
Collaborator

enryH commented Nov 19, 2021

As you wrap a keras model into an explainer, it is up to you if you only want to analyse your latent space after your encoder or if you want to see what the reconstructions explained: Do you want to explain single dimensions in your latent space or do you want to explain single reconstructions in your reconstructions.

Most other applications have a classic supervised setup, where the predicted class (logits/score) is explained.

@HugoTex98
Copy link
Author

Thanks for your reply @enryH !

If I want to explain the reconstructions of my inputs, do I need to change anything in the normal configuration of my LRP analyzer?

@enryH
Copy link
Collaborator

enryH commented Nov 19, 2021

Normally it is advised (in papers) to look at the logits, so you need to remove the activation. What loss are you using?

@HugoTex98
Copy link
Author

Yes, I already removed the activation function! For the loss I'm using the MSE @enryH

@lenbrocki
Copy link

lenbrocki commented Jan 14, 2022

@HugoTex98 If you like you can also check out our paper https://arxiv.org/abs/1910.13140 that goes beyond explaining single dimensions in the latent space.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants