如何在 Python 上将 Wordnet 3.1 与 NLTK 一起使用?

How to use Wordnet 3.1 with NLTK on Python?

重要编辑

@Pengin 在评论中告知。 NLTK 从 2022 年 1 月开始支持 WordNet 3.1。因此这个问题现在被认为是无关紧要的。


我的研究工作需要使用 Wordnet 3.1,但 NLTK (python) 附带默认的 wordnet 版本:3.0。 我使用最新版本的 Wordnet 很重要。

>>> from nltk.corpus import wordnet
>>> wordnet.get_version()
'3.0'

但是,由于 NLTK 3.1 是最新版本,我找不到任何方法来使用 nltk.download() 下载和访问它,我正在寻找解决方法。

正如 Wordnet 网站 (current version link here) 所写,我在下面引用:

WordNet 3.1 DATABASE FILES ONLY

You can download the WordNet 3.1 database files. Note that this is not a full package as those above, nor does it contain any code for running WordNet. However, you can replace the files in the database directory of your 3.0 local installation with these files and the WordNet interface will run, returning entries from the 3.1 database. This is simply a compressed tar file of the WordNet 3.1 database files.

我尝试下载 Wordnet 3.1 数据库文件并将它们替换为 C:\Users\<username>\AppData\Roaming\nltk_data\corpora(在 Windows 系统上)的默认 Wordnet 文件。我怀疑它不会起作用,因为说明是要替换 Wordnet 软件安装中的数据库文件,但我仍然尝试了。

在 运行 wordnet.get_version() 上,我收到以下错误。

---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-2-d64ae1e68b36> in <module>
----> 1 wordnet.get_version()

~\anaconda3\lib\site-packages\nltk\corpus\util.py in __getattr__(self, attr)
    118             raise AttributeError("LazyCorpusLoader object has no attribute '__bases__'")
    119 
--> 120         self.__load()
    121         # This looks circular, but its not, since __load() changes our
    122         # __class__ to something new:

~\anaconda3\lib\site-packages\nltk\corpus\util.py in __load(self)
     86 
     87         # Load the corpus.
---> 88         corpus = self.__reader_cls(root, *self.__args, **self.__kwargs)
     89 
     90         # This is where the magic happens!  Transform ourselves into

~\anaconda3\lib\site-packages\nltk\corpus\reader\wordnet.py in __init__(self, root, omw_reader)
   1136 
   1137         # Load the lexnames
-> 1138         for i, line in enumerate(self.open("lexnames")):
   1139             index, lexname, _ = line.split()
   1140             assert int(index) == i

