2017-10-26 19:46:11 +03:00
|
|
|
|
#!/usr/bin/env python
|
|
|
|
|
# coding: utf8
|
2017-11-01 02:43:22 +03:00
|
|
|
|
"""A simple example of extracting relations between phrases and entities using
|
2017-10-26 19:46:11 +03:00
|
|
|
|
spaCy's named entity recognizer and the dependency parse. Here, we extract
|
|
|
|
|
money and currency values (entities labelled as MONEY) and then check the
|
|
|
|
|
dependency tree to find the noun phrase they are referring to – for example:
|
|
|
|
|
$9.4 million --> Net income.
|
|
|
|
|
|
2017-11-07 03:22:30 +03:00
|
|
|
|
Compatible with: spaCy v2.0.0+
|
2017-10-26 19:46:11 +03:00
|
|
|
|
"""
|
|
|
|
|
from __future__ import unicode_literals, print_function
|
|
|
|
|
|
|
|
|
|
import plac
|
|
|
|
|
import spacy
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEXTS = [
|
2018-12-02 06:26:26 +03:00
|
|
|
|
"Net income was $9.4 million compared to the prior year of $2.7 million.",
|
|
|
|
|
"Revenue exceeded twelve billion dollars, with a loss of $1b.",
|
2017-10-26 19:46:11 +03:00
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@plac.annotations(
|
2018-12-02 06:26:26 +03:00
|
|
|
|
model=("Model to load (needs parser and NER)", "positional", None, str)
|
|
|
|
|
)
|
|
|
|
|
def main(model="en_core_web_sm"):
|
2017-10-26 19:46:11 +03:00
|
|
|
|
nlp = spacy.load(model)
|
|
|
|
|
print("Loaded model '%s'" % model)
|
|
|
|
|
print("Processing %d texts" % len(TEXTS))
|
|
|
|
|
|
|
|
|
|
for text in TEXTS:
|
|
|
|
|
doc = nlp(text)
|
|
|
|
|
relations = extract_currency_relations(doc)
|
|
|
|
|
for r1, r2 in relations:
|
2018-12-02 06:26:26 +03:00
|
|
|
|
print("{:<10}\t{}\t{}".format(r1.text, r2.ent_type_, r2.text))
|
2017-10-26 19:46:11 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extract_currency_relations(doc):
|
|
|
|
|
# merge entities and noun chunks into one token
|
2017-11-20 15:57:51 +03:00
|
|
|
|
spans = list(doc.ents) + list(doc.noun_chunks)
|
|
|
|
|
for span in spans:
|
2017-10-26 19:46:11 +03:00
|
|
|
|
span.merge()
|
|
|
|
|
|
|
|
|
|
relations = []
|
2018-12-02 06:26:26 +03:00
|
|
|
|
for money in filter(lambda w: w.ent_type_ == "MONEY", doc):
|
|
|
|
|
if money.dep_ in ("attr", "dobj"):
|
|
|
|
|
subject = [w for w in money.head.lefts if w.dep_ == "nsubj"]
|
2017-10-26 19:46:11 +03:00
|
|
|
|
if subject:
|
|
|
|
|
subject = subject[0]
|
|
|
|
|
relations.append((subject, money))
|
2018-12-02 06:26:26 +03:00
|
|
|
|
elif money.dep_ == "pobj" and money.head.dep_ == "prep":
|
2017-10-26 19:46:11 +03:00
|
|
|
|
relations.append((money.head.head, money))
|
|
|
|
|
return relations
|
|
|
|
|
|
|
|
|
|
|
2018-12-02 06:26:26 +03:00
|
|
|
|
if __name__ == "__main__":
|
2017-10-26 19:46:11 +03:00
|
|
|
|
plac.call(main)
|
|
|
|
|
|
|
|
|
|
# Expected output:
|
|
|
|
|
# Net income MONEY $9.4 million
|
|
|
|
|
# the prior year MONEY $2.7 million
|
|
|
|
|
# Revenue MONEY twelve billion dollars
|
|
|
|
|
# a loss MONEY 1b
|