2013-09-28 3 views
6

Итак, я беру класс обработки естественного языка, и мне нужно создать модель языка триграмм для генерации случайного текста, который в определенной степени выглядит «реалистичным» на основе некоторой выборки данные.Как создать словарь словарей словарей в Python

Нужно создать «триграмму» для хранения различных комбинаций слов трех грамматической грамматики. Мой профессор намекает, что это может быть сделано при наличии словаря словарей словарей, которые я пытался создать с помощью:

trigram = defaultdict(defaultdict(defaultdict(int))) 

Однако я получаю ошибку, которая говорит:

trigram = defaultdict(dict(dict(int))) 
TypeError: 'type' object is not iterable 

Как бы я делать создал 3-слойный вложенный словарь или словарь словарей словарей значений int?

Я думаю, люди голосуют за вопрос о переполнении стека, если они не знают, как ответить на него. Я добавлю несколько примеров, чтобы лучше объяснить вопрос тем, кто хочет помочь.

Эта триграмма используется для отслеживания тройных шаблонов слов. Они используются в программном обеспечении для обработки текстового языка и почти повсюду в процессе обработки естественного языка «думаю, сири или google сейчас».

Если обозначить 3 уровня словарей как dict1 dict2 и dict3 затем разбор текстового файла и чтение о «Мальчик бежит» бы следующее:

dict1, который имеет ключ из". Доступ к этому ключу будет возвращать dict2, который содержит ключ «мальчик». Доступ к этому ключу будет возвращать окончательный dict3, который будет содержать ключевые «прогоны», которые теперь будут обращаться к этому ключу, вернет значение 1.

Это символизирует, что в этом тексте «мальчик бежит» появился 1 раз. Если мы снова столкнемся с этим, мы будем следовать одному и тому же процессу и с шагом 1 на два. Если мы столкнемся с «прогулкой девушки», тогда dict2 «словарь ключей» теперь будет содержать еще один ключ для «девушки», который будет иметь dict3, который имеет ключ «прогулки» и значение 1 и так далее. В конце концов после разбора тонны текста (и отслеживания количества слов) у вас будет триграмма, которая может определить вероятность определенного стартового слова, ведущего к комбинации из трех слов, основанной на частоте появления в предыдущем анализируемом тексте .

Это может помочь вам создать правила грамматики для идентификации языков или в моем случае созданный случайно сгенерированный текст, который очень похож на грамматический английский. Мне нужен трехслойный словарь, потому что в любой позиции 3-х словной комбинации может быть другой слово, которое может создать целый набор комбинаций. Я хотел бы лучше всего объяснить триграммы и цель, стоящую за ними, насколько это возможно ... предоставил я только что сказал класс пару недель назад.

Теперь .. со всем этим . Как мне приступить к созданию словаря словарей словарей, базовый словарь которых содержит значения типа int в python?

триграмма = defaultdict (defaultdict (defaultdict (целое)))

бросает ошибка для меня

+4

Вы действительно сумасшедший кодер. –

+0

@AlexA. Как я уже сказал, это классный профессор, который рекомендовал нам это сделать. Я думаю, это потому, что мы используем его для создания языковой модели, и у нас есть неизвестное количество ключей для каждого уровня словаря. – crazyCoder

+0

Хе-хе, да, меня просто развлекал словарь словарей словарей. Насколько я знаю, для вашего случая использования это похоже на довольно разумный подход в мире Python. Не будьте слишком обескураженными вниз, так как ваш вопрос кажется справедливым, если вы спросите меня. –

ответ

11

Я пытался вложенными defaultdict «s до и решение представляется lambda вызов:

trigram = defaultdict(lambda: defaultdict(lambda: defaultdict(int))) 

trigram['a']['b']['c'] += 1 

Это некрасиво, но я подозреваю, что предложение вложенного словаря предназначено для эффективного поиска.

4

Как правило, для создания вложенного словаря триграмм уже опубликованные решения могут работать. Если вы хотите расширить идею более обобщенного решения, вы можете сделать одно из следующего: один из них принимается из Perl's AutoVivification, а другой - collection.defaultdict.

Раствор 1:

class ngram(dict): 
    """Based on perl's autovivification feature.""" 
    def __getitem__(self, item): 
     try: 
      return super(ngram, self).__getitem__(item) 
     except KeyError: 
      value = self[item] = type(self)() 
      return value 

Раствор 2:

from collections import defaultdict 
class ngram(defaultdict): 
    def __init__(self): 
     super(ngram, self).__init__(ngram) 

Демонстрация с использованием раствора 1

>>> trigram = ngram() 
>>> trigram['two']['three']['four'] = 4 
>>> trigram 
{'two': {'three': {'four': 4}}} 
>>> a['two'] 
{'three': {'four': 4}} 
>>> a['two']['three'] 
{'four': 4} 
>>> a['two']['three']['four'] 
4 

Демонстрация с использованием раствора 2

>>> a = ngram() 
>>> a['two']['three']['four'] = 4 
>>> a 
defaultdict(<class '__main__.ngram'>, {'two': defaultdict(<class '__main__.ngram'>, {'three': defaultdict(<class '__main__.ngram'>, {'four': 4})})}) 
0

Если это просто извлечения и извлечения триграмм, вы должны попробовать это с NLTK:

>>> import nltk 
>>> sent = "this is a foo bar crazycoder" 
>>> trigrams = nltk.ngrams(sent.split(), 3) 
[('this', 'is', 'a'), ('is', 'a', 'foo'), ('a', 'foo', 'bar'), ('foo', 'bar', 'crazycoder')] 
# token "a" in first element of trigram 
>>> first_a = [i for i in trigrams if i[0] == "a"] 
[('a', 'foo', 'bar')] 
# token "a" in 2nd element of trigram 
>>> second_a = [i for i in trigrams if i[1] == "a"] 
[('is', 'a', 'foo')] 
# token "a" in third element of trigram 
>>> third = [i for i in trigrams if i[2] == "a"] 
[('this', 'is', 'a')] 
# look for 2gram in trigrams 
>> two_foobar = [i for i in trigrams if "foo" in i and "bar" in i] 
[('a', 'foo', 'bar'), ('foo', 'bar', 'crazycoder')] 
# look for a perfect 3gram 
>> perfect = [i fof i in trigrams if "foo bar crazycoder".split() == i] 
[('foo', 'bar', 'crazycoder')] 
+1

в этом смысле решение более масштабируемо до> 3 грамм, но для больших данных вам могут понадобиться умные способы поиска, кроме понимания списка. – alvas

1

Метод defaultdict __init__ принимает аргумент, который требуется, чтобы быть отозваны. Вызываемый, передаваемый в defaultdict, должен быть вызван без аргументов и должен возвращать экземпляр значения по умолчанию.

Проблема с гнездом defaultdict как вы сделали то, что defaultdict10's __init__ принимает аргумент. Предоставляя defaultdict, этот аргумент означает, что вместо обертывания defaultdict, имеющего вызываемый как его аргумент __init__, он имеет экземпляр defaultdict, который не может быть вызван.

lambda решения по @pcoving будет работать, потому что это создает анонимную функцию, которая возвращает defaultdict инициализирован с функцией, которая возвращает правильный тип defaultdict для каждого слоя в словаре вложенности.

Смежные вопросы