Ответ 1
Технически без фиктивного корня оба синтаксиса car
и automobile
не имеют никакой связи друг с другом:
>>> from nltk.corpus import wordnet as wn
>>> x = wn.synset('car.n.01')
>>> y = wn.synset('automobile.v.01')
>>> print x.shortest_path_distance(y)
None
>>> print y.shortest_path_distance(x)
None
Теперь давайте внимательно рассмотрим проблему фиктивного корня. Во-первых, в NLTK есть аккуратная функция, которая говорит, нужен ли synset фиктивный корень:
>>> x._needs_root()
False
>>> y._needs_root()
True
Затем, когда вы смотрите код path_similarity
(http://nltk.googlecode.com/svn-/trunk/doc/api/nltk.corpus.reader.wordnet-pysrc.html#Synset.path_similarity), вы можете увидеть:
def path_similarity(self, other, verbose=False, simulate_root=True):
distance = self.shortest_path_distance(other, \
simulate_root=simulate_root and self._needs_root())
if distance is None or distance < 0:
return None
return 1.0 / (distance + 1)
Итак, для automobile
synset этот параметр simulate_root=simulate_root and self._needs_root()
всегда будет True
при попытке y.path_similarity(x)
, и при попытке x.path_similarity(y)
он всегда будет False
, так как x._needs_root()
есть False
:
>>> True and y._needs_root()
True
>>> True and x._needs_root()
False
Теперь, когда path_similarity()
переходит к shortest_path_distance()
(https://nltk.googlecode.com/svn/trunk/doc/api/nltk.corpus.reader.wordnet-pysrc.html#Synset.shortest_path_distance), а затем к hypernym_distances()
, он попытается позвонить для списка гиперних, чтобы проверить их расстояния, без simulate_root = True
, синхронизация automobile
не будет подключаться к car
и наоборот:
>>> y.hypernym_distances(simulate_root=True)
set([(Synset('automobile.v.01'), 0), (Synset('*ROOT*'), 2), (Synset('travel.v.01'), 1)])
>>> y.hypernym_distances()
set([(Synset('automobile.v.01'), 0), (Synset('travel.v.01'), 1)])
>>> x.hypernym_distances()
set([(Synset('object.n.01'), 8), (Synset('self-propelled_vehicle.n.01'), 2), (Synset('whole.n.02'), 8), (Synset('artifact.n.01'), 7), (Synset('physical_entity.n.01'), 10), (Synset('entity.n.01'), 11), (Synset('object.n.01'), 9), (Synset('instrumentality.n.03'), 5), (Synset('motor_vehicle.n.01'), 1), (Synset('vehicle.n.01'), 4), (Synset('entity.n.01'), 10), (Synset('physical_entity.n.01'), 9), (Synset('whole.n.02'), 7), (Synset('conveyance.n.03'), 5), (Synset('wheeled_vehicle.n.01'), 3), (Synset('artifact.n.01'), 6), (Synset('car.n.01'), 0), (Synset('container.n.01'), 4), (Synset('instrumentality.n.03'), 6)])
Итак, теоретически, правый path_similarity
равен 0/None, но из-за параметра simulate_root=simulate_root and self._needs_root()
nltk.corpus.wordnet.path_similarity()
в API NLTK не является коммутативным.
НО код также не ошибочен/прослушивается, так как сравнение любого расстояния между синхронизацией путем прохождения корня будет постоянно далеким, так как положение манекена *ROOT*
никогда не изменится, поэтому лучше всего это сделать для вычисления path_similarity:
>>> from nltk.corpus import wordnet as wn
>>> x = wn.synset('car.n.01')
>>> y = wn.synset('automobile.v.01')
# When you NEVER want a non-zero value, since going to
# the *ROOT* will always get you some sort of distance
# from synset x to synset y
>>> max(wn.path_similarity(x,y), wn.path_similarity(y,x))
# when you can allow None in synset similarity comparison
>>> min(wn.path_similarity(x,y), wn.path_similarity(y,x))