使用 python 有效提取 1-5 克

2024-01-27

我有一个 3,000,000 行的巨大文件,每行有 20-40 个单词。我必须从语料库中提取 1 到 5 个 ngram。我的输入文件是标记化的纯文本,例如:

This is a foo bar sentence .
There is a comma , in this sentence .
Such is an example text .

目前,我正在按如下方式进行操作,但这似乎不是提取 1-5 克的有效方法:

#!/usr/bin/env python -*- coding: utf-8 -*-

import io, os
from collections import Counter
import sys; reload(sys); sys.setdefaultencoding('utf-8')

with io.open('train-1.tok.en', 'r', encoding='utf8') as srcfin, \
io.open('train-1.tok.jp', 'r', encoding='utf8') as trgfin:
    # Extract words from file. 
    src_words = ['<s>'] + srcfin.read().replace('\n', ' </s> <s> ').split()
    del src_words[-1] # Removes the final '<s>'
    trg_words = ['<s>'] + trgfin.read().replace('\n', ' </s> <s> ').split()
    del trg_words[-1] # Removes the final '<s>'

    # Unigrams count.
    src_unigrams = Counter(src_words) 
    trg_unigrams = Counter(trg_words) 
    # Sum of unigram counts.
    src_sum_unigrams = sum(src_unigrams.values())
    trg_sum_unigrams = sum(trg_unigrams.values())

    # Bigrams count.
    src_bigrams = Counter(zip(src_words,src_words[1:]))
    trg_bigrams = Counter(zip(trg_words,trg_words[1:]))
    # Sum of bigram counts.
    src_sum_bigrams = sum(src_bigrams.values())
    trg_sum_bigrams = sum(trg_bigrams.values())

    # Trigrams count.
    src_trigrams = Counter(zip(src_words,src_words[1:], src_words[2:]))
    trg_trigrams = Counter(zip(trg_words,trg_words[1:], trg_words[2:]))
    # Sum of trigram counts.
    src_sum_trigrams = sum(src_bigrams.values())
    trg_sum_trigrams = sum(trg_bigrams.values())

还有其他方法可以更有效地做到这一点吗?

如何同时最优地提取N个不同的ngram?

From 在 python 中快速/优化 N-gram 实现 https://stackoverflow.com/questions/21883108/fast-optimize-n-gram-implementations-in-python,本质上是这样的:

zip(*[words[i:] for i in range(n)])

当对二元组进行硬编码时,n=2:

zip(src_words,src_words[1:])

这是卦象吗?n=3:

zip(src_words,src_words[1:],src_words[2:])

如果您只对最常见(常见)感兴趣n-grams(我想这是你的情况),你可以重用的中心思想Apriori算法 http://en.wikipedia.org/wiki/Apriori_algorithm. Given s_min,最小支持度可以被认为是给定的行数n-gram 包含在,它有效地搜索所有此类n-grams.

想法如下:编写一个查询函数,它接受一个n-gram 并测试它在语料库中包含的次数。准备好这样的函数后(可能会像后面讨论的那样进行优化),扫描整个语料库并获取所有1-grams,即裸令牌,并选择至少包含的那些s_min次。这给了你子集F1频繁的1-克。然后测试所有可能的情况2-grams 通过组合所有1-克来自F1。再次选择那些持有s_min标准,你会得到F2。通过结合所有2-克来自F2并选择频繁出现的3-克,你会得到F3。重复只要Fn是非空的。

这里可以进行很多优化。组合时n-克来自Fn,你可以利用这样一个事实n-grams x and y只能组合形成(n+1)-gram 当且仅当x[1:] == y[:-1](可以在恒定时间内检查任何n如果使用正确的散列)。此外,如果你有足够的 RAM(对于你的语料库来说,很多 GB),你可以极大地加快查询功能。对于每个1-gram,存储包含给定行索引的哈希集1-公克。组合两个时n-克成(n+1)-gram,使用两个对应集合的交集,获得一组线,其中(n+1)可以包含-gram。

时间复杂度增长为s_min减少。美丽就是那么罕见(因此无趣)n- 语法在算法运行时被完全过滤,仅节省频繁语法的计算时间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 python 有效提取 1-5 克 的相关文章

随机推荐