Расчет точечной взаимной информации (PMI) для n-грамм в Python

У меня есть большой корпус n-грамм и несколько внешних n-грамм. Я хочу рассчитать оценку PMI каждой внешней n-граммы на основе этого корпуса (подсчеты).

Существуют ли какие-либо инструменты для этого или кто-нибудь может предоставить мне фрагмент кода на Python, который может это сделать?

Проблема в том, что мои n-граммы 2-граммовые, 3-граммовые, 4-граммовые и 5-граммовые. Таким образом, вычисление вероятностей для 3 граммов и более требует много времени.


person Hossein    schedule 08.03.2011    source источник


Ответы (1)


Если я правильно понимаю вашу проблему, вы хотите вычислить такие вещи, как log { P("x1 x2 x3 x4 x5") / P("x1") P("x2") ... P("x5") } где P измеряет вероятность того, что любые заданные 5 грамм или 1 грамм являются данной вещью (и, по сути, представляет собой отношение количества, возможно, со смещением в стиле Лапласа). Итак, сделайте один проход через свой корпус и сохраните подсчеты (1) каждого 1-грамма, (2) каждого n-грамма (используйте диктовку для последнего), а затем для каждой внешней n-граммы вы делаете несколько диктовок Поиски, немного арифметики, и все готово. Один проход по корпусу на старте, затем фиксированный объем работы на внешний n-грамм.

(Примечание: на самом деле я не уверен, как определить PMI для более чем двух случайных величин; возможно, это что-то вроде журнала P (a) P (b) P (c) P (abc) / P (ab) P (bc) P (a_c). Но если это вообще что-то в этом роде, вы можете сделать это таким же образом: перебрать свой корпус, подсчитывая множество вещей, и тогда все вероятности, которые вам нужны, будут просто отношениями количества, возможно, с Лапласом- да поправки.)

Если ваш корпус настолько велик, что вы не можете уместить n-граммовый словарь в памяти, то разделите его на куски размером примерно с память, вычислите n-граммные словари для каждого куска и сохраните их на диске в форме, позволяющей вам достаточно эффективно получить любую запись n-граммы; затем для каждой внешней n-граммы пройдитесь по частям и подсчитайте количество.

Какая форма? Вам решать. Один простой вариант: в лексикографическом порядке n-граммы (примечание: если вы работаете со словами, а не с буквами, вы можете начать с преобразования слов в числа; вам понадобится один предварительный проход по вашему корпусу, чтобы сделать это); затем поиск нужной n-граммы представляет собой бинарный поиск или что-то в этом роде, что с кусками размером 1 ГБ будет означать где-то порядка 15-20 поисков на кусок; вы можете добавить дополнительную индексацию, чтобы уменьшить это. Или: используйте хэш-таблицу на диске, с Berkeley DB или что-то в этом роде; в этом случае вы можете отказаться от фрагментации. Или, если алфавит небольшой (например, это n-граммы букв, а не n-граммы слов, и вы обрабатываете обычный текст на английском языке), просто сохраните их в большом массиве с прямым поиском, но в этом случае вы, вероятно, все равно сможете уместить все это в памяти.

person Gareth McCaughan    schedule 08.03.2011