Question

Is there a way to capture WordNet selectional restrictions (such as +animate, +human, etc.) from synsets through NLTK? Or is there any other way of providing semantic information about synset? The closest I could get to it were hypernym relations.

Was it helpful?

Solution

It depends on what is your "selectional restrictions" or i would call it semantic features, because in classic semantics, there exists a world of concepts and to compare between concepts we have to find

  • discriminating features (i.e. features of the concepts that are used to distinguish them from each other) and
  • similarity features (i.e. features of the concepts similar and highlights the need to differentiate them)

For example:

Man is [+HUMAN], [+MALE], [+ADULT]
Woman is [+HUMAN], [-MALE], [+ADULT]

[+HUMAN] and [+ADULT] = similarity features
[+-MALE] is the discrimating features

The common problem of traditional semantics and applying this theory in computational semantics is the question of

"Is there a specific list of features that we can use to compare any

"If so, what are the features on this list?" concepts?"

(see www.acl.ldc.upenn.edu/E/E91/E91-1034.pdf‎ for more details)

Getting back to WordNet, I can suggest 2 methods to resolve the "selection restrictions"

First, Check the hypernyms for discriminating features, but first you must decide what is the discriminating features. To differentiate an animal from humans, let's take the discriminating features as [+-human] and [+-animal].

from nltk.corpus import wordnet as wn

# Concepts to compare
dog_sense = wn.synsets('dog')[0] # It's http://goo.gl/b9sg9X
jb_sense = wn.synsets('James_Baldwin')[0] # It's http://goo.gl/CQQIG9

# To access the hypernym_paths()[0]
# It's weird for that hypernym_paths gives a list of list rather than a list, nevertheless it works.
dog_hypernyms = dog_sense.hypernym_paths()[0]
jb_hypernyms = jb_sense.hypernym_paths()[0]


# Discriminating features in terms of concepts in WordNet
human = wn.synset('person.n.01') # i.e. [+human]
animal = wn.synset('animal.n.01') # i.e. [+animal]

try:
  assert human in jb_hypernyms and animal not in jb_hypernyms
  print "James Baldwin is human"
except:
  print "James Baldwin is not human"

try:
  assert human in dog_hypernyms and animal not in dog_hypernyms
  print "Dog is an animal"
except:
  print "Dog is not an animal"

Second, Check for similarity measures as @Jacob had suggested.

dog_sense = wn.synsets('dog')[0] # It's http://goo.gl/b9sg9X
jb_sense = wn.synsets('James_Baldwin')[0] # It's http://goo.gl/CQQIG9

# Features to check against whether the 'dubious' concept is a human or an animal
human = wn.synset('person.n.01') # i.e. [+human]
animal = wn.synset('animal.n.01') # i.e. [+animal]

if dog_sense.wup_similarity(animal) > dog_sense.wup_similarity(human):
  print "Dog is more of an animal than human"
elif dog_sense.wup_similarity(animal) < dog_sense.wup_similarity(human):
  print "Dog is more of a human than animal"

OTHER TIPS

You could try using some of the similarity functions with handpicked synsets, and use that to filter. But it's essentially the same as following the hypernym tree - afaik all the wordnet similarity functions use hypernym distance in their calculations. Also, there's a lot of optional attributes of a synset that might be worth exploring, but their presence can be very inconsistent.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top