在尝试使用PunktTokenizer
重新训练一个句子分词器模型时,NLTK代码占用了超过200GB的RAM,并进行了大量交换操作,似乎在两天的训练后仍未结束。
import pickle
from nltk.tokenize.punkt import PunktSentenceTokenizer
tokenizer = PunktSentenceTokenizer()
with open('wikipedia-en.txt') as fin:
text = fin.read()
tokenizer.train(text)
with open('wiki-en.pkl') as fout:
pickle.dump(tokenizer, fout)
对于我们现在需要训练的大规模数据集来说,这段代码似乎效率不高。
让我们将此问题保留以跟踪与Punkt相关的其他问题,直到我们获得该算法的更好版本。
7条答案
按热度按时间jdg4fx2g1#
将
_pair_iter
替换为bigrams
这看起来像是我们在
nltk.util.ngrams
中使用的 ngram 函数:https://github.com/nltk/nltk/blob/develop/nltk/tokenize/punkt.py#L306我们不应该同时维护
_pair_iter(it)
和bigrams(it)
。将
counter
替换为bounter
基于
collections.Counter
的 FreqDist 对象具有较高的内存占用,我们应该用bounter
替换它。Punkt 代码中有几个 FreqDist 的使用示例,其中
self._collocation_fdist
应该从具有较低内存需求的bounter
中受益最大,即:https://github.com/nltk/nltk/blob/develop/nltk/tokenize/punkt.py#L631常量(魔术数字)应该是参数
在
PunktTrainer
中有几个示例使用常量值来设置算法的阈值/退避,它们没有暴露给用户,而是作为固定的常量设置。它们应该是可调参数。例如:https://github.com/nltk/nltk/blob/develop/nltk/tokenize/punkt.py#L671监控和优化 for 循环
_train_tokens()
中的 for 循环通过多遍遍历数据集。很可能无法避免多遍,但我们应该能够使用一些并行化来优化这些遍历,如果可能的话,不要精确计算计数,而是用一些基于字符串的算法近似计算计数(我们需要研究一下)。
有一些看起来彼此独立的 for 循环,也可以并行化。
清理 Py2 和 Py3 字符串兼容性代码
nltk.token.punkt.py
包含各种文本类型检查和兼容性检查,它们应该统一为使用原生的nltk.compat
代码或six
:8hhllhi22#
你忽略了一个事实,那就是
PunktTrainer
有一个功能来管理由于不常见元素而导致的内存使用。这是一个名为freq_threshold
的方法,旨在在训练批次之间进行调用。是的,它应该被更清晰地记录下来。我们已经用维基百科上的punkt模型训练了好几年,但当我第一次这样做时,它偶尔会使用
freq_threshold
来修剪无用的统计信息。bounters
应该会受益匪浅,但我认为你的其他建议更改主要是表面文章。像ABBREV
这样的参数会在用户仅通过子类化就可以覆盖常量的情况下给接口添加噪声。avwztpqn3#
是的,我在阅读代码以了解发生了什么,同时列出可以改进的地方。但
bounter
替换是这里的主要目标=)我也发现 Punkt 词元分词器很有用,也许将其暴露出来会更好,而不是将其隐藏在
PunktLanguageVars
中。酷,我不知道还有个
freq_threshold
参数!仍在阅读代码。ldioqlga4#
我认为它之前被更多地曝光,并引起了困惑。
xggvc2p65#
它完成了我之前用其他正则表达式处理非英语语言时所完成的50%的清洗任务。我想我还需要查看代码历史记录。
有趣的是:#746 和 0b91a71
不幸的是,从
FreqDist
转换到bounter
并不容易解决。遇到的第一个问题是,FreqDist允许任何对象作为键,而bounter只允许unicode对象或字节缓冲区。t2a7ltrp6#
Collapsing multiply loops might help. In the current code,
PunktTrainer
is looping through to:sentbreak
, (ii)ellipsis
, (iii)period_final
token.ellipsis
information from step 3tokens.sentbreak
information from step 3token.type_no_period
information, (ii)_sent_starter_fdist
and (iii)_collocation_fdist
distributionsni65a41a7#
你忽略了一个事实,PunktTrainer有一个功能可以管理由于不频繁元素导致的内存使用。这个方法叫做freq_threshold,它用于在批次训练之间调用。是的,它应该有更清晰的文档说明。
@alvations@jnothman 我如何使用freq_threshold和批量训练?我想要训练大约6万个TXT文件。
这是我目前的代码:
这段代码看起来正确吗?我该如何知道要使用哪个freq_threshold?