Ключевые слова¶
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).
Логарифм правдоподобия¶
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. Знак отрицательный, если слово чаще в эталоне.
calc_p_value(g2)
p-значение \(G^2\) или хи-квадрат при любом знаке по распределению хи-квадрат с одной степенью свободы; массив значений дает массив.
Хи-квадрат¶
calc_chi2(a, b, c, d)
Хи-квадрат с поправкой Йейтса по таблице сопряженности 2×2 слова и остальных слов каждого корпуса. Если поправка больше разности, статистика равна нулю. Знак отрицательный, если слово чаще в эталоне.
%DIFF¶
calc_diff(a, b, c, d)
Разность частот \(NF\) на миллион слов в процентах от частоты в эталоне.
Log Ratio¶
calc_log_ratio(a, b, c, d)
Двоичный логарифм отношения частот \(NF\) на миллион слов: единица - слово вдвое чаще в целевом корпусе.
BIC¶
calc_bic(a, b, c, d)
Байесовский информационный критерий \(G^2\). По модулю выше 2 - положительное свидетельство различия, выше 6 - сильное, выше 10 - очень сильное; значение со знаком, противоположным \(G^2\), при \(\lvert G^2 \rvert < \ln N\) означает отсутствие свидетельства, а не обратное направление.
ELL¶
calc_ell(a, b, c, d)
Размер эффекта \(G^2\): доля наибольшего возможного отклонения от ожидаемых частот \(E_1\) и \(E_2\). Мера неограниченно растет, когда наименьшая ожидаемая частота приближается к единице, и равна nan, когда эта частота не больше единицы (логарифм нулевой или отрицательный). Знак отрицательный, если слово чаще в эталоне.
Отношение шансов¶
calc_odds_ratio(a, b, c, d)
Отношение шансов слова в двух корпусах: единица - шансы равны. Слово, которое занимает весь целевой корпус, дает inf, весь эталон - 0, оба - nan.