从大文本中提取n克

时间:2015-06-05 21:59:07

标签: python performance nlp bigdata text-processing

例如,我们有以下文字:

  

" Spark是一个用于编写快速分布式程序的框架。火花   解决类似Hadoop MapReduce的问题,但速度很快   内存方法和干净的功能样式API。 ..."

我分别需要本文所有可能的部分,一个字一个字,然后是两个,三个,三个到五到五个。 像这样:

  

其中:[' Spark',',' a''''' for' ,'写作,'快速',   '分发','程序',...]

     两个人:[' Spark是','是','''框架',''写作'   ......]

     三分:[' Spark是一个','是一个框架','一个框架,用于'   写作的框架','快速写作',...]

     

。 。

     

五:[' Spark是'的框架,'是写作的框架',   用于编写快速分发',...]的快速编写框架

请注意,要处理的文本是大文本(约100GB)。 我需要这个过程的最佳解决方案。可能应该并行处理多线程。

我不需要一次完整列表,它可以是流媒体。

5 个答案:

答案 0 :(得分:4)

首先,请确保您的文件中有行,然后无需担心您可以逐行阅读(discussed here):

with open('my100GBfile.txt') as corpus:
    for line in corpus:
        sequence = preprocess(line)
        extract_n_grams(sequence)

我们假设您的语料库不需要任何特殊处理。我想你可以为你的文字找到合适的治疗方法,我只想把它放到理想的标记中:

def preprocess(string):
    # do what ever preprocessing that it needs to be done
    # e.g. convert to lowercase: string = string.lower()
    # return the sequence of tokens
    return string.split()

我不知道你想用n-gram做什么。让我们假设你想把它们算作一个适合你记忆的语言模型(它通常会,但我不确定4克和5克)。简单的方法是使用现成的nltk库:

from nltk.util import ngrams

lm = {n:dict() for n in range(1,6)}
def extract_n_grams(sequence):
    for n in range(1,6):
        ngram = ngrams(sentence, n)
        # now you have an n-gram you can do what ever you want
        # yield ngram
        # you can count them for your language model?
        for item in ngram:
            lm[n][item] = lm[n].get(item, 0) + 1

答案 1 :(得分:1)

如果您不想立即使用整个列表,那么最好的选择应该是使用迭代器。 因此,我的解决方案如下所示:

import re
text = "Spark is a framework for writing fast, distributed programs. Spark solves similar problems as Hadoop MapReduce does but with a fast in-memory approach and a clean functional style API."
word_re = re.compile(r"\w+")
words = [text[word.start():word.end()] for word in word_re.finditer(text)]
ngrams = ((words[k] for k in xrange(j, j + i + 1)) for i in xrange(len(words)) for j in xrange(len(words) - i))
for ngram in ngrams:
    for word in ngram:
        print word,
    print

这将按所需顺序为您提供所需的所有ngram。 请注意,即使对于ngrams本身来说迭代器也是不可避免的,因为你的文本和500G一样大,而且你所有可能的部分都是#34;不适合你的记忆。

另请注意,在您的情况下,您需要计算文本的长度并单独从中获取单词,因为您将无法像在我的代码示例中那样将其保存在内存中。

答案 2 :(得分:1)

理想情况下应该这样做。 您可以自定义min_len和max_len参数以满足您的需求。 应用排序功能也可以让你很好地了解哪些n-gram与其他n-gram脱颖而出。

import nltk
from nltk.util import *
from nltk.collocations import *

content = "Spark is a framework for writing fast, distributed programs. Spark solves similar problems as Hadoop MapReduce does but with a fast in-memory approach and a clean functional style API. ..."
tokens = nltk.word_tokenize(content)
bgs = everygrams(tokens, min_len=users_minimium, max_len=users_maximum)
fdist_bg = nltk.FreqDist(bgs)
for k,v in fdist_bg.items():
        print k,v

既然你提到并行执行,你可以使用Spark MLib和Python

查看以下代码片段
from pyspark.ml.feature import NGram
wordDataFrame = sqlContext.createDataFrame([
(0, ["Hi", "I", "heard", "about", "Spark"]),
(1, ["I", "wish", "Java", "could", "use", "case", "classes"]),
(2, ["Logistic", "regression", "models", "are", "neat"])], ["label","words"])
ngram = NGram(inputCol="words", outputCol="ngrams")
ngramDataFrame = ngram.transform(wordDataFrame)
for ngrams_label in ngramDataFrame.select("ngrams", "label").take(3):
    print(ngrams_label)

Spark中的解决方案和其他特征提取技术的链接位于:Spark MLib Feature extraction

希望它有所帮助。干杯。 :)

答案 3 :(得分:1)

我已经编写了一个执行以下操作的C库:https://github.com/adriaan-pelzer/corpusToNgrams

本质上,我想到的最高效的方式是:

  • 逐字逐句地分析语料库。
  • 如果遇到单词结尾字符(空格,逗号,句号等),请将单词添加到1克数组中。
  • 重复n = 2到maxN:
  • 如果1-gram数组的长度大于n,则将1-gram数组中的最后n个单词连接起来,并将其添加到n-gram数组中。

以上内容可以在递归函数中实现,并且只需要解析一次主体即可。

答案 4 :(得分:0)

你写过任何代码吗?尝试谷歌搜索N-gram generation或查看此处:Computing N Grams using Python

看起来你想要生成1克(单词列表),最多5克。

我会在一次通过中完成每一次,然后转到n + 1-gram。