Перейти к содержанию

Ключевые слова

keyness(target, reference, measure='log_likelihood', min_freq=1, positive=True, top_n=None, n=1, lemmatize=True)

Поиск ключевых слов (keyness) целевого корпуса относительно эталонного: слова, которые в целевом корпусе встречаются значимо чаще, чем в эталонном.

Для каждого слова считаются две величины, которые Gabrielatos и Marchi и Hardie рекомендуют смотреть вместе: логарифм правдоподобия \(G^2\) с p-значением (есть ли различие) и Log Ratio (насколько оно велико), а также выбранная мера score, по которой список сортируется. Меры значимости (\(G^2\), хи-квадрат, BIC) и ELL, размер эффекта \(G^2\), отрицательны, если слово чаще в эталоне; %DIFF, Log Ratio и отношение шансов направленные по построению.

Эталоном может быть список слов, справочник частот (его объем - сумма частот) или FrequencyReference. Слова сравниваются как есть: регистр, лемматизация и стоп-слова - на стороне экстрактора слов, и оба корпуса должны быть извлечены одинаково. Корпус из нескольких текстов передается списком их списков слов. При n больше 1 ключевыми становятся N-граммы слов каждого текста, соединенные подчеркиванием, как N-граммы WordsExtractor (черный_кот), так что N-грамма никогда не переходит через границу текстов; частоты и объемы - это частоты и объемы N-грамм, а частоты на миллион - на миллион N-грамм. Частоты N-грамм - сумма Counter N-грамм каждого текста или частотный словарь N-грамм - передаются с n=1: справочник частот и FrequencyReference при n больше 1 не принимаются.

Функция оборачивает keyness ядра anyTS и принимает эталоном также частотный словарь Ляшевской и Шарова FreqDict; FrequencyReference лежит рядом с ней в ruts.corpus. Слова извлекает WordsExtractor.

from ruts import WordsExtractor
from ruts.corpus import keyness

we = WordsExtractor(use_lexemes=True, lowercase=True)
target = we.extract(
    "Кот сидел на окне и смотрел на птиц. Птицы улетели, и кот уснул на окне. "
    "Завтра кот снова будет сидеть на окне и смотреть на птиц."
)
reference = we.extract(
    "Собака лежала на полу и дремала. Потом собака ела и снова дремала. Завтра собака будет гулять."
)

keyness(target, reference, top_n=1)
[(k.word, round(k.g2, 2)) for k in keyness(target, reference, positive=False, top_n=2)]
[Keyword(word='кот', freq_target=3, freq_reference=0.0, ipm_target=115384.61538461539, ipm_reference=0.0, g2=2.8774384815713177, p_value=0.08982881315854577, log_ratio=1.8845227825800641, score=2.8774384815713177)]
[('собака', -5.79), ('дремать', -3.86)]

Параметры

Параметр Тип По умолчанию Описание
target list[str] / list[list[str]] / dict[str, int] - Слова целевого корпуса - одного текста или списка текстов - или их частоты
reference list[str] / list[list[str]] / dict[str, float] / FrequencyReference - Слова эталонного корпуса - одного текста или списка текстов, - их частоты или эталон по частотам
measure str 'log_likelihood' Мера из anyts.constants.KEYNESS_MEASURES для score и сортировки
min_freq int 1 Минимальная частота ключевого слова в своем корпусе
positive bool True Положительные ключевые слова (чаще в целевом корпусе) или отрицательные (чаще в эталонном)
top_n int None Количество ключевых слов; None - все
n int 1 Длина N-грамм слов каждого текста; 1 - слова

Параметры и целевой корпус проверяет check_keyness_params; n больше 1 при частотах или FrequencyReference дает ParameterError. Эталон, который не список строк, не список таких списков, не справочник частот и не FrequencyReference, дает SourceTypeError, а отрицательная, nan или бесконечная частота справочника и корпус без слов или короче n слов - SourceError.

reference может быть и FreqDict, и еще один параметр говорит, из чего при нем целевой корпус:

Параметр Тип По умолчанию Описание
lemmatize bool True Целевой корпус из словоформ, False - из лемм (только с FreqDict)

Незагруженный частотный словарь дает DatasetNotFoundError, а n больше 1 при нем - ParameterError: словарь хранит слова.

check_keyness_params(measure='log_likelihood', min_freq=1, top_n=None, target=None, n=1, positive=True)

Проверяет параметры keyness до чтения частотного словаря: дает ParameterError, если мера не из KEYNESS_MEASURES, минимальная частота не целое число, количество ключевых слов не None и не целое число не меньше единицы, длина N-грамм n не целое число не меньше единицы или positive не bool. С target дает также SourceTypeError, если целевой корпус не список строк, не список таких списков и не справочник строк с целыми частотами, и SourceError для отрицательной, nan или бесконечной частоты.