~\anaconda3\lib\site-packages\nltk\corpus\reader\api.py in open(self, file)
    206         """
    207         encoding = self.encoding(file)
--> 208         stream = self._root.join(file).open(encoding)
    209         return stream
    210 

~\anaconda3\lib\site-packages\nltk\data.py in join(self, fileid)
    335     def join(self, fileid):
    336         _path = os.path.join(self._path, fileid)
--> 337         return FileSystemPathPointer(_path)
    338 
    339     def __repr__(self):

~\anaconda3\lib\site-packages\nltk\compat.py in _decorator(*args, **kwargs)
     39     def _decorator(*args, **kwargs):
     40         args = (args[0], add_py3_data(args[1])) + args[2:]
---> 41         return init_func(*args, **kwargs)
     42 
     43     return wraps(init_func)(_decorator)

~\anaconda3\lib\site-packages\nltk\data.py in __init__(self, _path)
    313         _path = os.path.abspath(_path)
    314         if not os.path.exists(_path):
--> 315             raise IOError("No such file or directory: %r" % _path)
    316         self._path = _path
    317 

OSError: No such file or directory: 'C:\Users\Punit Singh\AppData\Roaming\nltk_data\corpora\wordnet\lexnames'

然后我检查了文件结构,我在下面列出了之前和之后的树。

Wordnet 3.0 中的文件树

wordnet
├── adj.exc
├── adv.exc
├── citation.bib
├── cntlist.rev
├── data.adj
├── data.adv
├── data.noun
├── data.verb
├── index.adj
├── index.adv
├── index.noun
├── index.sense
├── index.verb
├── lexnames
├── LICENSE
├── noun.exc
├── README
├── verb.exc

Wordnet 3.1 中的文件树

wordnet
├── adj.exc
├── adv.exc
├── cntlist
├── cntlist.rev
├── cousin.exc
├── data.adj
├── data.adv
├── data.noun
├── data.verb
├── index.adj
├── index.adv
├── index.noun
├── index.sense
├── index.verb
├── log.grind.3.1
├── noun.exc
├── sentidx.vrb
├── dbfiles
    ├── adj.all
    ├── adj.pert
    ├── adj.ppl
    ├── adv.all
    ├── cntlist
    ├── noun.act
    ├── noun.animal
    ├── noun.artifact
    ├── noun.attribute
    ├── noun.body
    ├── noun.cognition
    ├── noun.communication
    ├── noun.event
    ├── noun.feeling
    ├── noun.food
    ├── noun.group
    ├── noun.location
    ├── noun.motive
    ├── noun.object
    ├── noun.person
    ├── noun.phenomenon
    ├── noun.plant
    ├── noun.possession
    ├── noun.process
    ├── noun.quantity
    ├── noun.relation
    ├── noun.shape
    ├── noun.state
    ├── noun.substance
    ├── noun.time
    ├── noun.Tops
    ├── verb.body
    ├── verb.change
    ├── verb.cognition
    ├── verb.communication
    ├── verb.competition
    ├── verb.consumption
    ├── verb.contact
    ├── verb.creation
    ├── verb.emotion
    ├── verb.Framestext
    ├── verb.motion
    ├── verb.perception
    ├── verb.possession
    ├── verb.social
    ├── verb.stative
    ├── verb.weather

关于如何将 Wordnet 3.1 与 NLTK (Python) 结合使用的任何建议或解决方案都会有所帮助。

提前致谢。

经过大量搜索和反复试验,我能够在 NLTK (Python) 上使用 Wordnet 3.1。我调整了 this gist 使其工作。我在下面提供详细信息。

我将要点中提供的代码分为 3 个部分。

第 1 部分。download_extract.py

import os

nltkdata_wn = '/path/to/nltk_data/corpora/wordnet/'
wn31 = "http://wordnetcode.princeton.edu/wn3.1.dict.tar.gz"

if not os.path.exists(nltkdata_wn+'_3.0'):
    os.mkdir(nltkdata_wn+'_3.0')
os.system('mv '+nltkdata_wn+"* "+nltkdata_wn+"_3.0/")

if not os.path.exists('wn3.1.dict.tar.gz'):
    os.system('wget '+wn31)

os.system("tar zxf wn3.1.dict.tar.gz -C "+nltkdata_wn)
os.system("mv "+nltkdata_wn+"dict/* "+nltkdata_wn)
os.rmdir(nltkdata_wn + 'dict')

用于备份现有的Wordnet 3.0文件夹wordnetwordnet_3.0,下载Wordnet 3.1数据库,放入文件夹wordnet。由于我在 Windows 系统上,因此我手动完成了此操作。

第 2 部分。create_lexnames.py

import os

nltkdata_wn = '/path/to/nltk_data/corpora/wordnet/'
dbfiles = nltkdata_wn+'dbfiles'

with open(nltkdata_wn+'lexnames', 'w') as fout:
    for i,j in enumerate(sorted(os.listdir(dbfiles))):
        pos = j.partition('.')[0]
        if pos == "noun":
            syncat = 1
        elif pos == "verb":
            syncat = 2
        elif pos == "adj":
            syncat = 3
        elif pos == "adv":
            syncat = 4
        elif j == "cntlist":
            syncat = "cntlist"
        fout.write("\t".join([str(i).zfill(2),j,str(syncat)])+"\n")

这会在 wordnet 文件夹中创建所需的 lexnames 文件。

第 3 部分。testing_wn31.py

from nltk.corpus import wordnet as wn

nltkdata_wn = '/path/to/nltk_data/corpora/wordnet/'

# Checking generated lexnames file.
for i, line in enumerate(open(nltkdata_wn + 'lexnames','r')):
    index, lexname, _ = line.split()
    ##print line.split(), int(index), i
    assert int(index) == i

# Testing wordnet function.
print(wn.synsets('dog'))
for i in wn.all_synsets():
    print(i, i.pos(), i.definition())

这测试了生成的 lexname 文件,还测试了 wordnet 函数是否正常工作。

完成此过程后,我 运行 跟踪 python 中的代码,发现它实际上是 运行ning 版本 3.1

>>> from nltk.corpus import wordnet
>>> wordnet.get_version()
'3.1'

注意事项

替换 Wordnet 3.1 数据库后,您会注意到,如果 运行 以下代码

>>> import nltk
>>> nltk.download()

在下载对话框中,您会看到在Corpora选项卡下,Wordnet将显示为out of date,您不应该尝试更新它,因为它会替换将 wordnet 升级到 3.0 版或破坏它。