spaCy Pattern Matching - OR statements

Viewed 551

is there a way to use or apply "OR" logic to pattern matcher? Something like can be done with regex? I don't want to have to create individual parsers for each occurrence, if possible (car, boat, bus, for example). I am also thinking that if I can do that, I can use a script to generate my rules. Any help would be appreciated.

Can I do something like the below, but without regex? Obviously, bus in this case might pick up other things.

import spacy
from spacy.matcher import Matcher

nlp = spacy.load("en_core_web_sm")
matcher = Matcher(nlp.vocab)

matcher.add("VEHICLE", None,
            [{"LOWER":{"REGEX":"car|boat|bus"}}]
           )

text = "I saw a car pulling a boat today, which was really funny. I also saw a bus pulling a boat."

doc = nlp(text)
matches = matcher(doc)
2 Answers

If you have a list of items you want to use as patterns, create a list of dictionaries from it and pass as the third argument to matcher.add():

l = ['car', 'boat', 'bus']
patterns = [{"LOWER":x} for x in l]
matcher.add("VEHICLE", None, patterns)
>>> for _, start, end in matcher(doc):
    print(doc[start:end].text)
car
boat
bus
boat

The patterns will look like [{'LOWER': 'car'}, {'LOWER': 'boat'}, {'LOWER': 'bus'}].

The Matcher supports IN and NOT_IN operators that match values in lists:

import spacy
from spacy.matcher import Matcher

nlp = spacy.blank("en")
matcher = Matcher(nlp.vocab)
l = ['car', 'boat', 'bus']
matcher.add("VEHICLE", [[{"LOWER": {"IN": l}}]])
doc = nlp("This is a car.")
matches = matcher(doc)
for match_id, start, end in matches:
    print(nlp.vocab.strings[match_id], doc[start:end])

Output:

VEHICLE car

See: https://spacy.io/usage/rule-based-matching#adding-patterns-attributes-extended

Related