Эталон по частотам

FrequencyReference(counts, size, missing=0.0, key=None, keep=None)

Эталонный корпус, описанный одними частотами, - например, частотный словарь, построенный по корпусу, слишком большому, чтобы передать его словами:

Поле Тип По умолчанию Описание
counts dict[str, float] - Частоты ключей в эталонном корпусе
size float - Объем эталонного корпуса в словах
missing float 0.0 Частота ключа, которого нет в counts
key Callable None Ключ слова целевого корпуса в counts, например его лемма; None - само слово
keep Callable None Учитывается ли слово целевого корпуса; None - каждое слово

Учитываются только слова целевого корпуса, которые пропускает keep, - под своим key, и в частотах, и в объеме. Частота ключа, которого нет в counts, - missing, например наименьшая частота словаря: это верхняя граница, поэтому такое слово может быть положительным ключевым словом, но никогда - отрицательным. Отрицательные ключевые слова берутся только из ключей counts, которые пропускает keep. Частота проверяется при чтении, так что большой словарь не перебирается ради положительных ключевых слов: частота, которая не число, дает SourceTypeError, а отрицательная, nan или бесконечная - SourceError. size или missing, который не конечное число или отрицателен, дает ParameterError, а key или keep, который нельзя вызвать, - SourceTypeError.

Частотный словарь FreqDict, переданный как reference, превращается в такой эталон:

Поле FreqDict
counts частоты FreqDict.word_ipm, переведенные в число употреблений в корпусе словаря
size CORPUS_SIZE из ruts.datasets.freq2011, 92 млн словоупотреблений современного подкорпуса Национального корпуса русского языка
missing наименьшая частота словаря FreqDict.min_ipm, 0.4 ipm (около 37 употреблений)
key лемма словаря: словоформа лемматизируется ruMorph (с lemmatize=False берется как лемма) и приводится к соглашениям словаря функцией ruts.lexical_stats.dictionary_lemma, как в LexicalStats
keep слова из кириллических букв ruts.lexical_stats.DICTIONARY_WORD; числа и слова с латиницей отбрасываются

Статья словаря, которой нет в тексте, бывает отрицательным ключевым словом, только если к ней приводится хотя бы одна форма слова: статьи «во», «со» словарь ведет отдельно, а ruMorph приводит эти словоформы к «в», «с», и без этого правила они выходили бы отрицательными ключевыми словами у любого текста. Такие статьи - около 1 150 для словоформ и 1 450 для лемм - перечислены в ресурсах пакета; у слов вне словаря ruMorph («Михайлыч») формы угаданы.

С lemmatize=False соглашения словаря по лемме не восстановить: краткая форма, множественное число и вариант написания теряются («должный» вместо «должен», «деньга» вместо «деньги», «счастие» вместо «счастье»), и такие статьи выходят ложными ключевыми словами. Для сравнения со словарем передавайте словоформы.

from ruts import WordsExtractor
from ruts.corpus import keyness
from ruts.datasets import FreqDict

# Словарь загружается один раз: FreqDict().download()
words = WordsExtractor().extract(
    "Кот сидел на окне и смотрел на птиц. Птицы улетели, и кот уснул на окне. "
    "Завтра кот снова будет сидеть на окне и смотреть на птиц."
)
[(k.word, round(k.log_ratio, 1)) for k in keyness(words, FreqDict(), min_freq=3, top_n=2)]
[('кот', 11.5), ('птица', 10.3)]

Результат

Keyword(word, freq_target, freq_reference, ipm_target, ipm_reference, g2, p_value, log_ratio, score)

Список именованных кортежей Keyword по убыванию ключевости (при равенстве - по убыванию частоты и по алфавиту, слова с неопределенной мерой в конце); pd.DataFrame(keywords) дает таблицу.

Поле Тип Описание
word str Слово
freq_target int Частота в целевом корпусе
freq_reference float Частота в эталонном корпусе
ipm_target float Частота в целевом корпусе на миллион слов или N-грамм
ipm_reference float Частота в эталонном корпусе на миллион слов или N-грамм
g2 float \(G^2\) со знаком направления
p_value float p-значение \(G^2\)
log_ratio float Log Ratio
score float Значение выбранной меры

Меры

Меры measure по ключам, с названиями и описаниями в anyts.constants.KEYNESS_MEASURES:

