Pull to refresh

Сравнение распознавания сущностей русского языка в spaCy 2 и spaCy 3

В 2020 году для нового проекта мне потребовалось выбирать из текста названия компаний, имена людей, названия городов и т.п. По результатам гугления выяснилось, что речь идёт об “извлечении именованных сущностей” из текста (named entity recognition, NER). Для решения такой задачи существуют Python-библиотеки: nltk (10k звёзд), DeepPavlov (5k звёзд) и др. Но чаще всего встречался spaCy (20k звёзд). Сам spaCy на тот момент (v.2) не поддерживал русского языка из коробки, но к нему можно было подключить соответствующую модель через пакет Stanza (5k звёзд). Для справки, Stanza разрабатывается группой из Стэнфорда (The Stanford NLP Group). Ещё один способ подключения русского языка – использовать модель из пакетов natasha при помощи прослойки natasha-spacy (разработчик – Александр Кукушкин). Однако популярность у неё пониже, чем у Stanza.

В начале 2021 года вышел spaCy v.3. В нём появилась поддержка новых языков, включая русский. Причём, как я понял, законтрибутил его разработчик natasha. Есть три модели, отличающиеся размерами: ru_core_news_lg, ru_core_news_md, ru_core_news_sm. Вместе со Stanza – 5 моделей для тестирования.

# spaCy 2.3.7 (stanza)

import stanza
from spacy_stanza import StanzaLanguage
import pandas as pd
import datetime

# Засекаем начало работы
start_ts = datetime.datetime.now().timestamp()

# stanza.download('ru')

# Подключаем stanza
snlp = stanza.Pipeline(lang='ru')
nlp = StanzaLanguage(snlp)

# Загружаем подготовленные новости
df = pd.read_csv('news.csv')
# Сюда будем складывать распознанные сущности
df2 = pd.DataFrame(columns=['id', 'entities'])

i = 0
for doc in nlp.pipe(df.text):
    row_id = df.iloc[i]['id']
    row_title = df.iloc[i]['title']
    print('Document:', i, row_title)
    entities = []
    for ent in doc.ents:
        entities.append((ent.text, ent.label_))
    df2.loc[i] = {'id': row_id, 'entities': entities}
    
    # Сохраняемся каждые 10 новостей и в конце
    if (i % 10 == 0) or (i == len(df) - 1):
        df2.to_csv('entities.csv', index=False)
    i+=1

end_ts = datetime.datetime.now().timestamp()
print('Time, secs:', end_ts - start_ts)
# spaCy 3.0.6 (stanza)

-snlp = stanza.Pipeline(lang='ru')
-nlp = StanzaLanguage(snlp)
+nlp = spacy_stanza.load_pipeline('ru')
# spaCy 3.0.6

-snlp = stanza.Pipeline(lang='ru')
-nlp = StanzaLanguage(snlp)
+nlp = spacy.load('ru_core_news_lg')

Проходимся алгоритмами по 1000 новостей.

Среднее время работы:

v.2 (stanza)

v.3 (stanza)

v.3 lg

v.3 md

v.3 sm

63.2 мин.

58.5 мин.

3.4 мин.

3.3 мин.

3.5 мин.

Сразу замечаю, что spaCy обеих версий со Stanza выдаёт одинаковый результат по распознаванию. Ещё из таблицы видно, что алгоритмы со Stanza работают сильно дольше. Возможно, Stanza распознаёт больше сущностей и точнее? Решил изучить поглубже: взял 10 новостей разметил вручную и сравнил с алгоритмом. Да, тест на 10 новостях может показаться не показательным. Скорее всего так и есть. Но даже он занял день ручной работы.

По результатам, алгоритмы не всегда правильно распознали сущности и не все. Например:

Ручная разметка

Microsoft SQL Server

Windows 10

МЧС России

v.2.3.7 (stanza)

Microsoft SQL Server

Windows

МЧС России

v.3.0.6 lg

Microsoft

 

МЧС, России (две сущности)

v.3.0.6 md

Microsoft SQL Server

 

МЧС, России (две сущности)

v.3.0.6 sm

Microsoft

 

МЧС, России (две сущности)

 

Ошибки

Пропуски

v.2.3.7 (stanza)

4,95%

41,94%

v.3.0.6 lg

1,57%

26,65%

v.3.0.6 md

2,05%

27,17%

v.3.0.6 sm

1,39%

28,55%

Заметил, что:

  • spaCy со Stanza работает сильно дольше, но столь же большого различия в качестве работы я не заметил

  • точность распознавания зависит от текста: простой чёткий текст – точность выше

  • SpaCy 3 с родными моделями часто распознают сущности одинаково

  • есть ситуации, когда модели дополняют друг друга (одна нашла то, что не нашли другие)

  • есть ситуации, когда сам не знаешь, кто правее: ты или алгоритм

Выводы: если стоит задача получить статистическую информацию по большому числу текстов, я бы посмотрел в сторону spaCy 3 + ru_core_news_lg. Если задача, из представленных алгоритмов со стандартными моделями достигнуть высокой точности, потребуются эвристики и модерирование.

P.S.: Дообучать модели я не пробовал – априори не знаю, какой бы это принесло результат.

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.