Перевод официальной документации — spaCy 101: Everything you need to know
Самые важные концепции, объясненные простым языком.
Если вы новичок в spaCy или просто хотите освежить в памяти некоторые основы NLP и детали реализации — эта страница должна вам помочь. В каждом разделе одна из функций spaCy объясняется простым языком с примерами или иллюстрациями. Некоторые разделы также снова появятся в руководствах по использованию в качестве краткого введения.
На официальной странице есть ссылка на интерактивный бесплатный курс.
spaCy — это бесплатная библиотека с открытым исходным кодом для расширенной обработки естественного языка (NLP — Natural Language Processing) в Python.
Если вы работаете с большим количеством текста, со временем вам захочется узнать о нем больше. Например, о чем он? Что означают эти слова в контексте? Кто что с кем делает? Какие компании и продукты упоминаются? Какие тексты похожи друг на друга?
spaCy разработан специально для производственного использования и помогает создавать приложения, обрабатывающие и «понимающие» большие объемы текста. Его можно использовать для построения систем извлечения информации или понимания естественного языка или для предварительной обработки текста для глубокого обучения.
В документации вы встретите упоминания о функциях и возможностях spaCy. Некоторые из них относятся к лингвистическим концепциям, а другие относятся к более общим функциям машинного обучения.
Название | Описание |
---|---|
Tokenization | Сегментирование текста на слова, знаки препинания и т. д. |
Part-of-speech (POS) Tagging | Определение частей речи, например глагол или существительное. |
Dependency Parsing | Назначение меток синтаксической зависимости, описывающих отношения между отдельными токенами, такими как субъект или объект. |
Lemmatization | Определение базовых форм слов. Например, лемма «was» — это «be», а лемма «rats» — «rat». |
Sentence Boundary Detection (SBD) | Поиск и сегментирование отдельных предложений. |
Named Entity Recognition (NER) | Определение именованных «реальных» объектов, таких как люди, компании или местоположения. |
Entity Linking (EL) | Устранение неоднозначности текстовых сущностей в уникальные идентификаторы в базе знаний. |
Similarity | Сравнение слов, фрагментов текста и документы и определение насколько они похожи друг на друга. |
Text Classification | Назначение категорий или меток всему документу или его частям. |
Rule-based Matching | Поиск последовательностей токенов на основе их текстов и лингвистических аннотаций, аналогичных регулярным выражениям. |
Training | Обновление и улучшение прогнозов статистической модели. |
Serialization | Сохранение объектов в файлы или байтовые строки. |
В то время как некоторые функции spaCy работают независимо, другие требуют загрузки статистических моделей, которые позволяют spaCy предсказывать лингвистические аннотации, например, является ли слово глаголом или существительным. В настоящее время spaCy предлагает статистические модели для множества языков, которые можно установить как отдельные модули Python. Модели могут различаться по размеру, скорости, использованию памяти, точности и содержащимся в них данным. Выбор модели всегда зависит от вашего варианта использования spaCy и текстов, с которыми вы работаете. Как универсальный вариант выбора по умолчанию используется небольшие модели. Модели обычно включают в себя следующие компоненты:
spaCy предоставляет множество лингвистических аннотаций, чтобы вы могли лучше понять грамматическую структуру текста. Сюда входят типы слов, такие как части речи, и то, как слова связаны друг с другом. Например, если вы анализируете текст, имеет огромное значение, является ли существительное субъектом предложения (subject ) или объектом — или используется ли «google» в качестве глагола или относится к веб-сайту или компании в конкретном контекст.
После того, как вы скачали и установили модель, вы можете загрузить ее через spacy.load (). Это команда вернет объект Language, содержащий все компоненты и данные, необходимые для обработки текста. Обычно мы называем это nlp. Вызов объекта nlp в строке текста вернет обработанный документ:
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("Apple is looking at buying U.K. startup for $1 billion") for token in doc: print(token.text, token.pos_, token.dep_)
Результат
Apple PROPN nsubj is AUX aux looking VERB ROOT at ADP prep buying VERB pcomp U.K. PROPN compound startup NOUN dobj for ADP prep $ SYM quantmod 1 NUM compound billion NUM pobj
Даже после обработки Doc
(например, разделение на отдельные слова и аннотацию) — он по-прежнему содержит всю информацию исходного текста, например, пробельные символы. Вы всегда можете получить смещение токена в исходной строке или реконструировать оригинал, соединив токены и их пробелы. Таким образом, вы никогда не потеряете информацию при обработке текста с помощью spaCy.
Во время обработки spaCy сначала токенизирует текст, т. е. сегментирует его на слова, знаки препинания и так далее. Это делается путем применения правил, специфичных для каждого языка. Например, знаки препинания в конце предложения должны быть отделены — тогда как «U.K.» должен остаться как один токен. Каждый документ состоит из отдельных токенов, и мы можем перебирать их:
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("Apple is looking at buying U.K. startup for $1 billion") for token in doc: print(token.text)
Результат
Apple is looking at buying U.K. startup for $ 1 billion
Во-первых, необработанный текст разбивается на пробельные символы, аналогично text.split (»). Затем токенизатор обрабатывает текст слева направо. Для каждой подстроки он выполняет две проверки:
Если есть совпадение, применяется правило, и токенизатор продолжает цикл, начиная с вновь разделенных подстрок. Таким образом, spaCy может разбивать сложные, вложенные токены, такие как комбинации сокращений и нескольких знаков препинания.
Хотя правила пунктуации обычно довольно общие, исключения для токенизатора сильно зависят от специфики отдельного языка. Вот почему у каждого доступного языка есть свой собственный подкласс, например English
или German, который загружается в списки жестко заданных данных и правил исключений.
После токенизации spaCy может проанализировать и пометить данный Doc. Здесь на помощь приходит статистическая модель, которая позволяет spaCy прогнозировать, какой тег или метка наиболее вероятно применима в данном контексте. Модель состоит из двоичных данных и создается путем показа системе достаточного количества примеров, позволяющих ей делать прогнозы, которые обобщаются для всего языка — например, слово, следующее за «the» в английском языке, скорее всего, является существительным.
Лингвистические аннотации доступны как Token атрибуты. Как и многие библиотеки NLP, spaCy кодирует все строки в хеш-значения, чтобы уменьшить использование памяти и повысить эффективность. Итак, чтобы получить удобочитаемое строковое представление атрибута, нам нужно добавить символ подчеркивания _ к его имени:
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("Apple is looking at buying U.K. startup for $1 billion") for token in doc: print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_, token.shape_, token.is_alpha, token.is_stop)
Apple Apple PROPN NNP nsubj Xxxxx True False is be AUX VBZ aux xx True True looking look VERB VBG ROOT xxxx True False at at ADP IN prep xx True True buying buy VERB VBG pcomp xxxx True False U.K. U.K. PROPN NNP compound X.X. False False startup startup NOUN NN dobj xxxx True False for for ADP IN prep xxx True True $ $ SYM $ quantmod $ False False 1 1 NUM CD compound d False False billion billion NUM CD pobj xxxx True False
Именованная сущность — это «реальный объект», которому присвоено имя, например человек, страна, продукт или название книги. spaCy может распознавать различные типы именованных сущностей в документе, запрашивая у модели прогноз. Поскольку модели являются статистическими и сильно зависят от примеров, на которых они были обучены, это не всегда работает идеально и может потребовать некоторой настройки позже, в зависимости от вашего варианта использования.
Именованные сущности доступны как свойство ents в Doc:
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("Apple is looking at buying U.K. startup for $1 billion") for ent in doc.ents: print(ent.text, ent.start_char, ent.end_char, ent.label_)
Результат
Apple 0 5 ORG U.K. 27 31 GPE $1 billion 44 54 MONEY
Сходство определяется путем сравнения векторов слов или «вложений слов», многомерных смысловых представлений слова. Векторы слов могут быть сгенерированы с использованием такого алгоритма, как word2vec, и обычно выглядят так:
array([2.02280000e-01, -7.66180009e-02, 3.70319992e-01, 3.28450017e-02, -4.19569999e-01, 7.20689967e-02, -3.74760002e-01, 5.74599989e-02, -1.24009997e-02, 5.29489994e-01, -5.23800015e-01, -1.97710007e-01, -3.41470003e-01, 5.33169985e-01, -2.53309999e-02, 1.73800007e-01, 1.67720005e-01, 8.39839995e-01, 5.51070012e-02, 1.05470002e-01, 3.78719985e-01, 2.42750004e-01, 1.47449998e-02, 5.59509993e-01, 1.25210002e-01, -6.75960004e-01, 3.58420014e-01, # ... and so on ... 3.66849989e-01, 2.52470002e-03, -6.40089989e-01, -2.97650009e-01, 7.89430022e-01, 3.31680000e-01, -1.19659996e+00, -4.71559986e-02, 5.31750023e-01], dtype=float32)
Примечание:
Чтобы сделать модели компактными и быстрыми, spaCy небольшие модели (это все пакеты, заканчивающиеся на sm) не поставляются с векторами слов, а включают только контекстно-зависимые тензоры. Это означает, что вы по-прежнему можете использовать методы similarity () для сравнения документов, диапазонов и токенов, но результат будет не таким хорошим, и отдельным токенам не будут назначены векторы. Чтобы использовать реальные векторы слов, вам нужно скачать модель большего размера:
- python -m spacy download en_core_web_sm + python -m spacy download en_core_web_lg
Модели, которые поставляются со встроенными векторами слов, делают их доступными как атрибут Token.vector, Doc.vector и Span.vector по умолчанию будут использовать среднее значение их векторов токенов. Вы также можете проверить, назначен ли токену вектор, и получить норму L2, которую можно использовать для нормализации векторов.
import spacy nlp = spacy.load("en_core_web_md") tokens = nlp("dog cat banana afskfsd") for token in tokens: print(token.text, token.has_vector, token.vector_norm, token.is_oov)
dog True 7.0336733 True cat True 6.6808186 True banana True 6.700014 True afskfsd False 0.0 False
Слова «dog», «cat» и «banana» довольно распространены в английском языке, поэтому они являются частью словарного запаса модели и имеют вектор. С другой стороны, слово «afskfsd» встречается гораздо реже и не входит в словарный запас, поэтому его векторное представление состоит из 300 измерений 0, что означает, что его практически не существует. Если вашему приложению будет полезен большой словарь с большим количеством векторов, вам следует рассмотреть возможность использования одной из более крупных моделей или загрузки полного векторного пакета, например en_vectors_web_lg, который включает более 1 миллиона уникальных векторов.
spaCy может сравнивать два объекта и прогнозировать, насколько они похожи. Прогнозирование сходства полезно для построения рекомендательных систем или отметки дубликатов. Например, вы можете предложить пользователю контент, похожий на то, что он сейчас просматривает, или пометить заявку в службу поддержки как дублирующую, если она очень похожа на уже существующую.
Каждый Doc, Span
и Token
поставляется с методом .similarity (), который позволяет вам сравнивать его с другим объектом и определять сходство. Конечно, сходство всегда субъективно — действительно ли «dog» и «cat» похожи, зависит от того, как вы на это смотрите. Модель подобия spaCy обычно предполагает довольно универсальное определение подобия.
import spacy nlp = spacy.load("en_core_web_md") # make sure to use larger model! tokens = nlp("dog cat banana") for token1 in tokens: for token2 in tokens: print(token1.text, token2.text, token1.similarity(token2))
Результат
dog dog 1.0 dog cat 0.80168545 dog banana 0.24327643 cat dog 0.80168545 cat cat 1.0 cat banana 0.28154364 banana dog 0.24327643 banana cat 0.28154364 banana banana 1.0
В этом случае прогнозы модели вполне соответствуют действительности. dog очень похож на cat, а banana не очень похож ни на одну из них. Идентичные токены, очевидно, на 100% похожи друг на друга (но не всегда с точностью 1.0 из-за неточностей векторной математики и с плавающей запятой).
Когда вы вызываете nlp для текста, spaCy сначала токенизирует текст для создания объекта Doc. Затем Doc обрабатывается в несколько этапов — это также называется конвейером обработки. Конвейер, используемый моделями по умолчанию, состоит из теггера, парсера и распознавателя сущностей. Каждый компонент конвейера возвращает обработанный Doc, который затем передается следующему компоненту.
Название | Компонент | Создает | Описание |
---|---|---|---|
tokenizer | Tokenizer | Doc | Сегментируйте текст на токены. |
tagger | Tagger | Doc[i].tag | Назначает теги частей речи. |
parser | DependencyParser | Doc[i].head , Doc[i].dep , Doc.sents , Doc.noun_chunks | Назначает метки зависимостей. |
ner | EntityRecognizer | Doc.ents , Doc[i].ent_iob , Doc[i].ent_type | Обнаруживает и маркирует именованные объекты. |
textcat | TextCategorizer | Doc.cats | Назначьте метки документа. |
… | custom components | Doc._.xxx , Token._.xxx , Span._.xxx | Назначьте настраиваемые атрибуты, методы или свойства. |
Конвейер обработки всегда зависит от статистической модели и ее возможностей. Например, конвейер может включать компонент распознавания сущностей, только если модель включает данные для прогнозирования меток сущностей. Вот почему каждая модель будет указывать конвейер для использования в своих метаданных в виде простого списка, содержащего имена компонентов:
"pipeline": ["tagger", "parser", "ner"]
По возможности spaCy пытается сохранить данные в словаре Vocab, который будет использоваться несколькими документами. Для экономии памяти spaCy также кодирует все строки в хеш-значения — в этом случае, например, «coffee» имеет хэш 3197928453018144401. Метки сущностей, такие как «ORG», и теги части речи, такие как «VERB», также кодируются. Внутренне spaCy «говорит» только с помощью хеш-значений.
Если вы обрабатываете множество документов, содержащих слово «coffee» в самых разных контекстах, сохранение каждый раз точной строки «coffee» будет занимать слишком много места. Поэтому вместо этого spaCy хеширует строку и сохраняет ее в StringStore. Вы можете думать о StringStore как о таблице поиска, которая работает в обоих направлениях — вы можете искать строку, чтобы получить ее хэш, или хеш, чтобы получить его строку:
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("I love coffee") print(doc.vocab.strings["coffee"]) # 3197928453018144401 print(doc.vocab.strings[3197928453018144401]) # 'coffee'
Результат
3197928453018144401 coffee
Теперь, когда все строки закодированы, словарные статьи не должны включать сам текст слова. Вместо этого они могут найти его в StringStore по его хэш-значению. Каждая запись в словаре, также называемая Lexeme
, содержит контекстно-независимую информацию о слове. Например, независимо от того, используется ли слово «love» как глагол или существительное в каком-либо контексте, его написание и то, состоит ли оно из буквенных символов, никогда не изменится. Его хеш-значение всегда будет одинаковым.
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("I love coffee") for word in doc: lexeme = doc.vocab[word.text] print(lexeme.text, lexeme.orth, lexeme.shape_, lexeme.prefix_, lexeme.suffix_, lexeme.is_alpha, lexeme.is_digit, lexeme.is_title, lexeme.lang_)
Результат
I 4690420944186131903 X I I True False True en love 3702023516439754181 xxxx l ove True False False en coffee 3197928453018144401 xxxx c fee True False False en
Отображение слов в хэши не зависит от состояния. Чтобы убедиться, что каждое значение уникально, spaCy использует хеш-функцию для вычисления хеш-функции на основе строки слов. Это также означает, что хеш для слова «coffee» всегда будет одним и тем же, независимо от того, какую модель вы используете или как вы настроили spaCy.
Однако хеши нельзя отменить, и невозможно преобразовать 3197928453018144401 обратно в «coffee». Все, что может сделать spaCy, — это найти его в словаре. Вот почему вам всегда нужно следить за тем, чтобы все создаваемые вами объекты имели доступ к одному и тому же словарю. Если вы этого не сделаете, spaCy может не найти нужные строки.
import spacy from spacy.tokens import Doc from spacy.vocab import Vocab nlp = spacy.load("en_core_web_sm") doc = nlp("I love coffee") # Original Doc print(doc.vocab.strings["coffee"]) # 3197928453018144401 print(doc.vocab.strings[3197928453018144401]) # 'coffee' 👍 empty_doc = Doc(Vocab()) # New Doc with empty Vocab # empty_doc.vocab.strings[3197928453018144401] will raise an error :( empty_doc.vocab.strings.add("coffee") # Add "coffee" and generate hash print(empty_doc.vocab.strings[3197928453018144401]) # 'coffee' 👍 new_doc = Doc(doc.vocab) # Create new doc with first doc's vocab print(new_doc.vocab.strings[3197928453018144401]) # 'coffee' 👍
Результат
3197928453018144401 coffee coffee coffee
Если словарь не содержит строки для 3197928453018144401, spaCy выдаст ошибку. Вы можете повторно добавить слово «coffee» вручную, но это сработает, только если вы действительно знаете, что документ содержит это слово. Чтобы предотвратить эту проблему, spaCy также экспортирует словарь при сохранении объекта Doc или nlp. Это дает вам объект и его закодированные аннотации, а также «ключ» для его декодирования.
Для поддержки задач связывания сущностей spaCy хранит внешние знания в базе знаний (KnowledgeBase
). База знаний (KB) использует словарь для эффективного хранения данных.
База знаний создается путем добавления в нее всех сущностей. Затем для каждого потенциального упоминания или псевдонима добавляется список соответствующих идентификаторов KB и их предшествующих вероятностей. Сумма этих априорных вероятностей никогда не должна превышать 1 для любого данного псевдонима.
import spacy from spacy.kb import KnowledgeBase # load the model and create an empty KB nlp = spacy.load('en_core_web_sm') kb = KnowledgeBase(>Результат
Number of entities in KB: 3 Number of aliases in KB: 2Candidate generation
Для текстового объекта база знаний может предоставить список вероятных кандидатов или идентификаторов объектов.
EntityLinker
принимает этот список кандидатов в качестве входных данных и устраняет неоднозначность упоминания до наиболее вероятного идентификатора с учетом контекста документа.import spacy from spacy.kb import KnowledgeBase nlp = spacy.load('en_core_web_sm') kb = KnowledgeBase(>Результат
Q1004791 0.6000000238418579 [0.0, 3.0, 5.0] Q42 0.10000000149011612 [1.0, 9.0, -3.0] Q5301561 0.20000000298023224 [-2.0, 4.0, 2.0]Сериализация
Если вы изменили конвейер, словарь, векторы и сущности или обновили модель, вы в конечном итоге захотите сохранить свой прогресс - например, все, что есть в вашем объекте nlp. Это означает, что вам придется перевести его содержимое и структуру в формат, который можно сохранить, например в файл или байтовую строку. Этот процесс называется сериализацией. spaCy имеет встроенные методы сериализации и поддерживает протокол Pickle.
Для всех контейнерных классов, например Language (nlp), Doc, Vocab и StringStore, доступны следующие методы:
Метод Что возращает Пример to_bytes
bytes data = nlp.to_bytes()
from_bytes
object nlp.from_bytes(data)
to_disk
- nlp.to_disk("/path")
from_disk
object nlp.from_disk("/path")
Обучение
Модели spaCy являются статистическими, и каждое принимаемое ими «решение» - например, какой тег части речи назначать или является ли слово именованным объектом - является предсказанием. Этот прогноз основан на примерах, которые модель видела во время обучения. Чтобы обучить модель, вам сначала понадобятся данные для обучения - примеры текста и метки, которые должна предсказывать модель. Это может быть тег части речи, именованный объект или любая другая информация.
Затем модели будет показан текст без метки, и модель сделает прогноз. Поскольку мы знаем правильный ответ, мы можем дать модели обратную связь о ее прогнозе в виде градиента ошибки функции потерь, которая вычисляет разницу между обучающим примером и ожидаемым результатом. Чем больше разница, тем значительнее градиент и обновления нашей модели.
При обучении модели мы не просто хотим, чтобы она запоминала наши примеры - мы хотим, чтобы она выдвинула теорию, которую можно было бы обобщить на других примерах. В конце концов, мы не просто хотим, чтобы модель узнала, что этот единственный экземпляр «Amazon» прямо здесь - это компания - мы хотим, чтобы она узнала, что «Amazon» в подобном контексте, скорее всего, является компанией. Вот почему данные обучения всегда должны быть репрезентативными для данных, которые мы хотим обработать. Модель, обученная в Википедии, где предложения от первого лица крайне редки, скорее всего, будет плохо работать в Твиттере. Точно так же модель, обученная романтическим романам, скорее всего, плохо справится с юридическим текстом.
Это также означает, что для того, чтобы знать, как работает модель и правильно ли она обучается, вам нужны не только данные обучения - вам также понадобятся данные оценки. Если вы протестируете модель только с данными, на которых она была обучена, вы не поймете, насколько хорошо она обобщает. Если вы хотите обучить модель с нуля, вам обычно требуется как минимум несколько сотен примеров как для обучения, так и для оценки. Чтобы обновить существующую модель, вы уже можете добиться достойных результатов с очень небольшим количеством примеров - если они репрезентативны.
Языковые данные
Каждый язык индивидуален и обычно полон исключений и особых случаев, особенно среди самых распространенных слов. Некоторые из этих исключений являются общими для разных языков, в то время как другие полностью специфичны - обычно настолько специфичны, что их нужно жестко запрограммировать. Модуль lang содержит все данные для конкретного языка, организованные в простые файлы Python. Это упрощает обновление и расширение данных.
Общие языковые данные в каталоге root включают правила, которые могут быть обобщены для разных языков - например, правила для базовой пунктуации, эмодзи, смайликов, однобуквенных сокращений и нормы для эквивалентных токенов с разными написаниями, такими как «и». Это помогает модели делают более точные прогнозы. Отдельные языковые данные в подмодуле содержат правила, относящиеся только к определенному языку. Модель также заботится о объединении всех компонентов и создании подкласса языка - например, английского или немецкого.
Стоп слова stop_words.py
Список наиболее употребительных слов в языке, которые часто бывает полезно отфильтровать, например «and» или «I». Соответствующие токены вернут True для is_stop. Исключения токенизатора tokenizer_exceptions.py
Особые правила для токенизатора, например, сокращения типа «can’t» и аббревиатуры с пунктуацией, такие как «U.K». Исключения из норм norm_exceptions.py
Особые правила нормализации токенов для улучшения предсказаний модели, например, для американского и британского правописания. Правила пунктуации punctuation.py
Регулярные выражения для разделения токенов, например о пунктуации или специальных символах, например смайликах. Включает правила для префиксов, суффиксов и инфиксов. Классы символов char_classes.py
Классы символов, используемые в регулярных выражениях, например латинские символы, кавычки, дефисы или значки. Лексические атрибуты lex_attrs.py
Custom functions for setting lexical attributes on tokens, e.g. like_num
, which includes language-specific words like “ten” or “hundred”.Итераторы синтаксиса syntax_iterators.py
Functions that compute views of a Doc
object based on its syntax. At the moment, only used for noun chunks.Карта тэгов tag_map.py
Dictionary mapping strings in your tag set to Universal Dependencies tags. Правила морфа morph_rules.py
Exception rules for morphological analysis of irregular words like personal pronouns. Лемматизатор spacy-lookups-data
Lemmatization rules or a lookup-based lemmatization table to assign base forms, for example “be” for “was”. Была ли вам полезна эта статья?[8 / 5]
Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…
Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…
Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…
Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…
Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…
Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…
View Comments
Хорошая статья для начинающих и кто не очень знает английский :)