快速将NLTK解析为语法树

5 投票
1 回答
4752 浏览
提问于 2025-04-18 10:45

我正在尝试把几百个句子解析成它们的语法树,而且我需要快速完成这项工作。问题是,如果我使用NLTK这个工具,就必须定义一个语法规则,但我并不知道具体的规则,只知道这些句子是英语的。我试过使用这个统计解析器,它在我的需求上效果很好,但速度可以更快一些。有没有办法在不定义语法的情况下使用NLTK进行解析呢?在这个代码片段中,我使用了一个处理池来“并行”处理,但速度还是不够理想。

import pickle
import re
from stat_parser.parser import Parser
from multiprocessing import Pool
import HTMLParser
def multy(a):
    global parser
    lst=re.findall('(\S.+?[.!?])(?=\s+|$)',a[1])
    if len(lst)==0:
        lst.append(a[1])
    try:
        ssd=parser.norm_parse(lst[0])
    except:
        ssd=['NNP','nothing']
    with open('/var/www/html/internal','a') as f:
        f.write("[[ss")
        pickle.dump([a[0],ssd], f)
        f.write("ss]]")
if __name__ == '__main__':
    parser=Parser()
    with open('/var/www/html/interface') as f:
        data=f.read()
    data=data.split("\n")
    p = Pool(len(data))
    Totalis_dict=dict()
    listed=list()
    h = HTMLParser.HTMLParser()
    with open('/var/www/html/internal','w') as f:
        f.write("")
    for ind,each in enumerate(data):
        listed.append([str(ind),h.unescape(re.sub('[^\x00-\x7F]+','',each))])
    p.map(multy,listed)

1 个回答

11

解析是一项比较耗费计算资源的操作。如果你想要更好的性能,可以考虑使用一个更成熟的解析器,比如bllip。这个解析器是用C++写的,经过了一个团队长时间的开发和优化。而且,它还有一个Python模块可以和它进行交互。

下面是一个比较bllip和你正在使用的解析器的例子:

import timeit

# setup stat_parser
from stat_parser import Parser
parser = Parser()

# setup bllip
from bllipparser import RerankingParser
from bllipparser.ModelFetcher import download_and_install_model
# download model (only needs to be done once)
model_dir = download_and_install_model('WSJ', '/tmp/models')
# Loading the model is slow, but only needs to be done once
rrp = RerankingParser.from_unified_model_dir(model_dir)

sentence = "In linguistics, grammar is the set of structural rules governing the composition of clauses, phrases, and words in any given natural language."

if __name__=='__main__':
    from timeit import Timer
    t_bllip = Timer(lambda: rrp.parse(sentence))
    t_stat = Timer(lambda: parser.parse(sentence))
    print "bllip", t_bllip.timeit(number=5)
    print "stat", t_stat.timeit(number=5)

在我的电脑上,它的运行速度大约快了10倍:

(vs)[jonathan@ ~]$ python /tmp/test.py 
bllip 2.57274985313
stat 22.748554945

另外,目前有一个请求正在进行中,想把bllip解析器整合进NLTK:https://github.com/nltk/nltk/pull/605

还有,你在问题中提到:“我不知道,只知道它会是英语。”如果你的意思是它需要解析其他语言,那就会复杂得多。这些统计解析器是基于一些输入数据训练出来的,通常是来自《华尔街日报》的解析内容,存储在Penn TreeBanks里。有些解析器会提供其他语言的训练模型,但你需要先识别出语言,然后再把合适的模型加载到解析器中。

撰写回答