从大文本中提取 n 克
extracting n grams from huge 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. ..."
我需要这篇文章的所有可能的部分,分别是一个词一个词,然后两个词两个,三个词三个,五到五个。
像这样:
ones : ['Spark', 'is', 'a', 'framework', 'for', 'writing, 'fast',
'distributed', 'programs', ...]
twos : ['Spark is', 'is a', 'a framework', 'framework for', 'for writing'
...]
threes : ['Spark is a', 'is a framework', 'a framework for',
'framework for writing', 'for writing fast', ...]
. . .
fives : ['Spark is a framework for', 'is a framework for writing',
'a framework for writing fast','framework for writing fast distributed', ...]
请注意,要处理的文本是超大文本(约100GB)。
我需要这个过程的最佳解决方案。可能应该多线程并行处理。
我不需要一次整个列表,它可以流式传输。
你写过代码吗?尝试使用谷歌搜索 N-gram generation
或查看此处:Computing N Grams using Python
您似乎想要生成 1-gram(单词列表),最多 5-gram。
我会一次做每一个,然后转到 n+1-gram。
如果您不需要一次整个列表,那么最好的选择应该是使用迭代器。
因此,我的解决方案如下所示:
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。
请注意,即使对于 ngram 本身,迭代器也是不可避免的,因为您的文本有 500G 这么大,而且您的大部分 "all possible sections" 都无法放入您的内存中。
另请注意,在您的情况下,您需要计算文本的长度并单独从中获取单词,因为您无法像我的代码示例那样将其保存在内存中。
首先,确保您的文件中有行,然后您就可以放心地逐行阅读 (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
理想情况下应该这样做。
您可以自定义参数 min_len 和 max_len 以满足您的需要。
应用排序函数也可以让您很好地了解哪些 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)
Link 解决方案和 Spark 中的其他特征提取技术在这里:Spark MLib Feature extraction
希望对您有所帮助。干杯。 :)
我已经编写了一个 C 库来执行此操作:https://github.com/adriaan-pelzer/corpusToNgrams
基本上,我能想到的最高效的方法是:
- 逐字符解析语料库。
- 如果遇到单词结束字符(space、逗号、句号等),请将单词添加到 1-gram 数组中。
- 重复 n = 2 到 maxN:
- 如果 1-gram 数组的长度大于 n,则连接 1-gram 数组中的最后 n 个单词并将其添加到 n-gram 数组中。
以上可以用递归函数实现,只需要解析一次语料
例如我们有以下文字:
"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. ..."
我需要这篇文章的所有可能的部分,分别是一个词一个词,然后两个词两个,三个词三个,五到五个。 像这样:
ones : ['Spark', 'is', 'a', 'framework', 'for', 'writing, 'fast', 'distributed', 'programs', ...]
twos : ['Spark is', 'is a', 'a framework', 'framework for', 'for writing' ...]
threes : ['Spark is a', 'is a framework', 'a framework for', 'framework for writing', 'for writing fast', ...]
. . .
fives : ['Spark is a framework for', 'is a framework for writing', 'a framework for writing fast','framework for writing fast distributed', ...]
请注意,要处理的文本是超大文本(约100GB)。 我需要这个过程的最佳解决方案。可能应该多线程并行处理。
我不需要一次整个列表,它可以流式传输。
你写过代码吗?尝试使用谷歌搜索 N-gram generation
或查看此处:Computing N Grams using Python
您似乎想要生成 1-gram(单词列表),最多 5-gram。
我会一次做每一个,然后转到 n+1-gram。
如果您不需要一次整个列表,那么最好的选择应该是使用迭代器。 因此,我的解决方案如下所示:
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。 请注意,即使对于 ngram 本身,迭代器也是不可避免的,因为您的文本有 500G 这么大,而且您的大部分 "all possible sections" 都无法放入您的内存中。
另请注意,在您的情况下,您需要计算文本的长度并单独从中获取单词,因为您无法像我的代码示例那样将其保存在内存中。
首先,确保您的文件中有行,然后您就可以放心地逐行阅读 (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
理想情况下应该这样做。 您可以自定义参数 min_len 和 max_len 以满足您的需要。 应用排序函数也可以让您很好地了解哪些 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)
Link 解决方案和 Spark 中的其他特征提取技术在这里:Spark MLib Feature extraction
希望对您有所帮助。干杯。 :)
我已经编写了一个 C 库来执行此操作:https://github.com/adriaan-pelzer/corpusToNgrams
基本上,我能想到的最高效的方法是:
- 逐字符解析语料库。
- 如果遇到单词结束字符(space、逗号、句号等),请将单词添加到 1-gram 数组中。
- 重复 n = 2 到 maxN:
- 如果 1-gram 数组的长度大于 n,则连接 1-gram 数组中的最后 n 个单词并将其添加到 n-gram 数组中。
以上可以用递归函数实现,只需要解析一次语料