首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何保存Python NLTK对齐模型以供以后使用?

如何保存Python NLTK对齐模型以供以后使用?
EN

Stack Overflow用户
提问于 2015-05-12 23:25:51
回答 4查看 2.2K关注 0票数 14

在Python语言中,我使用NLTK's alignment module在平行文本之间创建单词对齐。对齐bitexts可能是一个耗时的过程,尤其是在大量语料库上完成时。如果有一天批量进行比对,并在以后使用这些比对,那就太好了。

代码语言:javascript
复制
from nltk import IBMModel1 as ibm
biverses = [list of AlignedSent objects]
model = ibm(biverses, 20)

with open(path + "eng-taq_model.txt", 'w') as f:
    f.write(model.train(biverses, 20))  // makes empty file

一旦创建了模型,我如何(1)将其保存到磁盘并(2)稍后重用它?

EN

回答 4

Stack Overflow用户

发布于 2015-05-13 20:18:28

直接的答案是对其进行腌制,请参阅https://wiki.python.org/moin/UsingPickle

但是因为IBMModel1返回一个lambda函数,所以不可能用默认的pickle / cPickle (参见https://github.com/nltk/nltk/blob/develop/nltk/align/ibm1.py#L74https://github.com/nltk/nltk/blob/develop/nltk/align/ibm1.py#L104)来pickle它。

所以我们将使用dill。首先,安装dill,请参阅Can Python pickle lambda functions?

代码语言:javascript
复制
$ pip install dill
$ python
>>> import dill as pickle

然后:

代码语言:javascript
复制
>>> import dill
>>> import dill as pickle
>>> from nltk.corpus import comtrans
>>> from nltk.align import IBMModel1
>>> bitexts = comtrans.aligned_sents()[:100]
>>> ibm = IBMModel1(bitexts, 20)
>>> with open('model1.pk', 'wb') as fout:
...     pickle.dump(ibm, fout)
...
>>> exit()

要使用酸洗模型,请执行以下操作:

代码语言:javascript
复制
>>> import dill as pickle
>>> from nltk.corpus import comtrans
>>> bitexts = comtrans.aligned_sents()[:100]
>>> with open('model1.pk', 'rb') as fin:
...     ibm = pickle.load(fin)
... 
>>> aligned_sent = ibm.align(bitexts[0])
>>> aligned_sent.words
['Wiederaufnahme', 'der', 'Sitzungsperiode']

如果您尝试pickle IBMModel1对象,它是一个lambda函数,您将得到以下结果:

代码语言:javascript
复制
>>> import cPickle as pickle
>>> from nltk.corpus import comtrans
>>> from nltk.align import IBMModel1
>>> bitexts = comtrans.aligned_sents()[:100]
>>> ibm = IBMModel1(bitexts, 20)
>>> with open('model1.pk', 'wb') as fout:
...     pickle.dump(ibm, fout)
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib/python2.7/copy_reg.py", line 70, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle function objects

(注:以上代码片段来自NLTK版本3.0.0)

在使用NLTK3.0.0的python3中,您也将面临同样的问题,因为IBMModel1返回一个λ函数:

代码语言:javascript
复制
alvas@ubi:~$ python3
Python 3.4.0 (default, Apr 11 2014, 13:05:11) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> from nltk.corpus import comtrans
>>> from nltk.align import IBMModel1
>>> bitexts = comtrans.aligned_sents()[:100]
>>> ibm = IBMModel1(bitexts, 20)
>>> with open('mode1.pk', 'wb') as fout:
...     pickle.dump(ibm, fout)
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
_pickle.PicklingError: Can't pickle <function IBMModel1.train.<locals>.<lambda> at 0x7fa37cf9d620>: attribute lookup <lambda> on nltk.align.ibm1 failed'

>>> import dill
>>> with open('model1.pk', 'wb') as fout:
...     dill.dump(ibm, fout)
... 
>>> exit()

alvas@ubi:~$ python3
Python 3.4.0 (default, Apr 11 2014, 13:05:11) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> from nltk.corpus import comtrans
>>> with open('model1.pk', 'rb') as fin:
...     ibm = dill.load(fin)
... 
>>> bitexts = comtrans.aligned_sents()[:100]
>>> aligned_sent = ibm.aligned(bitexts[0])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'IBMModel1' object has no attribute 'aligned'
>>> aligned_sent = ibm.align(bitexts[0])
>>> aligned_sent.words
['Wiederaufnahme', 'der', 'Sitzungsperiode']

(注:在python3中,picklecPickle,参见http://docs.pythonsprints.com/python3_porting/py-porting.html)

票数 8
EN

Stack Overflow用户

发布于 2015-05-21 23:52:27

您讨论了保存对齐器模型,但您的问题似乎更多地是关于保存您已对齐的比特表达式:“如果有一天批量进行对齐,并在以后使用这些对齐,那就太好了。”我将回答这个问题。

在nltk环境中,使用类似语料库的资源的最佳方式是使用语料库阅读器访问它。NLTK没有提供语料库编写器,但是NLTK的AlignedCorpusReader支持的格式非常容易生成:(NLTK3版本)

代码语言:javascript
复制
model = ibm(biverses, 20)  # As in your question

out = open("folder/newalignedtext.txt", "w")
for pair in biverses:
    asent = model.align(pair)
    out.write(" ".join(asent.words)+"\n")
    out.write(" ".join(asent.mots)+"\n")
    out.write(str(asent.alignment)+"\n")

out.close()

就这样。您可以稍后重新加载并使用与comtrans语料库完全相同的对齐句子:

代码语言:javascript
复制
from nltk.corpus.reader import AlignedCorpusReader

mycorpus = AlignedCorpusReader(r"folder", r".*\.txt")
biverses_reloaded = mycorpus.aligned_sents()

正如您所看到的,您不需要对齐器对象本身。对齐的句子可以用语料库阅读器加载,除非你想研究嵌入的概率,否则对齐器本身是非常无用的。

评论:我不确定我是否会把对齐器对象称为“模型”。在NLTK2中,对齐器没有设置为对齐新文本--它甚至没有align()方法。在NLTK3中,函数align()可以对齐新文本,但只能在Python2中使用;在Python3中,它被破坏了,显然是因为比较不同类型的对象的规则收紧了。但是,如果您希望能够处理和重新加载校正器,我很乐意将其添加到我的答案中;根据我所看到的,可以使用普通的cPickle来完成这项工作。

票数 3
EN

Stack Overflow用户

发布于 2015-06-02 09:45:08

如果您愿意,您可以将其存储为AlignedSent列表:

代码语言:javascript
复制
from nltk.align import IBMModel1 as IBM
from nltk.align import AlignedSent
import dill as pickle

biverses = [list of AlignedSent objects]
model = ibm(biverses, 20)

for sent in range(len(biverses)):
     biverses[sent].alignment = model.align(biverses[sent]).alignment

在此之后,您可以使用dill将其保存为泡菜:

代码语言:javascript
复制
with open('alignedtext.pk', 'wb') as arquive:
     pickle.dump(biverses, arquive)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30195287

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档