Extract list of Persons and Organizations using Stanford NER Tagger in NLTK

Thanks to the link discovered by @Vaulstein, it is clear that the trained Stanford tagger, as distributed (at least in 2012) does not chunk named entities. From the accepted answer:

Many NER systems use more complex labels such as IOB labels, where codes like B-PERS indicates where a person entity starts. The CRFClassifier class and feature factories support such labels, but they’re not used in the models we currently distribute (as of 2012)

You have the following options:

  1. Collect runs of identically tagged words; e.g., all adjacent words tagged PERSON should be taken together as one named entity. That’s very easy, but of course it will sometimes combine different named entities. (E.g. New York, Boston [and] Baltimore is about three cities, not one.) Edit: This is what Alvas’s code does in the accepted anwser. See below for a simpler implementation.

  2. Use nltk.ne_chunk(). It doesn’t use the Stanford recognizer but it does chunk entities. (It’s a wrapper around an IOB named entity tagger).

  3. Figure out a way to do your own chunking on top of the results that the Stanford tagger returns.

  4. Train your own IOB named entity chunker (using the Stanford tools, or the NLTK’s framework) for the domain you are interested in. If you have the time and resources to do this right, it will probably give you the best results.

Edit: If all you want is to pull out runs of continuous named entities (option 1 above), you should use itertools.groupby:

from itertools import groupby
for tag, chunk in groupby(netagged_words, lambda x:x[1]):
    if tag != "O":
        print("%-12s"%tag, " ".join(w for w, t in chunk))

If netagged_words is the list of (word, type) tuples in your question, this produces:

PERSON       Rami Eid
ORGANIZATION Stony Brook University
LOCATION     NY

Note again that if two named entities of the same type occur right next to each other, this approach will combine them. E.g. New York, Boston [and] Baltimore is about three cities, not one.

Leave a Comment