Ключ Что измеряет Диапазон Чем больше, тем
log_likelihood Значимость различия частот любое число значимее превышение в целевом корпусе
chi2 Значимость различия с поправкой Йейтса любое число значимее превышение в целевом корпусе
diff Разность частот на миллион в процентах от эталона больше −100 больше превышение в целевом корпусе
log_ratio Двоичный логарифм отношения частот на миллион любое число больше превышение в целевом корпусе
bic Свидетельство различия: \(G^2\) со штрафом за объем корпусов любое число сильнее свидетельство превышения в целевом корпусе для слова, которое там чаще
ell Размер эффекта \(G^2\) как правило, от −1 до 1, nan при малых ожидаемых частотах больше превышение в целевом корпусе
odds_ratio Отношение шансов слова в корпусах от 0 до inf, nan, если слово занимает оба корпуса выше шансы в целевом корпусе

Каждая мера - функция модуля anyts.corpus.keyness от частот слова и объемов корпусов, \(N = c + d\):

Параметр Тип По умолчанию Описание
a float - Частота слова в целевом корпусе
b float - Частота слова в эталонном корпусе
c float - Объем целевого корпуса
d float - Объем эталонного корпуса

Нулевая частота в одном из корпусов для %DIFF, Log Ratio и отношения шансов заменяется на 0.5 (Hardie 2014).

Модуль ruts.corpus.keyness реэкспортирует функции мер (from ruts.corpus.keyness import calc_log_likelihood).

Логарифм правдоподобия

log_likelihood · g2 · p_value · Rayson и Garside (2000)

calc_log_likelihood(a, b, c, d)

Логарифм правдоподобия частот слова относительно ожидаемых \(E_1\) и \(E_2\); слагаемое с нулевой частотой равно нулю. Критические значения - anyts.constants.G2_CRITICAL_VALUES: 3.84 для p < 0.05, 6.63 для p < 0.01, 10.83 для p < 0.001, 15.13 для p < 0.0001. Знак отрицательный, если слово чаще в эталоне.

\[ G^2 = 2 \left(a \ln \frac{a}{E_1} + b \ln \frac{b}{E_2}\right), \quad E_1 = \frac{c\,(a+b)}{N}, \quad E_2 = \frac{d\,(a+b)}{N} \]
calc_p_value(g2)

p-значение \(G^2\) или хи-квадрат при любом знаке по распределению хи-квадрат с одной степенью свободы; массив значений дает массив.

Хи-квадрат

chi2

calc_chi2(a, b, c, d)

Хи-квадрат с поправкой Йейтса по таблице сопряженности 2×2 слова и остальных слов каждого корпуса. Если поправка больше разности, статистика равна нулю. Знак отрицательный, если слово чаще в эталоне.

\[ \chi^2 = \frac{N\,\max(\lvert a(d-b) - b(c-a) \rvert - N/2,\ 0)^2}{(a+b)(N-a-b)\,c\,d} \]

%DIFF

diff · Gabrielatos и Marchi (2011)

calc_diff(a, b, c, d)

Разность частот \(NF\) на миллион слов в процентах от частоты в эталоне.

\[ \frac{NF_a - NF_b}{NF_b} \cdot 100 \]

Log Ratio

log_ratio · Hardie (2014)

calc_log_ratio(a, b, c, d)

Двоичный логарифм отношения частот \(NF\) на миллион слов: единица - слово вдвое чаще в целевом корпусе.

\[ \log_2 \frac{NF_a}{NF_b} \]

BIC

bic · Wilson (2013)

calc_bic(a, b, c, d)

Байесовский информационный критерий \(G^2\). По модулю выше 2 - положительное свидетельство различия, выше 6 - сильное, выше 10 - очень сильное; значение со знаком, противоположным \(G^2\), при \(\lvert G^2 \rvert < \ln N\) означает отсутствие свидетельства, а не обратное направление.

\[ \operatorname{sign}(G^2) \cdot (\lvert G^2 \rvert - \ln N) \]

ELL

ell · Johnston, Berry и Mielke (2006)

calc_ell(a, b, c, d)

Размер эффекта \(G^2\): доля наибольшего возможного отклонения от ожидаемых частот \(E_1\) и \(E_2\). Мера неограниченно растет, когда наименьшая ожидаемая частота приближается к единице, и равна nan, когда эта частота не больше единицы (логарифм нулевой или отрицательный). Знак отрицательный, если слово чаще в эталоне.

\[ \frac{G^2}{N \ln \min(E_1, E_2)} \]

Отношение шансов

odds_ratio

calc_odds_ratio(a, b, c, d)

Отношение шансов слова в двух корпусах: единица - шансы равны. Слово, которое занимает весь целевой корпус, дает inf, весь эталон - 0, оба - nan.

\[ \frac{a / (c - a)}{b / (d - b)} \]