首页 > 解决方案 > 如何在 Python 上使用 Wordnet 3.1 和 NLTK?

问题描述

重要编辑

正如@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 网站(此处为当前版本链接)中所写,我在下面引用:

仅限 WordNet 3.1 数据库文件

您可以下载 WordNet 3.1 数据库文件。请注意,这不是上面的完整包,也不包含任何运行 WordNet 的代码。但是,您可以用这些文件替换 3.0 本地安装的数据库目录中的文件,然后 WordNet 界面将运行,从 3.1 数据库返回条目。这只是 WordNet 3.1 数据库文件的压缩 tar 文件。

我尝试下载 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) 一起使用的建议或解决方案都会有所帮助。

提前致谢。

标签: pythonnltkwordnet

解决方案


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

我将要点中提供的代码分为 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文件夹wordnet到的wordnet_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")

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

第 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 中运行以下代码,发现它实际上运行的是 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 版或破坏它。


推荐阅读