例如,我们有以下文字:
" Spark是一个用于编写快速分布式程序的框架。火花 解决类似Hadoop MapReduce的问题,但速度很快 内存方法和干净的功能样式API。 ..."
我分别需要本文所有可能的部分,一个字一个字,然后是两个,三个,三个到五到五个。 像这样:
其中:[' Spark',',' a''''' for' ,'写作,'快速', '分发','程序',...]
两个人:[' Spark是','是','''框架',''写作' ......] 三分:[' Spark是一个','是一个框架','一个框架,用于' 写作的框架','快速写作',...]。 。
五:[' Spark是'的框架,'是写作的框架', 用于编写快速分发',...]的快速编写框架
请注意,要处理的文本是大文本(约100GB)。 我需要这个过程的最佳解决方案。可能应该并行处理多线程。
我不需要一次完整列表,它可以是流媒体。
答案 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
本质上,我想到的最高效的方式是:
以上内容可以在递归函数中实现,并且只需要解析一次主体即可。
答案 4 :(得分:0)
你写过任何代码吗?尝试谷歌搜索N-gram generation
或查看此处:Computing N Grams using Python
看起来你想要生成1克(单词列表),最多5克。
我会在一次通过中完成每一次,然后转到n + 1-gram。