spaCy 101: все, что вам нужно знать. Часть 2
Перевод официальной документации: spaCy 101: Everything you need to know
Обзорный тур
Следующие примеры и фрагменты кода дают вам обзор функциональности spaCy и ее использования.
Установка моделей и обработка текста
python -m spacy download en_core_web_sm python -m spacy download de_core_news_sm
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("Hello, world. Here are two sentences.") print([t.text for t in doc]) nlp_de = spacy.load("de_core_news_sm") doc_de = nlp_de("Ich bin ein Berliner.") print([t.text for t in doc_de])
['Hello', ',', 'world', '.', 'Here', 'are', 'two', 'sentences', '.'] ['Ich', 'bin', 'ein', 'Berliner', '.']
Получение токенов, фрагментов существительных и предложения
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("Peach emoji is where it has always been. Peach is the superior " "emoji. It's outranking eggplant 🍑 ") print(doc[0].text) # 'Peach' print(doc[1].text) # 'emoji' print(doc[-1].text) # '🍑' print(doc[17:19].text) # 'outranking eggplant' noun_chunks = list(doc.noun_chunks) print(noun_chunks[0].text) # 'Peach emoji' sentences = list(doc.sents) assert len(sentences) == 3 print(sentences[1].text) # 'Peach is the superior emoji.'
Peach emoji 🍑 outranking eggplant Peach Peach is the superior emoji.
Получение тегов и меток частей речи
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("Apple is looking at buying U.K. startup for $1 billion") apple = doc[0] print("Fine-grained POS tag", apple.pos_, apple.pos) print("Coarse-grained POS tag", apple.tag_, apple.tag) print("Word shape", apple.shape_, apple.shape) print("Alphabetic characters?", apple.is_alpha) print("Punctuation mark?", apple.is_punct) billion = doc[10] print("Digit?", billion.is_digit) print("Like a number?", billion.like_num) print("Like an email address?", billion.like_email)
Fine-grained POS tag PROPN 96 Coarse-grained POS tag NNP 15794550382381185553 Word shape Xxxxx 16072095006890171862 Alphabetic characters? True Punctuation mark? False Digit? False Like a number? True Like an email address? False
Использование хеш-значений для любой строки
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("I love coffee") coffee_hash = nlp.vocab.strings["coffee"] # 3197928453018144401 coffee_text = nlp.vocab.strings[coffee_hash] # 'coffee' print(coffee_hash, coffee_text) print(doc[2].orth, coffee_hash) # 3197928453018144401 print(doc[2].text, coffee_text) # 'coffee' beer_hash = doc.vocab.strings.add("beer") # 3073001599257881079 beer_text = doc.vocab.strings[beer_hash] # 'beer' print(beer_hash, beer_text) unicorn_hash = doc.vocab.strings.add("🦄") # 18234233413267120783 unicorn_text = doc.vocab.strings[unicorn_hash] # '🦄' print(unicorn_hash, unicorn_text)
3197928453018144401 coffee 3197928453018144401 3197928453018144401 coffee coffee 3073001599257881079 beer 18234233413267120783 🦄
Распознование именованных объектов
import spacy from spacy.tokens import Span nlp = spacy.load("en_core_web_sm") doc = nlp("San Francisco considers banning sidewalk delivery robots") for ent in doc.ents: print(ent.text, ent.start_char, ent.end_char, ent.label_) doc = nlp("FB is hiring a new VP of global policy") doc.ents = [Span(doc, 0, 1, label="ORG")] for ent in doc.ents: print(ent.text, ent.start_char, ent.end_char, ent.label_)
San Francisco 0 13 GPE FB 0 2 ORG
Обучение и обновление модели нейронных сетей
import spacy import random nlp = spacy.load("en_core_web_sm") train_data = [("Uber blew through $1 million", {"entities": [(0, 4, "ORG")]})] other_pipes = [pipe for pipe in nlp.pipe_names if pipe != "ner"] with nlp.disable_pipes(*other_pipes): optimizer = nlp.begin_training() for i in range(10): random.shuffle(train_data) for text, annotations in train_data: nlp.update([text], [annotations], sgd=optimizer) nlp.to_disk("/model")
Визуализирование анализа зависимостей и именованных сущностей
from spacy import displacy doc_dep = nlp("This is a sentence.") displacy.serve(doc_dep, style="dep") doc_ent = nlp("When Sebastian Thrun started working on self-driving cars at Google " "in 2007, few people outside of the company took him seriously.") displacy.serve(doc_ent, style="ent")
Получение векторов слов и сходства
import spacy nlp = spacy.load("en_core_web_md") doc = nlp("Apple and banana are similar. Pasta and hippo aren't.") apple = doc[0] banana = doc[2] pasta = doc[6] hippo = doc[8] print("apple <-> banana", apple.similarity(banana)) print("pasta <-> hippo", pasta.similarity(hippo)) print(apple.has_vector, banana.has_vector, pasta.has_vector, hippo.has_vector)
apple <-> banana 0.5831845 pasta <-> hippo 0.12069741 True True True True
Для достижения наилучших результатов вы должны запустить этот пример, используя модель en_vectors_web_lg
Простая и эффективная сериализация
import spacy from spacy.tokens import Doc from spacy.vocab import Vocab nlp = spacy.load("en_core_web_sm") customer_feedback = open("customer_feedback_627.txt").read() doc = nlp(customer_feedback) doc.to_disk("/tmp/customer_feedback_627.bin") new_doc = Doc(Vocab()).from_disk("/tmp/customer_feedback_627.bin")
Соответствие текста правилам токенов
import spacy from spacy.matcher import Matcher nlp = spacy.load("en_core_web_sm") matcher = Matcher(nlp.vocab) def set_sentiment(matcher, doc, i, matches): doc.sentiment += 0.1 pattern1 = [{"ORTH": "Google"}, {"ORTH": "I"}, {"ORTH": "/"}, {"ORTH": "O"}] pattern2 = [[{"ORTH": emoji, "OP": "+"}] for emoji in ["😀", "😂", "🤣", "😍"]] matcher.add("GoogleIO", None, pattern1) # Match "Google I/O" or "Google i/o" matcher.add("HAPPY", set_sentiment, *pattern2) # Match one or more happy emoji doc = nlp("A text about Google I/O 😀😀") matches = matcher(doc) for match_id, start, end in matches: string_id = nlp.vocab.strings[match_id] span = doc[start:end] print(string_id, span.text) print("Sentiment", doc.sentiment)
GoogleIO Google I/O HAPPY 😀 HAPPY 😀😀 HAPPY 😀 Sentiment 0.30000001192092896
Обработка потоков с мини-синхронизацией
texts = ["One document.", "...", "Lots of documents"] # .pipe streams input, and produces streaming output iter_texts = (texts[i % 3] for i in range(100000000)) for i, doc in enumerate(nlp.pipe(iter_texts, batch_size=50)): assert doc.is_parsed if i == 100: break
Получение синтаксических зависимостей
import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("When Sebastian Thrun started working on self-driving cars at Google " "in 2007, few people outside of the company took him seriously.") dep_labels = [] for token in doc: while token.head != token: dep_labels.append(token.dep_) token = token.head print(dep_labels) RUN
['advmod', 'advcl', 'compound', 'nsubj', 'advcl', 'nsubj', 'advcl', 'advcl', 'xcomp', 'advcl', 'prep', 'xcomp', 'advcl', 'npadvmod', 'amod', 'pobj', 'prep', 'xcomp', 'advcl', 'punct', 'amod', 'pobj', 'prep', 'xcomp', 'advcl', 'amod', 'pobj', 'prep', 'xcomp', 'advcl', 'pobj', 'prep', 'xcomp', 'advcl', 'prep', 'xcomp', 'advcl', 'pobj', 'prep', 'xcomp', 'advcl', 'prep', 'xcomp', 'advcl', 'pobj', 'prep', 'xcomp', 'advcl', 'punct', 'amod', 'nsubj', 'nsubj', 'advmod', 'nsubj', 'prep', 'advmod', 'nsubj', 'det', 'pobj', 'prep', 'advmod', 'nsubj', 'pobj', 'prep', 'advmod', 'nsubj', 'dobj', 'advmod', 'punct']
Экспорт в массивы numpy
import spacy from spacy.attrs import ORTH, LIKE_URL nlp = spacy.load("en_core_web_sm") doc = nlp("Check out https://spacy.io") for token in doc: print(token.text, token.orth, token.like_url) attr_ids = [ORTH, LIKE_URL] doc_array = doc.to_array(attr_ids) print(doc_array.shape) print(len(doc), len(attr_ids)) assert doc[0].orth == doc_array[0, 0] assert doc[1].orth == doc_array[1, 0] assert doc[0].like_url == doc_array[0, 1] assert list(doc_array[:, 1]) == [t.like_url for t in doc] print(list(doc_array[:, 1]))
Check 8104846059040039827 False out 1696981056005371314 False https://spacy.io 17142293684782158888 True (3, 2) 3 2 [0, 0, 1]
Вычисление встроенной разметки исходной строки
import spacy def put_spans_around_tokens(doc): """Here, we're building a custom "syntax highlighter" for part-of-speech tags and dependencies. We put each token in a span element, with the appropriate classes computed. All whitespace is preserved, outside of the spans. (Of course, HTML will only display multiple whitespace if enabled – but the point is, no information is lost and you can calculate what you need, e.g. <br />, <p> etc.) """ output = [] html = '<span class="{classes}">{word}</span>{space}' for token in doc: if token.is_space: output.append(token.text) else: classes = "pos-{} dep-{}".format(token.pos_, token.dep_) output.append(html.format(classes=classes, word=token.text, space=token.whitespace_)) string = "".join(output) string = string.replace("\n", "") string = string.replace("\t", " ") return "<pre>{}</pre>".format(string) nlp = spacy.load("en_core_web_sm") doc = nlp("This is a test.\n\nHello world.") html = put_spans_around_tokens(doc) print(html)
<pre><span class="pos-DET dep-nsubj">This</span> <span class="pos-AUX dep-ROOT">is</span> <span class="pos-DET dep-det">a</span> <span class="pos-NOUN dep-attr">test</span><span class="pos-PUNCT dep-punct">.</span><span class="pos-INTJ dep-intj">Hello</span> <span class="pos-NOUN dep-ROOT">world</span><span class="pos-PUNCT dep-punct">.</span></pre>
Архитектура
Центральными структурами данных в spaCy являются Doc и Vocab. Объекту Doc принадлежит последовательность токенов и все их аннотации. Объект Vocab владеет набором справочных таблиц, которые делают общую информацию доступной для всех документов. Благодаря централизации строк, векторов слов и лексических атрибутов мы избегаем хранения нескольких копий этих данных. Это экономит память и обеспечивает единый источник правды.
Текстовые аннотации также предназначены для использования единственного источника истины: объект Doc владеет данными, а Span и Token — это представления, которые указывают на него. Объект Doc создается Tokenizer, а затем изменяется на месте компонентами конвейера. Объект Language координирует эти компоненты. Он берет необработанный текст и отправляет его по конвейеру, возвращая аннотированный документ. Он также управляет обучением и сериализацией.
Контейнерные объекты
NAME | DESCRIPTION |
---|---|
Doc | Контейнер для доступа к лингвистическим аннотациям. |
Span | Фрагмент объекта Doc. |
Token | Отдельный токен — то есть слово, знак препинания, пробел и т. д. |
Lexeme | Запись в словарном запасе. Это словесный тип без контекста, в отличие от словесной лексемы. Поэтому в нем нет тега части речи, анализа зависимостей и т. д. |
Конвейер обработки
NAME | DESCRIPTION |
---|---|
Language | Конвейер обработки текста. Обычно вы загружаете это один раз для каждого процесса как nlp и передаете экземпляр всему приложению. |
Tokenizer | Сегментируйте текст и создавайте объекты Doc с обнаруженными границами сегмента. |
Lemmatizer | Определение основных форм слов. |
Morphology | Назначайте лингвистические функции, такие как леммы, падеж существительного, время глагола и т. д., На основе слова и его тега части речи. |
Tagger | Добавляйте аннотации к тегам части речи на объектах Doc. |
DependencyParser | Аннотируйте синтаксические зависимости для объектов Doc. |
EntityRecognizer | Аннотируйте именованные объекты, например лиц или продуктов на объектах Doc. |
TextCategorizer | Назначьте категории или метки объектам документа. |
Matcher | Сопоставление последовательностей токенов на основе шаблонных правил аналогично регулярным выражениям. |
PhraseMatcher | Сопоставьте последовательности токенов на основе фраз. |
EntityRuler | Добавьте в документ интервалы сущностей, используя правила на основе токенов или точное совпадение фраз. |
Sentencizer | Реализуйте настраиваемую логику определения границ предложения, которая не требует синтаксического анализа зависимостей. |
Other functions | Автоматически применять что-то к документу, например объединять промежутки токенов. |
Другие классы
NAME | DESCRIPTION |
---|---|
Vocab | Таблица поиска словаря, которая позволяет вам получить доступ к объектам Lexeme. |
StringStore | Сопоставьте строки с хэш-значениями и обратно. |
Vectors | Класс-контейнер для векторных данных с строковым ключом. |
GoldParse | Сборник обучающих аннотаций. |
GoldCorpus | Аннотированный корпус с использованием формата файла JSON. Управляет аннотациями для тегов, синтаксического анализа зависимостей и NER. |
Сообщество и FAQ
Мы очень рады, что сообщество spaCy растет и включает в себя людей из самых разных сфер — компьютерной лингвистики, науки о данных, глубокого обучения, исследований и т. д. Если вы хотите принять участие, ниже приведены ответы на самые важные вопросы и ресурсы для дальнейшего чтения.
Помогите, мой код не работает!
Ошибки — отстой, и мы делаем все возможное, чтобы постоянно улучшать тесты и исправлять ошибки как можно скорее. Прежде чем отправить сообщение о проблеме, выполните быстрый поиск и проверьте, не сообщалось ли уже о проблеме. Если у вас возникли проблемы с установкой или загрузкой, обязательно ознакомьтесь с руководством по устранению неполадок. Помощь по spaCy доступна на следующих платформах:
- Stack Overflow: вопросы по использованию и все, что связано с проблемами с вашим конкретным кодом. Сообщество Stack Overflow намного больше нашего, поэтому, если вашу проблему смогут решить другие, вы получите помощь гораздо быстрее.
- Gitter chat: общее обсуждение spaCy, встречи с другими членами сообщества и обмен советами, приемами и передовым опытом.
- GitHub issue tracker: отчеты об ошибках и предложения по улучшению, то есть все, что, скорее всего, вызвано ошибкой spaCy. Это также включает проблемы с моделями, помимо статистических неточностей, например шаблоны, указывающие на ошибку.
Как я могу внести свой вклад в spaCy?
Вам не нужно быть экспертом по NLP или специалистом по Python, чтобы внести свой вклад, и мы будем рады помочь вам начать работу. Если вы новичок в spaCy, хорошее место для начала — это ярлык «help wanted (easy)
» на GitHub, который мы используем для того, чтобы отмечать ошибки и запросы функций, которые просты и автономны. Мы также ценим вклад в документацию — будь то исправление опечатки, улучшение примера или добавление дополнительных пояснений. Внизу каждой страницы вы найдете ссылку «Suggest edits», которая указывает на источник.
Другой способ принять участие — помочь нам улучшить языковые данные, особенно если вы говорите на одном из языков, которые в настоящее время поддерживаются в альфа-версии. Даже добавление простых исключений токенизатора, стоп-слов или данных лемматизатора может иметь большое значение. Это также упростит нам создание статистической модели языка в будущем. Также очень полезно отправить тест, который документирует ошибку или проблему с производительностью либо охватывает функции, которые особенно важны для вашего приложения. Таким образом, вы также убедитесь, что мы случайно не введем регрессии в те части библиотеки, которые вам важны.
Я создал что-то крутое с помощью spaCy — как я могу рассказать об этом?
Во-первых, поздравляем — мы хотели бы это проверить! Когда вы публикуете свой проект в Twitter, не забудьте отметить @spacy_io, чтобы мы не пропустили его. Если вы думаете, что ваш проект подходит для SpaCy Universe, не стесняйтесь отправить ссылку на него нам! Учебники также невероятно ценны для других пользователей. Поэтому мы настоятельно рекомендуем писать о своем опыте или делиться своим кодом и некоторыми советами и приемами в своем блоге. Поскольку наш веб-сайт имеет открытый исходный код, вы можете добавить свой проект или руководство, сделав pull request на GitHub.