Дальнейшее редактирование - код включен Если вы в состоянии удерживать arrayOfTrigrams
в памяти, см. Исходное решение внизу. Но, если вы не смогли создать arrayOfTrigrams
(и я несколько скептически отношусь к тому, что вы получили такой далекий размер данных), вы все равно можете стрелять для создания словаря повторяющихся триграмм. Повторные биграммы всегда содержат повторяющиеся слова, а повторяющиеся триграммы содержат повторяющиеся биграммы. Обрабатывайте 500 МБ данных поэтапно. Сначала создайте набор повторяющихся слов. Используя это, создайте словарь повторных биграмм. Сначала сделайте необработанное частотное число биграмм, содержащих одно из повторяющихся слов, а затем отбросьте все, чей счет равен 1. Затем обработайте данные в третий раз, создав словарь повторяющихся триграмм. Опять же, сделайте необработанную частоту подсчета триграмм, которые содержат повторяющийся bigram (который должен быть небольшим подмножеством всех возможных триграмм), а затем отбросить те из словаря, окончательный счет которого равен 1. Таким образом, вы можете создать словарь без когда-либо, чтобы сохранить все триграммы в памяти сразу.
Доказательство концепции:
from collections import defaultdict
chars = set('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
def cleanWord(s):
return ''.join(c for c in s if c in chars)
f = open('moby dick.txt') #downloaded from Project Gutenberg: http://www.gutenberg.org/ebooks/2701 -- Thanks!
words = f.read().split()
f.close()
words = [cleanWord(w.upper()) for w in words]
words = [w for w in words if len(w) > 1 and not(w in set('AIOY'))]
repeatedWords = defaultdict(int)
for w in words:
repeatedWords[w] += 1
repeatedWords = set(w for w in repeatedWords if repeatedWords[w] > 1)
repeatedBigrams = defaultdict(int)
for i in range(len(words) - 1):
x,y = words[i:i+2]
if x in repeatedWords or y in repeatedWords:
repeatedBigrams[x + ' ' + y] +=1
repeatedBigrams = set(b for b in repeatedBigrams if repeatedBigrams[b] > 1)
repeatedTrigrams = defaultdict(int)
for i in range(len(words) - 2):
x,y,z = words[i:i+3]
if x + ' ' + y in repeatedBigrams and y + ' ' + z in repeatedBigrams:
repeatedTrigrams[x + ' ' + y + ' ' + z] +=1
repeatedTrigrams = {t:c for t,c in repeatedTrigrams.items() if c > 1}
Этот код поворачивает вверх 10016 триграмм, которые появляются более одного раза. В отличии от этого, когда я оцениваю
len(set(' '.join(words[i:i+3]) for i in range(len(words)-2)))
Я получаю 188285, так что в этом несколько значительных естественном языке, например, только 10016/188285 = 5,3% от возможных триграмм повторяются триграммами. Предполагая, что для ваших данных справедливо соотношение, я считаю, что размер частотного словаря для повторяющихся триграмм будет составлять около 100 МБ.
оригинальное решение:
Ваш код и Ваш вопрос предполагает, что вы в состоянии держать arrayOfTrigrams
в памяти, но не может создать словарь. Одним из возможных способов заключается в первый сортировать этот массив и создать счетчик частоты повторил триграмм:
arrayOfTrigrams.sort()
repeatedTrigrams = {}
for i,t in enumerate(arrayOfTrigrams):
if i > 0 and arrayOfTrigrams[i-1] == t:
if t in repeatedTrigrams:
repeatedTrigrams[t] += 1
else:
repeatedTrigrams[t] = 2
После построения repeatedTrigrams
вы могли бы использовать набор понимание:
uniques = {t for t in arrayOfTrigrams if not t in repeatedTrigrams}
Затем t in uniques
бы передать информацию что число t
равно 1, что я бы заподозрил в истинности для подавляющего большинства триграмм. На этом этапе у вас есть все соответствующей информации частоты и может отбросить список триграмм, чтобы освободить часть памяти, что вы потребленный:
arrayOfTrigrams = None
Возможный дубликат [Python memoryerror create large dictionary] (http://stackoverflow.com/questions/36464704/python-memoryerror-creating-large-dictionary) – redoc
Вы пытались посмотреть http://stackoverflow.com/ Вопросы/36464704/python-memoryerror-create-large-dictionary? – redoc
Так что 'arrayOfTrigrams' не слишком большой, но словарь вызывает проблемы? –