jenojp / negspacy

spaCy pipeline object for negating concepts in text
MIT License
274 stars 36 forks source link

Applying Negex to Adjectives #50

Open ZeroCool2u opened 2 years ago

ZeroCool2u commented 2 years ago

Is there a straight forward way to apply Negex to adjectives? I already incorporated Negex into my pipeline with my own custom component, but I didn't realize until after the fact that it seems to only be searching for negations in relation to Named Entities. For example, I was hoping to apply it, so I'd get positive matches on something like:


doc = nlp("Eve is not nice. Eve is friendly. Eve is not chill.")
for s in doc.sents:
    for t in s.tokens:
      print(t._.negex, t.text)

True nice
False friendly
True chill

It seems like this is not supported at the moment, but if anyone has any advice on how to customize Negex to achieve this it would be much appreciated. Also, if there's a good reason to not bother trying to do this at all, would love to understand that too.

Thanks!

jenojp commented 2 years ago

I suppose you could check every single token (rather than entities) in negspacy/negation.py starting at line 296.

This library's goal was to implement the Negex algorithm in spaCy which looks at named entities so it's probably not an additional feature I'd fold into the package.

ZeroCool2u commented 2 years ago

Got it. I'll look into trying it on my own fork. If I get it working maybe I can post the changes here for others to find if they're interested.

casparhsws commented 8 months ago

Hi @ZeroCool2u , this merged PR allows you to apply negex to span groups. You could write a function to add adjectives to a span group and then apply negex to that group. Something like... (not tested)

import spacy
from spacy.language import Language

@Language.component("adjectives_to_spans")
def adjectives_to_spans(doc):
    adjective_spans = [ent for ent in doc.ents if ent.label_ == "ADJ"]
    doc.spans["adjectives"] = adjective_spans
    return doc

nlp = spacy.load("en_core_web_sm")
nlp.add_pipe("sentencizer", last=True)
nlp.add_pipe("adjectives_to_spans", last=True)
nlp.add_pipe("negex", last=True, config={"span_keys": ["adjectives"]})
nlp(doc)
ZeroCool2u commented 8 months ago

Thanks for following up here!

I ended up implementing it myself, but it was not super simple and didn't think it was worth posting. Your example here looks shockingly similar to some of the most relevant code I ended up writing though and I imagine it largely accomplishes what I was going for.

Anyone that finds this thread in the future should definitely try this suggested approach.