首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在非常大的文本数据集上检测二元语法集合

在非常大的文本数据集上检测二元语法集合
EN

Stack Overflow用户
提问于 2019-07-01 19:39:02
回答 1查看 389关注 0票数 0

我想在文本格式的大型语料库中找到二元语法。由于语料库不能一次加载到内存中,而且它的行数非常大,所以我按块加载它,每个块1kb

代码语言:javascript
复制
def read_in_chunks(filename, chunk_size=1024):
    """Lazy function (generator) to read a file piece by piece.
    Default chunk size: 1k."""
    while True:
        data = filename.read(chunk_size)
        if not data:
            break
        yield data

然后,我想要在语料库中一段一段地查找二元语法,并使用gensim Phrases()和Phraser()函数,但在训练过程中,我的模型不断失去状态。因此,我尝试在读取每个兆字节后保存并重新加载模型,然后释放内存,但它仍然丢失状态。我的代码如下:

代码语言:javascript
复制
with open("./final/corpus.txt", "r", encoding='utf8') as r:
    max_vocab_size=20000000
    phrases = Phrases(max_vocab_size=max_vocab_size)
    i=1
    j=1024
    sentences = ""
    for piece in read_in_chunks(r):   

        if i<=j:
            sentences = sentences + piece

        else:
            phrases.add_vocab(sentences)
            phrases = Phrases(sentences)
            phrases = phrases.save('./final/phrases.txt')
            phrases = Phraser.load('./final/phrases.txt')

            sentences = ""
            j+=1024
        i+=1
print("Done")

有什么建议吗?谢谢。

EN

回答 1

Stack Overflow用户

发布于 2019-07-02 01:25:24

当你做这两行的时候...

代码语言:javascript
复制
        phrases.add_vocab(sentences)
        phrases = Phrases(sentences)

...that第二行丢弃了phrases变量中的任何现有实例,并用一个全新的实例(Phrases(sentences))替换它。没有机会对单个实例进行附加调整。

其次,连续两行.save()-then-immediate-re-.load()不可能节省净内存使用量。在最好的情况下,.load()将是不必要的,仅精确地再现刚刚是.save()d的内容,但是浪费大量时间和临时内存来加载第二个副本,然后丢弃已在phrases中的副本以将phrases分配给新的克隆。

虽然这些都是问题,但更普遍的是,问题是你需要做的事情不一定要这么复杂。

Phrases类将接受一个可迭代对象作为其sentences语料库,其中每一项都是一个字符串令牌列表。您不必担心块大小和多次调用add_vocab() -您只需提供一个对象,该对象本身依次提供每个项目,Phrases将做正确的事情。您必须担心将原始行分解为您想要考虑的特定单词(“标记化”)。

(对于大型语料库,您可能仍然会遇到与Phrases尝试统计的唯一单词的数量相关的内存问题。但是,条目的数量有多大并不重要--因为它一次只能查看一个条目。只有唯一单词的累积才会消耗运行中的内存。)

要很好地介绍可迭代对象在这种情况下是如何工作的,一个好的博客帖子是:

Data streaming in Python: generators, iterators, iterables

如果您的corpus.txt文件已经设置为每行只有一个合理大小的句子,并且所有单词都已经由简单的空格分隔,那么可迭代类可能就像这样简单:

代码语言:javascript
复制
class FileByLineIterable(object):
    def __init__(self, filename):
        self.filename = filename
    def __iter__(self):
        with open(self.filename, 'r', encoding='utf8') as src:
            for line in src.readlines():
                yield line.split()

然后,你的代码可能就像...

代码语言:javascript
复制
sentences = FileByLineIterable('./final/corpus.txt')
phrases = Phrases(sentences, max_vocab_size=max_vocab_size)

...because Phrases类得到了它想要的东西-一个通过迭代一次只提供一个单词列表项目的语料库。

注意:

  • 您可能想要启用INFO级别的日志记录,以监视进度并观察事情进展的任何线索wrong
  • there's一个稍微更高级的逐行迭代器,它还将任何一行的文本限制为不超过10,000个标记(以匹配Word2Vec的内部实现限制),并从gensim.models.word2vec.LineSentence上提供的本地文件路径以外的位置打开文件。请参阅:

https://radimrehurek.com/gensim/models/word2vec.html#gensim.models.word2vec.LineSentence

(尽管它打包在word2vec包中,但也可以在其他地方使用。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56835032

复制
相关文章

相似问题

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