Статистики лексической сложности¶
LexicalStats(source, words_extractor=None, freq_dict=None)
Лексическая сложность (lexical sophistication) по образцу TAALES (Kyle, Crossley и Berger, 2018) - насколько редки слова текста: статистики по частотному словарю и его униграммной модели, доли частотных полос списка самых частых лемм и лексическая плотность. Статистики по словарю вычисляются при первом обращении, поэтому полосам и лексической плотности данные словаря не нужны.
Исключения:
SourceTypeError- словарь другого класса, чем у библиотеки, или, безfreq_dict_class, словарь безlookupиipmили его отсутствие;analyze, который дает не объектыLexicalWord;SourceError- источник без слов.
В ruTS SourceTypeError дают также источник, который не строка и не Doc, и экстрактор другого типа, а метрики по словарю без загруженного словаря - DatasetNotFoundError.
В отличие от метрик лексического разнообразия, которые сравнивают слова текста между собой, здесь слова сравниваются с частотами языка (TAALES). Источник данных - текст или объект Doc библиотеки spaCy.
Класс расширяет LexicalStats ядра anyTS русским слоем: словарь - FreqDict Ляшевской и Шарова (freq_dict_class), ранги лемм и размер списка (rank, top_size) - из вшитого списка лемм Шарова (get_rank). Слова строки извлекает русский WordsExtractor или заданный экстрактор, который для Doc применяется к его тексту; без экстрактора слова Doc берутся из его токенов, а части дефисного слова, разрезанного spaCy, склеиваются. Числа (2020, 5.5, 3-й) словами не считаются. Леммы дает ruMorph: для Doc с разметкой частей речи - по части речи токена (ruts.utils.lemmatize), для строки - в контексте предложения, для Doc без разметки - так же в предложениях, слова которых совпадают со словами строки, а для остальных слов и с заданным экстрактором слов - по первому разбору. Ключи слов в словаре (keys, dictionary_keys) - леммы, приведенные к его соглашениям функцией dictionary_lemma: должна - должен, денег - деньги, ночью - ночь. Таблица print_stats и сообщения об ошибках - по-русски (LEXICAL_STATS_DESC и CORE_MESSAGES из ruts.constants).
from ruts import LexicalStats
from ruts.datasets import FreqDict
FreqDict().download()
ls = LexicalStats("Кот сидел на окне и смотрел на птиц")
ls.print_stats()
Статистика | Значение
-------------------------------------------------------------------
Доля слов, найденных в частотном словаре | 1.00
Средняя частотность (ipm) | 8645.54
Средняя частотность знаменательных слов (ipm) | 324.18
Средняя логарифмическая частотность (lg ipm) | 3.07
Средняя логарифмическая частотность знаменательных слов | 2.32
Средний диапазон (R) | 99.75
Средняя дисперсия (D) | 95.12
Средний сюрпризал (бит) | 9.74
Униграммная перплексия | 856.21
Доля слов из топ-1000 | 0.75
Доля слов из топ-2000 | 0.88
Доля слов из топ-5000 | 1.00
Доля слов из топ-10000 | 1.00
Доля слов вне топ-10000 | 0.00
Лексическая плотность | 0.62
Параметры¶
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
source |
str / Doc |
- | Источник данных |
words_extractor |
WordsExtractor |
None |
Инструмент для извлечения слов; применяется и к Doc, к его тексту |
freq_dict |
FreqDict |
None |
Частотный словарь; по умолчанию FreqDict() из директории по умолчанию |
Атрибуты¶
| Атрибут | Тип | Описание |
|---|---|---|
freq_dict |
FrequencyDictionary |
Частотный словарь |
words, lemmas |
tuple[str] |
Слова и их леммы; полосы считаются по леммам |
keys |
tuple[str] |
Ключи слов в словаре |
entries |
tuple[FrequencyEntry / None] |
Статьи словаря, None для слова вне его |
ranks |
tuple[int / None] |
Ранги лемм, None вне списка |
n_words, n_content_words, n_found |
int |
Количество слов, знаменательных слов и слов, найденных в словаре |
В ruTS словарь - FreqDict, а его статьи - именованные кортежи Entry.
Метрики¶
Каждая метрика - атрибут или свойство объекта, а get_stats дает их все. Среднее берется по словам, найденным в словаре, а без них равно nan.
| Метрика | Что измеряет | Диапазон | Чем больше, тем |
|---|---|---|---|
coverage |
Доля слов, найденных в словаре | 0-1 | больше слов знакомо словарю |
mean_ipm, mean_ipm_content |
Средняя частотность на миллион слов найденных слов, найденных знаменательных слов | больше 0 | частотнее слова |
mean_log_ipm, mean_log_ipm_content |
Средний десятичный логарифм частотности найденных слов, найденных знаменательных слов | до 6 | частотнее слова |
mean_range |
Средний диапазон найденных слов | от 0 | в большем числе частей корпуса встречаются слова |
mean_dispersion |
Средняя дисперсия найденных слов | как у словаря | по мере словаря |
surprisal |
Средний сюрпризал слов по униграммной модели словаря в битах | от 0 | реже слова |
perplexity |
2 в степени сюрпризала | от 1 | реже слова |
p_top1000, p_top2000, p_top5000, p_top10000 |
Доля слов с леммой из топ-1000, 2000, 5000 и 10000 списка | 0-1, nan для полосы больше top_size |
частотнее слова |
p_beyond_top10000 |
Доля слов с леммой вне топ-10000 | 0-1, nan для списка короче 10000 |
реже слова |
lexical_density |
Доля знаменательных слов | 0-1 | больше знаменательных слов |
Метрики считаются по двум ресурсам; рядом со средними по словарю всегда смотрите coverage.
| Ресурс | Метрики | Доступность |
|---|---|---|
FreqDict - словарь Ляшевской и Шарова, 52 138 лемм с ipm, R, D |
coverage, mean_ipm*, mean_log_ipm*, mean_range, mean_dispersion, surprisal, perplexity |
загружается один раз командой FreqDict().download() |
| Вшитый список 10 000 самых частых лемм интернет-корпуса Лидского университета (С. А. Шаров, зеркало hingston/russian, CC BY 2.5) | p_top1000, p_top2000, p_top5000, p_top10000, p_beyond_top10000, band_coverage |
всегда |
Частотность по словарю¶
Метрики считаются по статьям FreqDict для ключей слов (keys, entries): средние берутся по словам, найденным в словаре, по всем или только по знаменательным. Средняя частотность в ipm чувствительна к служебным словам (и - 35 000 ipm, в - 31 000), поэтому для сравнения текстов удобнее логарифм частотности или средняя по знаменательным словам. Средняя частотность знаменательных слов mean_ipm_content - признак FREQ2 формулы Соловьёва, Иванова, Солнышкиной 2023 года, значения которого в статье лежат в пределах 200-1000 (sis_grade_by_freq).
Редкие слова опускают покрытие и логарифм частотности и поднимают сюрпризал и долю вне топ-10000:
from ruts import LexicalStats
ls = LexicalStats("Фелинолог пребывал на подоконнике")
ls.coverage, ls.mean_log_ipm, ls.surprisal, ls.p_beyond_top10000
(0.75, 2.3063585317426494, 14.515882690436708, 0.25)
Сюрпризал и перплексия¶
calc_surprisal(lemmas, freq_dict)
Средний сюрпризал слов по униграммной модели частотного словаря в битах; слово вне словаря получает его наименьшую частоту min_ipm. Перплексия - 2 в его степени.
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
lemmas |
list[str] |
- | Ключи слов в словаре |
freq_dict |
FrequencyDictionary |
- | Частотный словарь |
Без слов результат - nan; ключи, которые не список строк, и словарь без ipm и min_ipm дают SourceTypeError, наименьшая частота не больше нуля - ParameterError.
В ruTS словарь - FreqDict с наименьшей частотой 0.4 ipm: словарь другого класса дает SourceTypeError.
from ruts.datasets import FreqDict
from ruts.lexical_stats import calc_surprisal
calc_surprisal(["кот", "сидеть", "фелинолог"], FreqDict())
15.570731790883956
Частотные полосы¶
Доля слов, лемма которых имеет ранг (rank) в пределах топ-\(N\) списка, для границ 1000, 2000, 5000 и 10000 из FREQUENCY_BANDS; доля вне топ-10000 - остаток, включая слова вне списка. Полоса больше размера списка (top_size) равна nan, как и доля вне топ-10000 для списка короче 10000.
Так строится профиль частотных полос по образцу Lexical Frequency Profile.
get_rank(lemma)
Ранг леммы по вшитому списку Шарова, None для леммы вне списка; лемма берется в любом регистре, с ё или без.
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
lemma |
str |
- | Лемма |
load_top_lemmas()
Весь список из файла ruts/resources/sharoff_top10000.txt: ранг каждой леммы в нижнем регистре без буквы ё, начиная с 1; у дублей остается меньший ранг.
from ruts.lexical_stats import get_rank, load_top_lemmas
get_rank("и"), get_rank("кот"), get_rank("фелинолог")
len(load_top_lemmas())
(1, 2009, None)
9989
Лексическая плотность¶
Доля знаменательных слов (существительные, прилагательные, глаголы, наречия без местоименных и вводных слов) среди всех слов; знаменательное слово определяет is_content_word для строки и CONTENT_UD_POS для Doc с разметкой.
Методы¶
band_coverage(bands, unique) возвращает долю слов с леммой из топ-N списка для каждой границы N из bands (по умолчанию FREQUENCY_BANDS), а с unique=True - долю различных лемм. Границы, которые не список целых чисел, и граница вне промежутка от 1 до top_size() дают ParameterError.
from ruts import LexicalStats
ls = LexicalStats("Кот сидел на окне и смотрел на птиц")
ls.band_coverage(unique=True)
ls.band_coverage(bands=(100, 500))
{1000: 0.7142857142857143, 2000: 0.8571428571428571, 5000: 1.0, 10000: 1.0}
{100: 0.375, 500: 0.75}
Остальные методы - get_stats, to_dataframe, print_stats и describe - из интерфейса статистик ядра anyTS; шкал у статистик лексической сложности нет, поэтому describe для статистик get_stats возвращает None.
ls.get_stats()
{'coverage': 1.0,
'mean_ipm': 8645.5375,
'mean_ipm_content': 324.18,
'mean_log_ipm': 3.0674194359404705,
'mean_log_ipm_content': 2.316850597556863,
'mean_range': 99.75,
'mean_dispersion': 95.125,
'surprisal': 9.74182176626998,
'perplexity': 856.2105288389297,
'p_top1000': 0.75,
'p_top2000': 0.875,
'p_top5000': 1.0,
'p_top10000': 1.0,
'p_beyond_top10000': 0.0,
'lexical_density': 0.625}