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

Multiple Sentence Inputs #24

Closed
jaderabbit opened this issue Sep 12, 2016 · 10 comments
Closed

Multiple Sentence Inputs #24

jaderabbit opened this issue Sep 12, 2016 · 10 comments

Comments

@jaderabbit
Copy link

My model takes 2 sentences as input, as well as a number of continuous values.
The sentences are converted into 2 sentence vectors, operations are applied to them, and then are passed on to the next model along with the continuous values. This model then predicts semantic similarity (softmax) based on cosine distance between sentence vectors and the extra continuous valued features.

I would like to see if I can adapt parts of the LimeTextExplainer in order to explain which parts of each sentence result in high semantic similarity.

Do you have any suggestions on where I should begin? Is it a viable idea? Any help would be appreciated

@marcotcr
Copy link
Owner

Oh, this is interesting - you have both text AND continuous features.
If all you care about is explaining the text parts while keeping the continuous values fixed, it should be easy, as the only difference is that you have two sentences instead of one. What you would need to do in this case is to put both sentences in a string, separated by a character that is not caught by the split_expression parameter (see the initializer of LimeTextExplainer). You then could define a classifier_fn that takes whatever text LIME gives is, splits it into two sentences, computes the sentence vectors and etc. Your code would look something like this:

def get_classifier_fn(continuous_features):  
    def classifier_fn(text_list):
        ret = []
        for text in text_list: 
            sentence1, sentence2 = text.split(SPLIT_CHARACTER)
            # assuming this returns a number between 0 and 1
            ret.append(model.predict_similarity(get_embedding(sentence1), 
                                                get_embedding(sentence2),
                                                continuous_features))
        return ret
    return classifier_fn

Then, if you wanted to explain a particular instance, you would have to do something like this:

def explain_instance(instance):  
   text = '%s %s %s' % (instance.sentence1, SPLIT_CHARACTER, instance.sentence2)
   fn = get_classifier_fn(instance.continuous_features)
   explainer = LimeTextExplainer(split_expression=SPLIT_EXPRESSION, bow=BOW)
   return explainer.explain_instance(text, fn, labels=(0,))

You may have to be a bit creative if you want to use the visualizations we have, since the text displayed will have both sentences. Also, you have to think if it makes sense to use bow=True or False in this case. If you're doing anything with sequences, I would say False makes more sense.

If you want to explain the impact of the words and the numerical features, you'll have to write a function that perturbs both at the same time. If this is the case, you would want to do a mix of __data_labels_distances in lime_text.py and __data_inverse in lime_tabular.py.

Both are viable ideas, the second one is definitely a bit more work.
I would be very interested to see what you end up with, I've never thought about this particular use case. If you are comfortable sharing what the application is, please tell me over email : ).
Let me know if you have any more questions too.

Best,

@jaderabbit
Copy link
Author

Thank you so so much! Your explanations are super helpful. For now, I'm particularly interested in the text components so will focus on that. I will definitely drop you a mail :)

@LeZhengThu
Copy link

Hi, in code "explainer.explain_instance(text, fn, labels=(0,))", the default value is "labels=(1,)" and explanation in your original code is "labels: iterable with labels to be explained." I wonder what this variable exactly stands for? Thanks.

@marcotcr
Copy link
Owner

This parameter is there for multi-class classification problems, and it defines for which classes (or labels) we want to generate explanations for. The default is 1 because usually what we have is two-class classification, where we only care about explaining label 1 (since the explanation for label 0 is the opposite).
The code assumes that the classifier function returns an array with a column per label (the probability for each), while in this example we are only outputting one number. That is why I set labels=(0,).

@LeZhengThu
Copy link

Thanks so much for your quick response. BTW, is there a chance to only explain several particular features? Which parameter should I set?

@marcotcr
Copy link
Owner

Do you mean restrict the explanation to a particular set of features? If so, there is no parameter for that.

@Aureole-1210
Copy link

Thank you so so much! Your explanations are super helpful. For now, I'm particularly interested in the text components so will focus on that. I will definitely drop you a mail :)

Thank you so so much! Your explanations are super helpful. For now, I'm particularly interested in the text components so will focus on that. I will definitely drop you a mail :)

Hi! I am conducting the same task as yours. But I find the final score of every token is similar. I think it's incorrect. Could you please tell me how you complete it?
More appreciate!!!!!!!!

@JINHXu
Copy link

JINHXu commented Feb 1, 2024

LimeTextExplainer

can someone give an example SPLIT_EXPRESSION? 🙏

@JINHXu
Copy link

JINHXu commented Feb 1, 2024

@marcotcr can you give an example for SPLIT_EXPRESSION? 🙏 I have a very similar use case meanwhile would not know what to pass to SPLIT_EXPRESSION. many thanks! 🙏 documentations here are not helping:

split_expression – Regex string or callable. If regex string, will be used with re.split. If callable, the function should return a list of tokens.

@JINHXu
Copy link

JINHXu commented Feb 1, 2024

apparently without using SPLIT_EXPRESSION, the split_char is considered part of the input and get interpreted

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

5 participants