spaCy 101: все, что вам нужно знать. Часть 2

Spread the love

Перевод официальной документации: 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 координирует эти компоненты. Он берет необработанный текст и отправляет его по конвейеру, возвращая аннотированный документ. Он также управляет обучением и сериализацией.

Контейнерные объекты

NAMEDESCRIPTION
DocКонтейнер для доступа к лингвистическим аннотациям.
SpanФрагмент объекта Doc.
TokenОтдельный токен – то есть слово, знак препинания, пробел и т. д.
LexemeЗапись в словарном запасе. Это словесный тип без контекста, в отличие от словесной лексемы. Поэтому в нем нет тега части речи, анализа зависимостей и т. д.

Конвейер обработки

NAMEDESCRIPTION
LanguageКонвейер обработки текста. Обычно вы загружаете это один раз для каждого процесса как nlp и передаете экземпляр всему приложению.
TokenizerСегментируйте текст и создавайте объекты Doc с обнаруженными границами сегмента.
LemmatizerОпределение основных форм слов.
MorphologyНазначайте лингвистические функции, такие как леммы, падеж существительного, время глагола и т. д., На основе слова и его тега части речи.
TaggerДобавляйте аннотации к тегам части речи на объектах Doc.
DependencyParserАннотируйте синтаксические зависимости для объектов Doc.
EntityRecognizerАннотируйте именованные объекты, например лиц или продуктов на объектах Doc.
TextCategorizerНазначьте категории или метки объектам документа.
MatcherСопоставление последовательностей токенов на основе шаблонных правил аналогично регулярным выражениям.
PhraseMatcherСопоставьте последовательности токенов на основе фраз.
EntityRulerДобавьте в документ интервалы сущностей, используя правила на основе токенов или точное совпадение фраз.
SentencizerРеализуйте настраиваемую логику определения границ предложения, которая не требует синтаксического анализа зависимостей.
Other functionsАвтоматически применять что-то к документу, например объединять промежутки токенов.

Другие классы

NAMEDESCRIPTION
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.

Была ли вам полезна эта статья?
[6 / 5]

Spread the love
Подписаться
Уведомление о
guest
0 Комментарий
Inline Feedbacks
View all comments